]> err.no Git - sope/blob - Recycler/SxComponents/SxComponentRegistry.m
use %p for pointer formats
[sope] / Recycler / SxComponents / SxComponentRegistry.m
1 /*
2   Copyright (C) 2000-2003 SKYRIX Software AG
3
4   This file is part of OGo
5
6   OGo is free software; you can redistribute it and/or modify it under
7   the terms of the GNU Lesser General Public License as published by the
8   Free Software Foundation; either version 2, or (at your option) any
9   later version.
10
11   OGo is distributed in the hope that it will be useful, but WITHOUT ANY
12   WARRANTY; without even the implied warranty of MERCHANTABILITY or
13   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
14   License for more details.
15
16   You should have received a copy of the GNU Lesser General Public
17   License along with OGo; see the file COPYING.  If not, write to the
18   Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
19   02111-1307, USA.
20 */
21 // $Id$
22
23 #include "SxComponentRegistry.h"
24 #include "SxComponent.h"
25 #include "common.h"
26
27 @implementation SxComponentRegistry
28
29 static SxComponentRegistry *defreg = nil;
30
31 + (void)initialize {
32   static BOOL didInit = NO;
33   if (!didInit) {
34     NSDictionary *defs;
35     didInit = YES;
36
37     defs = [NSDictionary dictionaryWithObjectsAndKeys:
38                          [NSArray arrayWithObject:@"SxXmlRpcRegBackend"],
39                          @"SxComponentRegistryBackends",
40                          [NSNumber numberWithInt:3],
41                          @"SxComponentRetriesOnError",
42                          [NSNumber numberWithInt:5],
43                          @"SxComponentRetryTime",
44                          nil];
45     [[NSUserDefaults standardUserDefaults] registerDefaults:defs];
46   }
47 }
48 + (NSArray *)defaultRegistryBackends {
49   return [[NSUserDefaults standardUserDefaults]
50                           arrayForKey:@"SxComponentRegistryBackends"];
51 }
52
53 + (id)defaultComponentRegistry {
54   if (defreg == nil) {
55     // THREAD
56     defreg = [[SxComponentRegistry alloc] init];
57   }
58   return defreg;
59 }
60
61 - (id)initWithBackends:(NSArray *)_backends { /* designated initializer */
62   self->credentials = [[NSMutableArray alloc] initWithCapacity:4];
63   self->backends    = [_backends shallowCopy];
64   self->listMethodsCache = [[NSMutableDictionary alloc] initWithCapacity:64];
65   self->methodSignatureCache =
66     [[NSMutableDictionary alloc] initWithCapacity:256];
67   return self;
68 }
69
70 - (id)initWithBackendClassNames:(NSArray *)_beClasses {
71   NSEnumerator   *e;
72   NSString       *beClassName;
73   NSMutableArray *bes;
74   
75   /* load backends */
76
77   bes = [NSMutableArray arrayWithCapacity:[_beClasses count]];
78   e   = [_beClasses objectEnumerator];
79   while ((beClassName = [e nextObject])) {
80     Class beClass;
81     id be;
82     
83     if ((beClass = NSClassFromString(beClassName)) == Nil) {
84       [self logWithFormat:@"did not find backend class '%@'", beClassName];
85       continue;
86     }
87     
88     if ((be = [[beClass alloc] init])) {
89       [bes addObject:be];
90       RELEASE(be);
91     }
92     else {
93       [self logWithFormat:@"backend of class %@ wasn't initialized ...",
94               NSStringFromClass(beClass)];
95     }
96   }
97   
98   return [self initWithBackends:bes];
99 }
100 - (id)init {
101   return [self initWithBackendClassNames:
102                  [[self class] defaultRegistryBackends]];
103 }
104
105 - (void)dealloc {
106   RELEASE(self->methodSignatureCache);
107   RELEASE(self->listMethodsCache);
108   RELEASE(self->backends);
109   RELEASE(self->credentials);
110   
111   if (self->lookupCache) {
112     NSFreeMapTable(self->lookupCache);
113     self->lookupCache = NULL;
114   }
115   [super dealloc];
116 }
117
118 /* callbacks */
119
120 - (void)_componentWillDealloc:(SxComponent *)_c {
121   if (self->lookupCache)
122     NSMapRemove(self->lookupCache, [_c componentName]);
123 }
124
125 - (void)_removeComponentFromLookupCache:(NSString *)_cname {
126   if (self->lookupCache)
127     NSMapRemove(self->lookupCache, _cname);
128 }
129
130 /* getting components */
131
132 - (id<NSObject,SxComponent>)getComponent:(NSString *)_namespace {
133   NSAutoreleasePool *pool;
134   SxComponent *c;
135   NSEnumerator *e;
136   id           backend;
137   
138   if (self->lookupCache == NULL) {
139     self->lookupCache = NSCreateMapTable(NSObjectMapKeyCallBacks,
140                                          NSNonRetainedObjectMapValueCallBacks,
141                                          64);
142   }
143   
144   if ((c = NSMapGet(self->lookupCache, _namespace))) {
145     return c;
146   }
147   
148   pool = [[NSAutoreleasePool alloc] init];
149
150   e = [self->backends objectEnumerator];
151
152   while((backend = [e nextObject])) {
153     if ([backend registry:self canHandleNamespace:_namespace]) {
154       c = [backend registry:self getComponent:_namespace];
155       break;
156     }
157   }
158
159   if (c) NSMapInsert(self->lookupCache, [c componentName], c);
160   
161   RETAIN(c);
162   RELEASE(pool);
163
164   return AUTORELEASE(c);
165 }
166
167 /* returns the names of the available components */
168
169 - (NSArray *)listComponents:(NSString *)_path {
170   NSMutableArray *results;
171   NSEnumerator *e;
172   id backend;
173   
174   results = nil;
175   e = [self->backends objectEnumerator];
176   while ((backend = [e nextObject])) {
177     NSArray *r;
178     
179     if ((r = [backend registry:self listComponents:_path])) {
180       if (results == nil)
181         results = [NSMutableArray arrayWithCapacity:128];
182       [results addObjectsFromArray:r];
183     }
184   }
185   return results;
186 }
187 - (NSArray *)listComponents {
188   return [self listComponents:nil];
189 }
190
191 - (NSArray *)listMethods:(NSString *)_component {
192   NSEnumerator *e;
193   id           backend;
194   NSArray      *result;
195
196   if ([_component length] == 0)
197     return nil;
198
199   /* check cache */
200   if ((result = [self->listMethodsCache objectForKey:_component]))
201     return AUTORELEASE(RETAIN(result));
202
203   /* let backends make reflection */
204   e = [self->backends objectEnumerator];
205   while((backend = [e nextObject])) {
206     if ([backend registry:self canHandleNamespace:_component]) {
207       result = [backend registry:self listMethods:_component];
208       break;
209     }
210   }
211
212   /* store in cache */
213   if (result)
214     [self->listMethodsCache setObject:result forKey:_component];
215   
216   return result;
217 }
218
219 - (NSArray *)methodSignature:(NSString *)_component method:(NSString *)_name {
220   NSEnumerator *e;
221   id           backend;
222   NSString     *key;
223   NSArray      *result;
224
225   /* check cache */
226   key = [NSString stringWithFormat:@"%@\n%@", _name, _component];
227   if ((result = [self->methodSignatureCache objectForKey:key]))
228     return AUTORELEASE(RETAIN(result));
229
230   /* perform operation */
231   e = [self->backends objectEnumerator];
232   while((backend = [e nextObject])) {
233     if ([backend registry:self canHandleNamespace:_component]) {
234       result = [backend registry:self methodSignature:_component method:_name];
235       break;
236     }
237   }
238
239   /* store in cache */
240   if (result)
241     [self->methodSignatureCache setObject:result forKey:key];
242   
243   return result;
244 }
245
246 - (NSString *)methodHelp:(NSString *)_component method:(NSString *)_name {
247   NSEnumerator *e;
248   id           backend;
249
250   e = [self->backends objectEnumerator];
251   
252   while((backend = [e nextObject])) {
253     if ([backend registry:self canHandleNamespace:_component]) {
254       return [backend registry:self methodHelp:_component method:_name];
255     }
256   }
257   return nil;
258 }
259
260 /* component registration */
261
262 - (BOOL)registerComponent:(SxComponent *)_component {
263   if (_component == nil) return YES;
264   return NO;
265 }
266 - (BOOL)unregisterComponent:(SxComponent *)_component {
267   if (_component == nil) return YES;
268   return NO;
269 }
270
271 /* caching */
272
273 - (SxComponent *)getCachedComponent:(NSString *)_namespace {
274   if (self->lookupCache == NULL) return nil;
275   return NSMapGet(self->lookupCache, _namespace);
276 }
277 - (void)flush {
278   if (self->lookupCache)
279     NSResetMapTable(self->lookupCache);
280   
281   [self->listMethodsCache     removeAllObjects];
282   [self->methodSignatureCache removeAllObjects];
283 }
284
285 /* component retries on error (failover) */
286
287 - (NSUserDefaults *)userDefaults {
288   return [NSUserDefaults standardUserDefaults];
289 }
290
291 - (int)componentRetryCountOnError {
292   return [[[self userDefaults]
293                  valueForKey:@"SxComponentRetriesOnError"]
294                  intValue];
295 }
296
297 - (int)componentRetryTime {
298   return [[[self userDefaults]
299                  valueForKey:@"SxComponentRetryTime"]
300                  intValue];
301 }
302
303 /* credentials */
304
305 - (NSArray *)credentials {
306   return self->credentials;
307 }
308
309 - (void)addCredentials:(id)_creds {
310   if (_creds == nil) {
311     [self logWithFormat:@"warning: passed <nil> to -addCredentials: ..."];
312     return;
313   }
314
315   [self->credentials addObject:_creds];
316 }
317 - (void)removeCredentials:(id)_creds {
318   [self->credentials removeObject:_creds];
319 }
320
321 /* NSCoding */
322
323 - (void)encodeWithCoder:(NSCoder *)_coder {
324   [_coder encodeObject:self->backends];
325 }
326 - (id)initWithCoder:(NSCoder *)_coder {
327   self->credentials = [[NSMutableArray alloc] initWithCapacity:4];
328   self->backends = [[_coder decodeObject] retain];
329   return self;
330 }
331
332 /* description */
333
334 - (NSString *)description {
335   return [NSString stringWithFormat:
336                      @"<0x%p[%@]: backends=%@>",
337                      self, NSStringFromClass([self class]),
338                      self->backends];
339 }
340
341 @end /* SxComponentRegistry */