4 Copyright (C) 1996 Free Software Foundation, Inc.
6 Author: Ovidiu Predescu <ovidiu@bx.logicnet.ro>
9 This file is part of the GNUstep Database Library.
11 This library is free software; you can redistribute it and/or
12 modify it under the terms of the GNU Library General Public
13 License as published by the Free Software Foundation; either
14 version 2 of the License, or (at your option) any later version.
16 This library is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 Library General Public License for more details.
21 You should have received a copy of the GNU Library General Public
22 License along with this library; see the file COPYING.LIB.
23 If not, write to the Free Software Foundation,
24 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
27 #include "EOAdaptor.h"
28 #include "EOAdaptorChannel.h"
29 #include "EOAdaptorContext.h"
30 #include "EOAttribute.h"
31 #include "EOFExceptions.h"
33 #include "EOSQLExpression.h"
36 @implementation EOAdaptor
38 + (id)adaptorWithModel:(EOModel*)_model {
39 /* Check first to see if the adaptor class exists in the running program
40 by testing the existence of [_model adaptorClassName]. */
41 NSString *adaptorName = [_model adaptorName];
42 Class adaptorClass = NSClassFromString([_model adaptorClassName]);
45 adaptor = adaptorClass
46 ? AUTORELEASE([[adaptorClass alloc] initWithName:adaptorName])
47 : [self adaptorWithName:adaptorName];
49 [adaptor setModel:_model];
53 + (NSArray *)adaptorSearchPathes {
54 // TODO: add support for Cocoa
55 static NSArray *searchPathes = nil;
60 if (searchPathes != nil) return searchPathes;
62 env = [[NSProcessInfo processInfo] environment];
63 ma = [NSMutableArray arrayWithCapacity:8];
65 if ((tmp = [env objectForKey:@"GNUSTEP_PATHPREFIX_LIST"]) == nil)
66 tmp = [env objectForKey:@"GNUSTEP_PATHLIST"];
67 tmp = [tmp componentsSeparatedByString:@":"];
68 if ([tmp count] > 0) {
71 e = [tmp objectEnumerator];
72 while ((tmp = [e nextObject])) {
73 tmp = [tmp stringByAppendingPathComponent:@"Library/GDLAdaptors-1.1"];
74 if ([ma containsObject:tmp]) continue;
78 [ma addObject:@"/usr/local/lib/sope-4.3/dbadaptors"];
79 [ma addObject:@"/usr/lib/sope-4.3/dbadaptors"];
81 searchPathes = [ma copy];
82 if ([searchPathes count] == 0)
83 NSLog(@"%s: empty library search path !", __PRETTY_FUNCTION__);
87 + (id)adaptorWithName:(NSString *)adaptorName {
90 NSString *adaptorBundlePath = nil;
91 Class adaptorClass = Nil;
93 bundle = [NSBundle mainBundle];
96 if ((adaptorName == nil) || [adaptorName isEqual:@""])
99 /* Look in application bundle */
100 bundle = [NSBundle mainBundle];
102 [bundle pathForResource:adaptorName ofType:@"gdladaptor"];
104 /* Look in standard paths */
105 if (adaptorBundlePath == nil) {
110 fm = [NSFileManager defaultManager];
111 paths = [self adaptorSearchPathes];
112 dirname = [adaptorName stringByAppendingPathExtension:@"gdladaptor"];
114 /* Loop through the paths and check each one */
115 for (i = 0, count = [paths count]; i < count; i++) {
119 p = [[paths objectAtIndex:i] stringByAppendingPathComponent:dirname];
120 if (![fm fileExistsAtPath:p isDirectory:&isDir])
125 adaptorBundlePath = p;
130 /* Make adaptor bundle */
131 bundle = adaptorBundlePath
132 ? [NSBundle bundleWithPath:adaptorBundlePath]
137 NSLog(@"Cannot find adaptor bundle '%@'", adaptorName);
139 [[[[CannotFindAdaptorBundleException alloc]
140 initWithFormat:@"Cannot find adaptor bundle '%@'",
141 adaptorName] autorelease] raise];
148 if (![bundle load]) {
149 NSLog(@"Cannot load adaptor bundle '%@'", adaptorName);
151 [[[[InvalidAdaptorBundleException alloc]
152 initWithFormat:@"Cannot load adaptor bundle '%@'",
153 adaptorName] autorelease] raise];
158 /* Get the adaptor bundle "infoDictionary", and pricipal class, ie. the
159 adaptor class. Other info about the adaptor should be put in the
160 bundle's "Info.plist" file (property list format - see NSBundle class
161 documentation for details about reserved keys in this dictionary
162 property list containing one entry whose key is adaptorClassName. It
163 identifies the actual adaptor class from the bundle. */
165 adaptorClass = [bundle principalClass];
166 if (adaptorClass == Nil) {
167 NSLog(@"The adaptor bundle '%@' at '%@' doesn't contain "
168 @"a principal class (infoDict=%@)",
169 adaptorName, [bundle bundlePath], [bundle infoDictionary]);
171 [[[InvalidAdaptorBundleException alloc]
172 initWithFormat:@"The adaptor bundle '%@' doesn't contain "
173 @"a principal class (infoDict=%@)",
174 adaptorName, [bundle infoDictionary]]
177 return AUTORELEASE([[adaptorClass alloc] initWithName:adaptorName]);
180 - (id)initWithName:(NSString*)_name {
181 ASSIGN(self->name, _name);
182 self->contexts = [[NSMutableArray allocWithZone:[self zone]] init];
187 RELEASE(self->model);
189 RELEASE(self->connectionDictionary);
190 RELEASE(self->pkeyGeneratorDictionary);
191 RELEASE(self->contexts);
197 - (void)setConnectionDictionary:(NSDictionary*)_dictionary {
198 if([self hasOpenChannels]) {
199 [NSException raise:NSInvalidArgumentException
200 format:@"Cannot set the connection dictionary "
201 @"while the adaptor is connected!"];
203 ASSIGN(self->connectionDictionary, _dictionary);
204 [self->model setConnectionDictionary:_dictionary];
206 - (NSDictionary *)connectionDictionary {
207 return self->connectionDictionary;
209 - (BOOL)hasValidConnectionDictionary {
213 - (EOAdaptorContext*)createAdaptorContext {
214 return AUTORELEASE([[[self adaptorContextClass] alloc]
215 initWithAdaptor:self]);
217 - (NSArray *)contexts {
221 if ((count = [self->contexts count]) == 0)
224 ma = [NSMutableArray arrayWithCapacity:count];
225 for (i = 0; i < count; i++)
226 [ma addObject:[[self->contexts objectAtIndex:i] nonretainedObjectValue]];
231 /* Setting pkey generation info */
233 - (void)setPkeyGeneratorDictionary:(NSDictionary*)aDictionary {
234 ASSIGN(self->pkeyGeneratorDictionary, aDictionary);
235 [self->model setPkeyGeneratorDictionary:aDictionary];
237 - (NSDictionary*)pkeyGeneratorDictionary {
238 return self->pkeyGeneratorDictionary;
243 - (void)contextDidInit:aContext {
244 [self->contexts addObject:[NSValue valueWithNonretainedObject:aContext]];
247 - (void)contextWillDealloc:aContext {
250 for (i = [contexts count]-1; i >= 0; i--) {
251 if ([[contexts objectAtIndex:i] nonretainedObjectValue] == aContext) {
252 [contexts removeObjectAtIndex:i];
258 - (BOOL)hasOpenChannels {
261 for (i = [contexts count] - 1; i >= 0; i--) {
262 EOAdaptorContext* ctx = [[contexts objectAtIndex:i]
263 nonretainedObjectValue];
264 if ([ctx hasOpenChannels])
270 - (id)formatAttribute:(EOAttribute *)_attribute {
271 return [_attribute expressionValueForContext:nil];
274 - (id)formatValue:(id)_value forAttribute:(EOAttribute *)attribute {
275 if (_value == nil) _value = [NSNull null];
276 return [_value expressionValueForContext:nil];
279 - (void)reportError:(NSString*)error {
280 if(delegateWillReportError) {
281 if([delegate adaptor:self willReportError:error] == NO)
284 NSLog(@"%@ adaptor error: %@", name, error);
287 - (void)setDelegate:(id)_delegate {
288 self->delegate = _delegate;
289 self->delegateWillReportError
290 = [self->delegate respondsToSelector:
291 @selector(adaptor:willReportError:)];
294 - (void)setModel:(EOModel *)_model {
295 ASSIGN(self->model, _model);
296 [self setConnectionDictionary:[_model connectionDictionary]];
297 [self setPkeyGeneratorDictionary:[_model pkeyGeneratorDictionary]];
307 - (Class)expressionClass {
308 return [EOSQLExpression class];
310 - (Class)adaptorContextClass {
311 return [EOAdaptorContext class];
313 - (Class)adaptorChannelClass {
314 return [EOAdaptorChannel class];
317 - (BOOL)attributeAllowedInDistinctSelects:(EOAttribute *)_attr {
320 - (BOOL)isValidQualifierType:(NSString*)typeName {
324 return self->delegate;
329 - (NSString *)description {
330 return [NSString stringWithFormat:
331 @"<%@[0x%08X]: name=%@ "
332 @"model=%s connection-dict=%s>",
333 NSStringFromClass([self class]), self,
335 [self model] ? "yes" : "no",
336 [self connectionDictionary] ? "yes" : "no"];
341 @implementation EOAdaptor(EOF2Additions)
343 - (BOOL)canServiceModel:(EOModel *)_model {