]> err.no Git - sope/blob - sope-appserver/SoOFS/OFSFactoryRegistry.m
added strict OSX bundle dependencies
[sope] / sope-appserver / SoOFS / OFSFactoryRegistry.m
1 /*
2   Copyright (C) 2002-2005 SKYRIX Software AG
3
4   This file is part of SOPE.
5
6   SOPE 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   SOPE 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 SOPE; 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
22 #include "OFSFactoryRegistry.h"
23 #include "OFSFolder.h"
24 #include "OFSFile.h"
25 #include "OFSFactoryContext.h"
26 #include <SoObjects/SoClassRegistry.h>
27 #include <SoObjects/SoObjCClass.h>
28 #include "common.h"
29
30 @interface SoClass(Factory)
31 - (id)ofsObjectFactory;
32 @end
33
34 @implementation OFSFactoryRegistry
35
36 static int factoryDebugOn    = 0;
37 static int factoryRegDebugOn = 0;
38
39 + (id)sharedFactoryRegistry {
40   static id reg = nil;
41   if (reg == nil) reg = [[OFSFactoryRegistry alloc] init];
42   return reg;
43 }
44
45 - (id)init {
46   if ((self = [super init])) {
47     self->classToFileFactory = 
48       [[NSMutableDictionary alloc] initWithCapacity:32];
49     self->extToFileFactory = 
50       [[NSMutableDictionary alloc] initWithCapacity:64];
51     self->nameToFileFactory = 
52       [[NSMutableDictionary alloc] initWithCapacity:64];
53     
54     self->defaultFolderFactory = [OFSFolder class];
55     self->defaultFileFactory   = [OFSFile   class];
56   }
57   return self;
58 }
59 - (void)dealloc {
60   [self->defaultFileFactory   release];
61   [self->defaultFolderFactory release];
62   [self->classToFileFactory   release];
63   [self->extToFileFactory     release];
64   [self->nameToFileFactory    release];
65   [super dealloc];
66 }
67
68 /* lookup factory */
69
70 - (id)factoryForChildKey:(NSString *)_key 
71   ofFolder:(OFSFolder *)_folder
72   fileType:(NSString *)_ftype
73   mimeType:(NSString *)_mimeType
74 {
75   SoClassRegistry *classRegistry;
76   NSString *pe;
77   SoClass  *soClass;
78   BOOL     isDir;
79   id       factory = nil;
80   
81   isDir = [_ftype isEqualToString:NSFileTypeDirectory] ? YES : NO;
82   
83   if (factoryDebugOn) {
84     [self debugWithFormat:@"lookup factory for key %@ type=%@ mime=%@",
85             _key, _ftype, _mimeType];
86   }
87   
88   /* first check fixed child classes */
89   
90   if (_folder && !isDir) {
91     factory = [self->classToFileFactory objectForKey:[_folder soClass]];
92     if (factory) {
93       if (factoryDebugOn) {
94         [self debugWithFormat:
95                 @"selected a file factory fixed to folderclass: %@", factory];
96       }
97       return factory;
98     }
99   }
100   
101   /* then, check exact names (eg 'htpasswd') */
102
103   if ((factory = [self->nameToFileFactory objectForKey:_key])) {
104     if (factoryDebugOn) {
105       [self debugWithFormat:@"selected file factory by exact name '%@': %@",
106               _key, factory];
107     }
108     return factory;
109   }
110   
111   /* now check extension */
112   
113   pe = [_key pathExtension];
114   if (pe == nil) pe = @"";
115   
116   if ((factory = [self->extToFileFactory objectForKey:pe])) {
117     if (factoryDebugOn) {
118       [self debugWithFormat:@"selected file factory by extension '%@': %@",
119               pe, factory];
120     }
121     return factory;
122   }
123   
124   /* check for SoClass factories */
125
126   classRegistry = [SoClassRegistry sharedClassRegistry];
127   
128   if ((soClass = [classRegistry soClassForExactName:_key])) {
129     if (factoryDebugOn) {
130       [self debugWithFormat:@"selected SoClass factory by exact name '%@': %@",
131               _key, factory];
132     }
133   }
134   else if ((soClass = [classRegistry soClassForExtension:pe])) {
135     if (factoryDebugOn) {
136       [self debugWithFormat:@"selected SoClass factory by extension '%@': %@",
137               pe, factory];
138     }
139   }
140   
141   if (soClass) {
142     if ((factory = [soClass ofsObjectFactory]))
143       return factory;
144     else {
145       if (factoryDebugOn) {
146         [self debugWithFormat:
147                 @"did not use SoClass for name/extension %@/'%@': %@",
148                 _key, pe, soClass];
149       }
150     }
151   }
152   
153   /* apply defaults */
154   
155   return isDir ? self->defaultFolderFactory : self->defaultFileFactory;
156 }
157
158 - (id)restorationFactoryForContext:(OFSFactoryContext *)_ctx {
159   return [self factoryForChildKey:[_ctx nameInContainer]
160                ofFolder:[_ctx container]
161                fileType:_ctx->fileType
162                mimeType:_ctx->mimeType];
163 }
164 - (id)creationFactoryForContext:(OFSFactoryContext *)_ctx {
165   return [self factoryForChildKey:[_ctx nameInContainer]
166                ofFolder:[_ctx container]
167                fileType:_ctx->fileType
168                mimeType:_ctx->mimeType];
169 }
170
171 /* registration */
172
173 - (void)registerFileFactory:(id)_factory forSoClass:(SoClass *)_clazz {
174   if (_factory == nil) return;
175   if (_clazz   == nil) return;
176   if (factoryRegDebugOn) {
177     [self debugWithFormat:@"registering file factory '%@' for class %@",
178             _factory, _clazz];
179   }
180   [self->classToFileFactory setObject:_factory forKey:_clazz];
181 }
182
183 - (void)registerFileFactory:(id)_factory forClass:(Class)_clazz {
184   [self registerFileFactory:_factory forSoClass:[_clazz soClass]];
185 }
186
187 - (void)registerFileFactory:(id)_factory forExtension:(NSString *)_ext {
188   if (_factory == nil) return;
189   if (_ext     == nil) return;
190   
191   if (factoryRegDebugOn) {
192     [self debugWithFormat:@"registering file factory '%@' for extension %@",
193             _factory, _ext];
194   }
195   [self->extToFileFactory setObject:_factory forKey:_ext];
196 }
197
198 - (void)registerFileFactory:(id)_factory forExactName:(NSString *)_name {
199   if (_factory == nil) return;
200   if (_name    == nil) return;
201   
202   if (factoryRegDebugOn) {
203     [self debugWithFormat:@"registering file factory '%@' for exact name '%@'",
204             _factory, _name];
205   }
206   [self->nameToFileFactory setObject:_factory forKey:_name];
207 }
208
209 @end /* OFSFactoryRegistry */
210
211 @implementation SoClass(Factory)
212
213 - (id)ofsObjectFactory {
214   return nil;
215 }
216
217 @end /* SoClass(Factory) */
218
219 @implementation SoObjCClass(Factory)
220
221 - (id)ofsObjectFactory {
222   Class bClazz;
223   
224   if ((bClazz = [self objcClass]) == Nil)
225     return nil;
226   
227   if (![bClazz respondsToSelector:@selector(instantiateInFactoryContext:)])
228     return nil;
229   
230   return bClazz;
231 }
232
233 @end /* SoObjCClass(Factory) */