]> err.no Git - sope/blob - sope-core/NGExtensions/NGResourceLocator.m
Drop apache 1 build-dependency
[sope] / sope-core / NGExtensions / NGResourceLocator.m
1 /*
2   Copyright (C) 2000-2006 SKYRIX Software AG
3   Copyright (C) 2006      Helge Hess
4
5   This file is part of SOPE.
6
7   SOPE is free software; you can redistribute it and/or modify it under
8   the terms of the GNU Lesser General Public License as published by the
9   Free Software Foundation; either version 2, or (at your option) any
10   later version.
11
12   SOPE is distributed in the hope that it will be useful, but WITHOUT ANY
13   WARRANTY; without even the implied warranty of MERCHANTABILITY or
14   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
15   License for more details.
16
17   You should have received a copy of the GNU Lesser General Public
18   License along with SOPE; see the file COPYING.  If not, write to the
19   Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
20   02111-1307, USA.
21 */
22
23 #include "NGResourceLocator.h"
24 #include "NSNull+misc.h"
25 #include "common.h"
26
27 @implementation NGResourceLocator
28
29 + (id)resourceLocatorForGNUstepPath:(NSString *)_path fhsPath:(NSString *)_fhs{
30   return [[[self alloc] initWithGNUstepPath:_path fhsPath:_fhs] autorelease];
31 }
32
33 - (id)initWithGNUstepPath:(NSString *)_path fhsPath:(NSString *)_fhs {
34   if ((self = [super init])) {
35     self->gsSubPath   = [_path copy];
36     self->fhsSubPath  = [_fhs  copy];
37     self->fileManager = [[NSFileManager defaultManager] retain];
38     
39     self->flags.cacheSearchPathes = 1;
40     self->flags.cachePathMisses   = 1;
41     self->flags.cachePathHits     = 1;
42   }
43   return self;
44 }
45 - (id)init {
46   return [self initWithGNUstepPath:@"Library/Resources" fhsPath:@"share"];
47 }
48
49 - (void)dealloc {
50   [self->nameToPathCache release];
51   [self->searchPathes release];
52   [self->fhsSubPath   release];
53   [self->gsSubPath    release];
54   [self->fileManager  release];
55   [super dealloc];
56 }
57
58 /* search pathes */
59
60 - (NSArray *)gsRootPathes {
61   static NSArray *pathes = nil;
62   NSDictionary *env;
63   NSString *apath;
64   
65   if (pathes != nil)
66     return [pathes isNotNull] ? pathes : (NSArray *)nil;
67   
68   env = [[NSProcessInfo processInfo] environment];
69   if ((apath = [env objectForKey:@"GNUSTEP_PATHPREFIX_LIST"]) == nil)
70     apath = [env objectForKey:@"GNUSTEP_PATHLIST"];
71   
72   if (![apath isNotNull]) return nil;
73   pathes = [[apath componentsSeparatedByString:@":"] copy];
74   return pathes;
75 }
76
77 - (NSArray *)fhsRootPathes {
78   // TODO: we probably want to make this configurable?! At least with an envvar
79   static NSArray *pathes = nil;
80   if (pathes == nil) {
81     pathes = [[NSArray alloc] initWithObjects:
82 #ifdef FHS_INSTALL_ROOT
83                                 FHS_INSTALL_ROOT,
84 #endif
85                                 @"/usr/local/", @"/usr/", nil];
86   }
87   return pathes;
88 }
89
90 - (NSArray *)collectSearchPathes {
91   NSMutableArray *ma;
92   NSEnumerator *e;
93   NSString *p;
94   
95   ma = [NSMutableArray arrayWithCapacity:6];
96   
97   e = ([self->gsSubPath length] > 0)
98     ? [[self gsRootPathes] objectEnumerator]
99     : (NSEnumerator *)nil;
100   while ((p = [e nextObject]) != nil) {
101     p = [p stringByAppendingPathComponent:self->gsSubPath];
102     if ([ma containsObject:p])
103       continue;
104     
105     if (![self->fileManager fileExistsAtPath:p])
106       continue;
107
108     [ma addObject:p];
109   }
110   
111   e = ([self->fhsSubPath length] > 0)
112     ? [[self fhsRootPathes] objectEnumerator]
113     : (NSEnumerator *)nil;
114   while ((p = [e nextObject]) != nil) {
115     p = [p stringByAppendingPathComponent:self->fhsSubPath];
116     if ([ma containsObject:p])
117       continue;
118     
119     if (![self->fileManager fileExistsAtPath:p])
120       continue;
121     
122     [ma addObject:p];
123   }
124   
125   return ma;
126 }
127
128 - (NSArray *)searchPathes {
129   NSArray *a;
130   
131   if (self->searchPathes != nil)
132     return self->searchPathes;
133   
134   a = [self collectSearchPathes];
135   if (self->flags.cacheSearchPathes) {
136     ASSIGNCOPY(self->searchPathes, a);
137     return self->searchPathes; /* return copy */
138   }
139   
140   return a;
141 }
142
143 /* cache */
144
145 - (void)cachePath:(NSString *)_path forName:(NSString *)_name {
146   if (self->nameToPathCache == nil)
147     self->nameToPathCache = [[NSMutableDictionary alloc] initWithCapacity:64];
148   
149   [self->nameToPathCache setObject:(_path ? _path : (NSString *)[NSNull null])
150                          forKey:_name];
151 }
152
153 /* operation */
154
155 - (NSString *)lookupFileWithName:(NSString *)_name {
156   NSEnumerator *e;
157   NSString *p;
158   
159   if (![_name isNotNull] || [_name length] == 0)
160     return nil;
161   if ((p = [self->nameToPathCache objectForKey:_name]) != nil)
162     return [p isNotNull] ? p : (NSString *)nil;
163   
164   e = [[self searchPathes] objectEnumerator];
165   while ((p = [e nextObject]) != nil) {
166     p = [p stringByAppendingPathComponent:_name];
167     
168     if (![self->fileManager fileExistsAtPath:p])
169       continue;
170     
171     [self cachePath:p forName:_name];
172     return p;
173   }
174   
175   if (self->flags.cachePathMisses)
176     [self cachePath:nil forName:_name];
177   return nil;
178 }
179
180 - (NSString *)lookupFileWithName:(NSString *)_name extension:(NSString *)_ext {
181   if ([_ext isNotNull] && [_ext length] > 0)
182     _name = [_name stringByAppendingPathExtension:_ext];
183   return [self lookupFileWithName:_name];
184 }
185
186 - (NSArray *)lookupAllFilesWithExtension:(NSString *)_ext
187   doReturnFullPath:(BOOL)_withPath
188 {
189   /* only deliver each filename once */
190   NSMutableArray *pathes;
191   NSMutableSet   *uniquer;
192   NSArray  *lSearchPathes;
193   unsigned i, count;
194   
195   _ext  = ([_ext length] > 0)
196     ? [@"." stringByAppendingString:_ext]
197     : (NSString *)nil;
198   
199   uniquer       = [NSMutableSet setWithCapacity:128];
200   pathes        = _withPath ? [NSMutableArray arrayWithCapacity:64] : nil;
201   lSearchPathes = [self searchPathes];
202   
203   for (i = 0, count = [lSearchPathes count]; i < count; i++) {
204     NSArray  *filenames;
205     unsigned j, jcount;
206     
207     filenames = [self->fileManager directoryContentsAtPath:
208                        [lSearchPathes objectAtIndex:i]];
209     
210     for (j = 0, jcount = [filenames count]; j < jcount; j++) {
211       NSString *fn, *pn;
212       
213       fn = [filenames objectAtIndex:j];
214       if (_ext != nil) {
215         if (![fn hasSuffix:_ext])
216           continue;
217       }
218       
219       if ([uniquer containsObject:fn])
220         continue;
221       
222       [uniquer addObject:fn];
223
224       /* build and cache path */
225       pn = [[lSearchPathes objectAtIndex:i] stringByAppendingPathComponent:fn];
226       [self cachePath:pn forName:fn];
227       if (_withPath) [pathes addObject:pn];
228     }
229   }
230   
231   return _withPath ? (NSArray *)pathes : [uniquer allObjects];
232 }
233
234 /* description */
235
236 - (NSString *)description {
237   NSMutableString *ms;
238   
239   ms = [NSMutableString stringWithCapacity:128];
240   [ms appendFormat:@"<0x%p[%@]:", self, NSStringFromClass([self class])];
241   
242   [ms appendFormat:@" gs=%@ fhs=%@", self->gsSubPath, self->fhsSubPath];
243   
244   [ms appendString:@" cache"];
245   if (self->flags.cacheSearchPathes)
246     [ms appendString:@":pathes"];
247   if (self->flags.cachePathHits)
248     [ms appendString:@":hits"];
249   if (self->flags.cachePathMisses)
250     [ms appendString:@":misses"];
251   [ms appendFormat:@":#%d", [self->nameToPathCache count]];
252   
253   [ms appendString:@">"];
254   return ms;
255 }
256
257 @end /* NGResourceLocator */