]> err.no Git - sope/blob - sope-gdl1/GDLAccess/EOAdaptor.m
fixed bug in GDL adaptor lookup
[sope] / sope-gdl1 / GDLAccess / EOAdaptor.m
1 /* 
2    EOAttributeOrdering.m
3
4    Copyright (C) 1996 Free Software Foundation, Inc.
5
6    Author: Ovidiu Predescu <ovidiu@bx.logicnet.ro>
7    Date: 1996
8
9    This file is part of the GNUstep Database Library.
10
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.
15
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.
20
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.
25 */
26
27 #include "EOAdaptor.h"
28 #include "EOAdaptorChannel.h"
29 #include "EOAdaptorContext.h"
30 #include "EOAttribute.h"
31 #include "EOFExceptions.h"
32 #include "EOModel.h"
33 #include "EOSQLExpression.h"
34 #include "common.h"
35
36 @implementation EOAdaptor
37
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]);
43     id       adaptor;
44
45     adaptor = adaptorClass
46         ? AUTORELEASE([[adaptorClass alloc] initWithName:adaptorName])
47         : [self adaptorWithName:adaptorName];
48     
49     [adaptor setModel:_model];
50     return adaptor;
51 }
52
53 + (NSArray *)adaptorSearchPathes {
54   // TODO: add support for Cocoa
55   static NSArray *searchPathes = nil;
56   NSDictionary   *env;
57   NSMutableArray *ma;
58   id             tmp;
59
60   if (searchPathes != nil) return searchPathes;
61
62   env = [[NSProcessInfo processInfo] environment];
63   ma  = [NSMutableArray arrayWithCapacity:8];
64   
65   if ((tmp = [env objectForKey:@"GNUSTEP_PATHPREFIX_LIST"]) == nil)
66     tmp = [env objectForKey:@"GNUSTEP_PATHLIST"];
67   tmp = [tmp componentsSeparatedByString:@":"];
68   if ([tmp count] > 0) {
69     NSEnumerator *e;
70     
71     e = [tmp objectEnumerator];
72     while ((tmp = [e nextObject])) {
73       if (![tmp hasSuffix:@"/"]) tmp = [tmp stringByAppendingString:@"/"];
74       
75       tmp = [tmp stringByAppendingFormat:@"Library/GDLAdaptors-%i.%i",
76                    GDL_MAJOR_VERSION, GDL_MINOR_VERSION];
77       
78       if ([ma containsObject:tmp] || tmp == nil) continue;
79       [ma addObject:tmp];
80     }
81   }
82   
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]];
87   
88   searchPathes = [ma copy];
89   if ([searchPathes count] == 0)
90     NSLog(@"%s: empty library search path !", __PRETTY_FUNCTION__);
91   return searchPathes;
92 }
93
94 + (id)adaptorWithName:(NSString *)adaptorName {
95   int      i, count;
96   NSBundle *bundle;
97   NSString *adaptorBundlePath = nil;
98   Class    adaptorClass       = Nil;
99   
100   bundle = [NSBundle mainBundle];
101     
102   /* Check error */
103   if ((adaptorName == nil) || [adaptorName isEqual:@""])
104     return nil;
105   
106   /* Look in application bundle */
107   bundle = [NSBundle mainBundle];
108   adaptorBundlePath =
109     [bundle pathForResource:adaptorName ofType:@"gdladaptor"];
110   
111   /* Look in standard paths */
112   if (adaptorBundlePath == nil) {
113     NSFileManager *fm;
114     NSString *dirname;
115     NSArray  *paths;
116       
117     fm      = [NSFileManager defaultManager];
118     paths   = [self adaptorSearchPathes];
119     dirname = [adaptorName stringByAppendingPathExtension:@"gdladaptor"];
120       
121     /* Loop through the paths and check each one */
122     for (i = 0, count = [paths count]; i < count; i++) {
123       NSString *p;
124       BOOL isDir;
125         
126       p = [[paths objectAtIndex:i] stringByAppendingPathComponent:dirname];
127       if (![fm fileExistsAtPath:p isDirectory:&isDir])
128         continue;
129       if (!isDir)
130         continue;
131         
132       adaptorBundlePath = p;
133       break;
134     }
135   }
136     
137   /* Make adaptor bundle */
138   bundle = adaptorBundlePath
139     ? [NSBundle bundleWithPath:adaptorBundlePath]
140     : nil;
141     
142   /* Check bundle */
143   if (bundle == nil) {
144     NSLog(@"EOAdaptor: cannot find adaptor bundle: '%@'", adaptorName);
145 #if 0
146     [[[[CannotFindAdaptorBundleException alloc]
147         initWithFormat:@"Cannot find adaptor bundle '%@'",
148         adaptorName] autorelease] raise];
149 #endif
150     return nil;
151   }
152
153   /* load bundle */
154
155   if (![bundle load]) {
156     NSLog(@"Cannot load adaptor bundle '%@'", adaptorName);
157 #if 1
158     [[[[InvalidAdaptorBundleException alloc]
159         initWithFormat:@"Cannot load adaptor bundle '%@'",
160         adaptorName] autorelease] raise];
161 #endif
162     return nil;
163   }
164     
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. */
171     
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]);
177       
178     [[[InvalidAdaptorBundleException alloc]
179        initWithFormat:@"The adaptor bundle '%@' doesn't contain "
180        @"a principal class (infoDict=%@)",
181        adaptorName, [bundle infoDictionary]]
182       raise];
183   }
184   return AUTORELEASE([[adaptorClass alloc] initWithName:adaptorName]);
185 }
186
187 - (id)initWithName:(NSString*)_name {
188     ASSIGN(self->name, _name);
189     self->contexts = [[NSMutableArray allocWithZone:[self zone]] init];
190     return self;
191 }
192
193 - (void)dealloc {
194     RELEASE(self->model);
195     RELEASE(self->name);
196     RELEASE(self->connectionDictionary);
197     RELEASE(self->pkeyGeneratorDictionary);
198     RELEASE(self->contexts);
199     [super dealloc];
200 }
201
202 /* accessors */
203
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!"];
209   }
210   ASSIGN(self->connectionDictionary, _dictionary);
211   [self->model setConnectionDictionary:_dictionary];
212 }
213 - (NSDictionary *)connectionDictionary {
214   return self->connectionDictionary;
215 }
216 - (BOOL)hasValidConnectionDictionary {
217   return NO;
218 }
219
220 - (EOAdaptorContext*)createAdaptorContext {
221   return AUTORELEASE([[[self adaptorContextClass] alloc] 
222                              initWithAdaptor:self]);
223 }
224 - (NSArray *)contexts {
225   NSMutableArray *ma;
226   unsigned i, count;
227   
228   if ((count = [self->contexts count]) == 0)
229     return nil;
230
231   ma = [NSMutableArray arrayWithCapacity:count];
232   for (i = 0; i < count; i++)
233     [ma addObject:[[self->contexts objectAtIndex:i] nonretainedObjectValue]];
234   
235   return ma;
236 }
237
238 /* Setting pkey generation info */
239
240 - (void)setPkeyGeneratorDictionary:(NSDictionary*)aDictionary {
241   ASSIGN(self->pkeyGeneratorDictionary, aDictionary);
242   [self->model setPkeyGeneratorDictionary:aDictionary];
243 }
244 - (NSDictionary*)pkeyGeneratorDictionary {
245   return self->pkeyGeneratorDictionary;
246 }
247
248 // notifications
249
250 - (void)contextDidInit:aContext {
251     [self->contexts addObject:[NSValue valueWithNonretainedObject:aContext]];
252 }
253
254 - (void)contextWillDealloc:aContext {
255     int i;
256     
257     for (i = [contexts count]-1; i >= 0; i--) {
258         if ([[contexts objectAtIndex:i] nonretainedObjectValue] == aContext) {
259             [contexts removeObjectAtIndex:i];
260             break;
261         }
262     }
263 }
264
265 - (BOOL)hasOpenChannels {
266     int i;
267
268     for (i = [contexts count] - 1; i >= 0; i--) {
269         EOAdaptorContext* ctx = [[contexts objectAtIndex:i] 
270             nonretainedObjectValue];
271         if ([ctx hasOpenChannels])
272             return YES;
273     }
274     return NO;
275 }
276
277 - (id)formatAttribute:(EOAttribute *)_attribute {
278     return [_attribute expressionValueForContext:nil];
279 }
280
281 - (id)formatValue:(id)_value forAttribute:(EOAttribute *)attribute {
282   if (_value == nil) _value = [NSNull null];
283   return [_value expressionValueForContext:nil];
284 }
285
286 - (void)reportError:(NSString*)error {
287     if(delegateWillReportError) {
288         if([delegate adaptor:self willReportError:error] == NO)
289             return;
290     }
291     NSLog(@"%@ adaptor error: %@", name, error);
292 }
293
294 - (void)setDelegate:(id)_delegate {
295     self->delegate = _delegate;
296     self->delegateWillReportError
297         = [self->delegate respondsToSelector:
298                             @selector(adaptor:willReportError:)];
299 }
300
301 - (void)setModel:(EOModel *)_model {
302     ASSIGN(self->model, _model);
303     [self setConnectionDictionary:[_model connectionDictionary]];
304     [self setPkeyGeneratorDictionary:[_model pkeyGeneratorDictionary]];
305 }
306 - (EOModel *)model {
307     return self->model;
308 }
309
310 - (NSString *)name {
311     return self->name;
312 }
313
314 - (Class)expressionClass {
315   return [EOSQLExpression class];
316 }
317 - (Class)adaptorContextClass {
318   return [EOAdaptorContext class];
319 }
320 - (Class)adaptorChannelClass {
321   return [EOAdaptorChannel class];
322 }
323
324 - (BOOL)attributeAllowedInDistinctSelects:(EOAttribute *)_attr {
325   return YES;
326 }
327 - (BOOL)isValidQualifierType:(NSString*)typeName {
328   return NO;
329 }
330 - (id)delegate {
331   return self->delegate;
332 }
333
334 // description
335
336 - (NSString *)description {
337   return [NSString stringWithFormat:
338                      @"<%@[0x%08X]: name=%@ "
339                      @"model=%s connection-dict=%s>",
340                      NSStringFromClass([self class]), self,
341                      [self name],
342                      [self model] ? "yes" : "no",
343                      [self connectionDictionary] ? "yes" : "no"];
344 }
345
346 @end /* EOAdaptor */
347
348 @implementation EOAdaptor(EOF2Additions)
349
350 - (BOOL)canServiceModel:(EOModel *)_model {
351   return YES;
352 }
353
354 @end