2 Copyright (C) 2000-2004 SKYRIX Software AG
4 This file is part of OpenGroupware.org.
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
22 #include "SaxXMLReaderFactory.h"
25 #if GNUSTEP_BASE_LIBRARY
26 @implementation NSBundle(Copying)
27 - (id)copyWithZone:(NSZone *)_zone {
33 @implementation SaxXMLReaderFactory
35 static BOOL coreOnMissingParser = NO;
36 static BOOL debugOn = NO;
37 static NSArray *searchPathes = nil;
38 static NSNull *null = nil;
39 static id factory = nil;
42 NSUserDefaults *ud = [NSUserDefaults standardUserDefaults];
44 coreOnMissingParser = [ud boolForKey:@"SaxCoreOnMissingParser"];
45 debugOn = [ud boolForKey:@"SaxDebugReaderFactory"];
48 + (id)standardXMLReaderFactory {
50 factory = [[self alloc] init];
55 [self->nameToBundle release];
56 [self->mimeTypeToName release];
63 [self->nameToBundle release]; self->nameToBundle = nil;
64 [self->mimeTypeToName release]; self->mimeTypeToName = nil;
67 - (NSArray *)saxReaderSearchPathes {
70 #if !COCOA_Foundation_LIBRARY
77 ma = [NSMutableArray arrayWithCapacity:8];
79 #if COCOA_Foundation_LIBRARY
80 tmp = NSSearchPathForDirectoriesInDomains(NSAllLibrariesDirectory,
83 if ([tmp count] > 0) {
86 e = [tmp objectEnumerator];
87 while ((tmp = [e nextObject])) {
88 tmp = [tmp stringByAppendingPathComponent:@"SaxDrivers-4.3"];
89 if (![ma containsObject:tmp])
93 #if COMPILE_AS_FRAMEWORK
97 /* no need to add 4.3 here, right? */
98 fwBundle = [NSBundle bundleForClass:[self class]];
99 [ma addObject:[[fwBundle resourcePath]
100 stringByAppendingPathComponent:@"SaxDrivers"]];
104 env = [[NSProcessInfo processInfo] environment];
106 if ((tmp = [env objectForKey:@"GNUSTEP_PATHPREFIX_LIST"]) == nil)
107 tmp = [env objectForKey:@"GNUSTEP_PATHLIST"];
108 tmp = [tmp componentsSeparatedByString:@":"];
109 if ([tmp count] > 0) {
112 e = [tmp objectEnumerator];
113 while ((tmp = [e nextObject])) {
114 tmp = [tmp stringByAppendingPathComponent:@"Library/SaxDrivers-4.3"];
115 if (![ma containsObject:tmp])
122 [ma addObject:@"/usr/local/lib/sope-4.3/saxdrivers/"];
123 [ma addObject:@"/usr/lib/sope-4.3/saxdrivers/"];
124 searchPathes = [ma copy];
126 if ([searchPathes count] == 0)
127 NSLog(@"%s: no search pathes were found!", __PRETTY_FUNCTION__);
132 - (void)_loadBundlePath:(NSString *)_bundlePath
133 infoDictionary:(NSDictionary *)_info
134 nameMap:(NSMutableDictionary *)_nameMap
135 typeMap:(NSMutableDictionary *)_typeMap
139 NSDictionary *driverInfo;
142 _info = [_info objectForKey:@"provides"];
143 if ((drivers = [_info objectForKey:@"SAXDrivers"]) == nil) {
144 NSLog(@"%s: .sax bundle '%@' does not provide any SAX drivers ...",
145 __PRETTY_FUNCTION__, _bundlePath);
149 if ((bundle = [NSBundle bundleWithPath:_bundlePath]) == nil) {
150 NSLog(@"%s: could not create bundle from path '%@'",
151 __PRETTY_FUNCTION__, _bundlePath);
155 /* found a driver with valid info dict, process it ... */
157 e = [drivers objectEnumerator];
158 while ((driverInfo = [e nextObject])) {
159 NSString *name, *tname;
162 name = [driverInfo objectForKey:@"name"];
163 if ([name length] == 0) {
164 NSLog(@"%s: missing name in sax driver section of bundle %@ ...",
165 __PRETTY_FUNCTION__, _bundlePath);
169 /* check if name is already registered */
170 if ([_nameMap objectForKey:name]) {
172 NSLog(@"%s: already have sax driver named '%@' ...",
173 __PRETTY_FUNCTION__, name);
177 /* register bundle for name */
178 [_nameMap setObject:bundle forKey:name];
180 /* register MIME-types */
181 te = [[driverInfo objectForKey:@"sourceTypes"] objectEnumerator];
182 while ((tname = [te nextObject])) {
185 if ((tmp = [_typeMap objectForKey:tname])) {
186 NSLog(@"WARNING(%s): multiple parsers available for MIME type '%@', "
187 @"using '%@' as default for type %@.",
188 __PRETTY_FUNCTION__, tname, tmp, tname);
192 [_typeMap setObject:name forKey:tname];
197 - (void)_loadLibraryPath:(NSString *)_libraryPath
198 nameMap:(NSMutableDictionary *)_nameMap
199 typeMap:(NSMutableDictionary *)_typeMap
201 NSFileManager *fm = [NSFileManager defaultManager];
205 e = [[fm directoryContentsAtPath:_libraryPath] objectEnumerator];
206 while ((p = [e nextObject])) {
211 if (![p hasSuffix:@".sax"]) continue;
213 p = [_libraryPath stringByAppendingPathComponent:p];
214 if (![fm fileExistsAtPath:p isDirectory:&isDir])
216 if (!isDir) { /* info file is a directory ??? */
217 NSLog(@"%s: .sax is not a dir: '%@' ???", __PRETTY_FUNCTION__, p);
221 #if COCOA_Foundation_LIBRARY
225 b = [NSBundle bundleWithPath:p];
226 infoPath = [b pathForResource:@"bundle-info" ofType:@"plist"];
229 infoPath = [p stringByAppendingPathComponent:@"bundle-info.plist"];
232 info = [NSDictionary dictionaryWithContentsOfFile:infoPath];
234 NSLog(@"%s: could not parse bundle-info dictionary: '%@'",
235 __PRETTY_FUNCTION__, infoPath);
239 [self _loadBundlePath:p infoDictionary:info
240 nameMap:_nameMap typeMap:_typeMap];
244 - (void)_loadAvailableBundles {
245 NSAutoreleasePool *pool;
249 null = [[NSNull null] retain];
252 NSAssert(self->nameToBundle == nil, @"already set up !");
253 NSAssert(self->mimeTypeToName == nil, @"partially set up !");
255 if (self->nameToBundle) return;
258 pool = [[NSAutoreleasePool alloc] init];
260 /* lookup bundle in Libary/SaxDrivers pathes */
261 NSEnumerator *pathes;
263 NSMutableDictionary *nameMap, *typeMap;
265 nameMap = [NSMutableDictionary dictionaryWithCapacity:16];
266 typeMap = [NSMutableDictionary dictionaryWithCapacity:16];
268 pathes = [[self saxReaderSearchPathes] objectEnumerator];
269 while ((path = [pathes nextObject]))
270 [self _loadLibraryPath:path nameMap:nameMap typeMap:typeMap];
272 self->nameToBundle = [nameMap copy];
273 self->mimeTypeToName = [typeMap copy];
276 if ([self->nameToBundle count] == 0) {
277 NSLog(@"%s: no XML parser could be found ...", __PRETTY_FUNCTION__);
279 else if ([self->mimeTypeToName count] == 0) {
280 NSLog(@"%s: no XML parser declared a MIME type ...",__PRETTY_FUNCTION__);
287 - (id<NSObject,SaxXMLReader>)createXMLReader {
291 if (debugOn) NSLog(@"%s: lookup default XML reader ...",__PRETTY_FUNCTION__);
294 [[NSUserDefaults standardUserDefaults] stringForKey:@"XMLReader"];
296 if (debugOn) NSLog(@"%s: default name ...",__PRETTY_FUNCTION__, defReader);
299 if ((reader = [self createXMLReaderWithName:defReader]))
302 NSLog(@"%s: could not create default XMLReader '%@' !",
303 __PRETTY_FUNCTION__, defReader);
306 return [self createXMLReaderForMimeType:@"text/xml"];
309 - (id<NSObject,SaxXMLReader>)createXMLReaderWithName:(NSString *)_name {
314 NSLog(@"%s: lookup XML reader with name: '%@'",__PRETTY_FUNCTION__,_name);
316 if ([_name length] == 0)
317 return [self createXMLReader];
319 if (self->nameToBundle == nil)
320 [self _loadAvailableBundles];
322 if ((bundle = [self->nameToBundle objectForKey:_name]) == nil)
325 /* load bundle executable code */
326 if (![bundle load]) {
327 NSLog(@"%s: could not load SaxDriver bundle %@ !", __PRETTY_FUNCTION__,
332 NSAssert(bundle, @"should have a loaded bundle at this stage ...");
335 if ((readerClass = NSClassFromString(_name)) == Nil) {
336 NSLog(@"WARNING(%s): could not find SAX reader class %@ (SAX bundle=%@)",
337 __PRETTY_FUNCTION__, _name, bundle);
341 /* create instance */
342 return [[[readerClass alloc] init] autorelease];
345 - (id<NSObject,SaxXMLReader>)createXMLReaderForMimeType:(NSString *)_mtype {
346 id<NSObject,SaxXMLReader> reader;
349 if (self->mimeTypeToName == nil)
350 [self _loadAvailableBundles];
353 NSLog(@"%s: lookup XML reader for type: '%@'",__PRETTY_FUNCTION__, _mtype);
355 if ([_mtype respondsToSelector:@selector(stringValue)])
356 _mtype = [(id)_mtype stringValue];
357 if ([_mtype length] == 0)
358 _mtype = @"text/xml";
360 if ((name = [self->mimeTypeToName objectForKey:_mtype]) == nil) {
362 NSLog(@"%s: did not find SAX parser for MIME type %@ map: \n%@",
363 __PRETTY_FUNCTION__, _mtype, self->mimeTypeToName);
364 NSLog(@"%s: parsers: %@", __PRETTY_FUNCTION__,
365 [self->nameToBundle allKeys]);
367 if (coreOnMissingParser) {
368 NSLog(@"%s: aborting, because 'SaxCoreOnMissingParser' "
369 @"default is enabled!", __PRETTY_FUNCTION__);
375 NSLog(@"%s: found XML reader named: '%@'", __PRETTY_FUNCTION__, name);
377 reader = [self createXMLReaderWithName:name];
380 NSLog(@"%s: created XML reader: %@", __PRETTY_FUNCTION__, reader);
384 - (NSArray *)availableXMLReaders {
385 return [self->nameToBundle allKeys];
388 @end /* SaxXMLReaderFactory */