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 if (![tmp hasSuffix:@"/"]) tmp = [tmp stringByAppendingString:@"/"];
75 tmp = [tmp stringByAppendingFormat:@"Library/GDLAdaptors-%i.%i",
76 GDL_MAJOR_VERSION, GDL_MINOR_VERSION];
78 if ([ma containsObject:tmp] || tmp == nil) continue;
83 tmp = [NSString stringWithFormat:@"/lib/sope-%i.%i/dbadaptors",
84 SOPE_MAJOR_VERSION, SOPE_MINOR_VERSION];
85 [ma addObject:[@"/usr/local" stringByAppendingString:tmp]];
86 [ma addObject:[@"/usr" stringByAppendingString:tmp]];
88 searchPathes = [ma copy];
89 if ([searchPathes count] == 0)
90 NSLog(@"%s: empty library search path !", __PRETTY_FUNCTION__);
94 + (id)adaptorWithName:(NSString *)adaptorName {
97 NSString *adaptorBundlePath = nil;
98 Class adaptorClass = Nil;
100 bundle = [NSBundle mainBundle];
103 if ((adaptorName == nil) || [adaptorName isEqual:@""])
106 /* Look in application bundle */
107 bundle = [NSBundle mainBundle];
109 [bundle pathForResource:adaptorName ofType:@"gdladaptor"];
111 /* Look in standard paths */
112 if (adaptorBundlePath == nil) {
117 fm = [NSFileManager defaultManager];
118 paths = [self adaptorSearchPathes];
119 dirname = [adaptorName stringByAppendingPathExtension:@"gdladaptor"];
121 /* Loop through the paths and check each one */
122 for (i = 0, count = [paths count]; i < count; i++) {
126 p = [[paths objectAtIndex:i] stringByAppendingPathComponent:dirname];
127 if (![fm fileExistsAtPath:p isDirectory:&isDir])
132 adaptorBundlePath = p;
137 /* Make adaptor bundle */
138 bundle = adaptorBundlePath
139 ? [NSBundle bundleWithPath:adaptorBundlePath]
144 NSLog(@"EOAdaptor: cannot find adaptor bundle: '%@'", adaptorName);
146 [[[[CannotFindAdaptorBundleException alloc]
147 initWithFormat:@"Cannot find adaptor bundle '%@'",
148 adaptorName] autorelease] raise];
155 if (![bundle load]) {
156 NSLog(@"Cannot load adaptor bundle '%@'", adaptorName);
158 [[[[InvalidAdaptorBundleException alloc]
159 initWithFormat:@"Cannot load adaptor bundle '%@'",
160 adaptorName] autorelease] raise];
165 /* Get the adaptor bundle "infoDictionary", and pricipal class, ie. the
166 adaptor class. Other info about the adaptor should be put in the
167 bundle's "Info.plist" file (property list format - see NSBundle class
168 documentation for details about reserved keys in this dictionary
169 property list containing one entry whose key is adaptorClassName. It
170 identifies the actual adaptor class from the bundle. */
172 adaptorClass = [bundle principalClass];
173 if (adaptorClass == Nil) {
174 NSLog(@"The adaptor bundle '%@' at '%@' doesn't contain "
175 @"a principal class (infoDict=%@)",
176 adaptorName, [bundle bundlePath], [bundle infoDictionary]);
178 [[[InvalidAdaptorBundleException alloc]
179 initWithFormat:@"The adaptor bundle '%@' doesn't contain "
180 @"a principal class (infoDict=%@)",
181 adaptorName, [bundle infoDictionary]]
184 return AUTORELEASE([[adaptorClass alloc] initWithName:adaptorName]);
187 - (id)initWithName:(NSString*)_name {
188 ASSIGN(self->name, _name);
189 self->contexts = [[NSMutableArray allocWithZone:[self zone]] init];
194 RELEASE(self->model);
196 RELEASE(self->connectionDictionary);
197 RELEASE(self->pkeyGeneratorDictionary);
198 RELEASE(self->contexts);
204 - (void)setConnectionDictionary:(NSDictionary*)_dictionary {
205 if([self hasOpenChannels]) {
206 [NSException raise:NSInvalidArgumentException
207 format:@"Cannot set the connection dictionary "
208 @"while the adaptor is connected!"];
210 ASSIGN(self->connectionDictionary, _dictionary);
211 [self->model setConnectionDictionary:_dictionary];
213 - (NSDictionary *)connectionDictionary {
214 return self->connectionDictionary;
216 - (BOOL)hasValidConnectionDictionary {
220 - (EOAdaptorContext*)createAdaptorContext {
221 return AUTORELEASE([[[self adaptorContextClass] alloc]
222 initWithAdaptor:self]);
224 - (NSArray *)contexts {
228 if ((count = [self->contexts count]) == 0)
231 ma = [NSMutableArray arrayWithCapacity:count];
232 for (i = 0; i < count; i++)
233 [ma addObject:[[self->contexts objectAtIndex:i] nonretainedObjectValue]];
238 /* Setting pkey generation info */
240 - (void)setPkeyGeneratorDictionary:(NSDictionary*)aDictionary {
241 ASSIGN(self->pkeyGeneratorDictionary, aDictionary);
242 [self->model setPkeyGeneratorDictionary:aDictionary];
244 - (NSDictionary*)pkeyGeneratorDictionary {
245 return self->pkeyGeneratorDictionary;
250 - (void)contextDidInit:aContext {
251 [self->contexts addObject:[NSValue valueWithNonretainedObject:aContext]];
254 - (void)contextWillDealloc:aContext {
257 for (i = [contexts count]-1; i >= 0; i--) {
258 if ([[contexts objectAtIndex:i] nonretainedObjectValue] == aContext) {
259 [contexts removeObjectAtIndex:i];
265 - (BOOL)hasOpenChannels {
268 for (i = [contexts count] - 1; i >= 0; i--) {
269 EOAdaptorContext* ctx = [[contexts objectAtIndex:i]
270 nonretainedObjectValue];
271 if ([ctx hasOpenChannels])
277 - (id)formatAttribute:(EOAttribute *)_attribute {
278 return [_attribute expressionValueForContext:nil];
281 - (id)formatValue:(id)_value forAttribute:(EOAttribute *)attribute {
282 if (_value == nil) _value = [NSNull null];
283 return [_value expressionValueForContext:nil];
286 - (void)reportError:(NSString*)error {
287 if(delegateWillReportError) {
288 if([delegate adaptor:self willReportError:error] == NO)
291 NSLog(@"%@ adaptor error: %@", name, error);
294 - (void)setDelegate:(id)_delegate {
295 self->delegate = _delegate;
296 self->delegateWillReportError
297 = [self->delegate respondsToSelector:
298 @selector(adaptor:willReportError:)];
301 - (void)setModel:(EOModel *)_model {
302 ASSIGN(self->model, _model);
303 [self setConnectionDictionary:[_model connectionDictionary]];
304 [self setPkeyGeneratorDictionary:[_model pkeyGeneratorDictionary]];
314 - (Class)expressionClass {
315 return [EOSQLExpression class];
317 - (Class)adaptorContextClass {
318 return [EOAdaptorContext class];
320 - (Class)adaptorChannelClass {
321 return [EOAdaptorChannel class];
324 - (BOOL)attributeAllowedInDistinctSelects:(EOAttribute *)_attr {
327 - (BOOL)isValidQualifierType:(NSString*)typeName {
331 return self->delegate;
336 - (NSString *)description {
337 return [NSString stringWithFormat:
338 @"<%@[0x%08X]: name=%@ "
339 @"model=%s connection-dict=%s>",
340 NSStringFromClass([self class]), self,
342 [self model] ? "yes" : "no",
343 [self connectionDictionary] ? "yes" : "no"];
348 @implementation EOAdaptor(EOF2Additions)
350 - (BOOL)canServiceModel:(EOModel *)_model {