2 Copyright (C) 2000-2003 SKYRIX Software AG
4 This file is part of OGo
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
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.
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
23 #include "SxComponentRegistry.h"
24 #include "SxComponent.h"
27 @implementation SxComponentRegistry
29 static SxComponentRegistry *defreg = nil;
32 static BOOL didInit = NO;
37 defs = [NSDictionary dictionaryWithObjectsAndKeys:
38 [NSArray arrayWithObject:@"SxXmlRpcRegBackend"],
39 @"SxComponentRegistryBackends",
40 [NSNumber numberWithInt:3],
41 @"SxComponentRetriesOnError",
42 [NSNumber numberWithInt:5],
43 @"SxComponentRetryTime",
45 [[NSUserDefaults standardUserDefaults] registerDefaults:defs];
48 + (NSArray *)defaultRegistryBackends {
49 return [[NSUserDefaults standardUserDefaults]
50 arrayForKey:@"SxComponentRegistryBackends"];
53 + (id)defaultComponentRegistry {
56 defreg = [[SxComponentRegistry alloc] init];
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];
70 - (id)initWithBackendClassNames:(NSArray *)_beClasses {
72 NSString *beClassName;
77 bes = [NSMutableArray arrayWithCapacity:[_beClasses count]];
78 e = [_beClasses objectEnumerator];
79 while ((beClassName = [e nextObject])) {
83 if ((beClass = NSClassFromString(beClassName)) == Nil) {
84 [self logWithFormat:@"did not find backend class '%@'", beClassName];
88 if ((be = [[beClass alloc] init])) {
93 [self logWithFormat:@"backend of class %@ wasn't initialized ...",
94 NSStringFromClass(beClass)];
98 return [self initWithBackends:bes];
101 return [self initWithBackendClassNames:
102 [[self class] defaultRegistryBackends]];
106 RELEASE(self->methodSignatureCache);
107 RELEASE(self->listMethodsCache);
108 RELEASE(self->backends);
109 RELEASE(self->credentials);
111 if (self->lookupCache) {
112 NSFreeMapTable(self->lookupCache);
113 self->lookupCache = NULL;
120 - (void)_componentWillDealloc:(SxComponent *)_c {
121 if (self->lookupCache)
122 NSMapRemove(self->lookupCache, [_c componentName]);
125 - (void)_removeComponentFromLookupCache:(NSString *)_cname {
126 if (self->lookupCache)
127 NSMapRemove(self->lookupCache, _cname);
130 /* getting components */
132 - (id<NSObject,SxComponent>)getComponent:(NSString *)_namespace {
133 NSAutoreleasePool *pool;
138 if (self->lookupCache == NULL) {
139 self->lookupCache = NSCreateMapTable(NSObjectMapKeyCallBacks,
140 NSNonRetainedObjectMapValueCallBacks,
144 if ((c = NSMapGet(self->lookupCache, _namespace))) {
148 pool = [[NSAutoreleasePool alloc] init];
150 e = [self->backends objectEnumerator];
152 while((backend = [e nextObject])) {
153 if ([backend registry:self canHandleNamespace:_namespace]) {
154 c = [backend registry:self getComponent:_namespace];
159 if (c) NSMapInsert(self->lookupCache, [c componentName], c);
164 return AUTORELEASE(c);
167 /* returns the names of the available components */
169 - (NSArray *)listComponents:(NSString *)_path {
170 NSMutableArray *results;
175 e = [self->backends objectEnumerator];
176 while ((backend = [e nextObject])) {
179 if ((r = [backend registry:self listComponents:_path])) {
181 results = [NSMutableArray arrayWithCapacity:128];
182 [results addObjectsFromArray:r];
187 - (NSArray *)listComponents {
188 return [self listComponents:nil];
191 - (NSArray *)listMethods:(NSString *)_component {
196 if ([_component length] == 0)
200 if ((result = [self->listMethodsCache objectForKey:_component]))
201 return AUTORELEASE(RETAIN(result));
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];
214 [self->listMethodsCache setObject:result forKey:_component];
219 - (NSArray *)methodSignature:(NSString *)_component method:(NSString *)_name {
226 key = [NSString stringWithFormat:@"%@\n%@", _name, _component];
227 if ((result = [self->methodSignatureCache objectForKey:key]))
228 return AUTORELEASE(RETAIN(result));
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];
241 [self->methodSignatureCache setObject:result forKey:key];
246 - (NSString *)methodHelp:(NSString *)_component method:(NSString *)_name {
250 e = [self->backends objectEnumerator];
252 while((backend = [e nextObject])) {
253 if ([backend registry:self canHandleNamespace:_component]) {
254 return [backend registry:self methodHelp:_component method:_name];
260 /* component registration */
262 - (BOOL)registerComponent:(SxComponent *)_component {
263 if (_component == nil) return YES;
266 - (BOOL)unregisterComponent:(SxComponent *)_component {
267 if (_component == nil) return YES;
273 - (SxComponent *)getCachedComponent:(NSString *)_namespace {
274 if (self->lookupCache == NULL) return nil;
275 return NSMapGet(self->lookupCache, _namespace);
278 if (self->lookupCache)
279 NSResetMapTable(self->lookupCache);
281 [self->listMethodsCache removeAllObjects];
282 [self->methodSignatureCache removeAllObjects];
285 /* component retries on error (failover) */
287 - (NSUserDefaults *)userDefaults {
288 return [NSUserDefaults standardUserDefaults];
291 - (int)componentRetryCountOnError {
292 return [[[self userDefaults]
293 valueForKey:@"SxComponentRetriesOnError"]
297 - (int)componentRetryTime {
298 return [[[self userDefaults]
299 valueForKey:@"SxComponentRetryTime"]
305 - (NSArray *)credentials {
306 return self->credentials;
309 - (void)addCredentials:(id)_creds {
311 [self logWithFormat:@"warning: passed <nil> to -addCredentials: ..."];
315 [self->credentials addObject:_creds];
317 - (void)removeCredentials:(id)_creds {
318 [self->credentials removeObject:_creds];
323 - (void)encodeWithCoder:(NSCoder *)_coder {
324 [_coder encodeObject:self->backends];
326 - (id)initWithCoder:(NSCoder *)_coder {
327 self->credentials = [[NSMutableArray alloc] initWithCapacity:4];
328 self->backends = [[_coder decodeObject] retain];
334 - (NSString *)description {
335 return [NSString stringWithFormat:
336 @"<0x%08X[%@]: backends=%@>",
337 self, NSStringFromClass([self class]),
341 @end /* SxComponentRegistry */