PageRenderTime 18ms CodeModel.GetById 2ms app.highlight 12ms RepoModel.GetById 1ms app.codeStats 0ms

/Objective-J/StaticResource.js

http://github.com/cacaodev/cappuccino
JavaScript | 345 lines | 260 code | 76 blank | 9 comment | 40 complexity | 338caa6ca4738a2b8fad8fe2b1f59427 MD5 | raw file
  1
  2var rootResources = { };
  3
  4function StaticResource(/*CFURL*/ aURL, /*StaticResource*/ aParent, /*BOOL*/ isDirectory, /*BOOL*/ isResolved, /*Dictionary*/ aFilenameTranslateDictionary)
  5{
  6    this._parent = aParent;
  7    this._eventDispatcher = new EventDispatcher(this);
  8
  9    var name = aURL.absoluteURL().lastPathComponent() || aURL.schemeAndAuthority();
 10
 11    this._name = name;
 12    this._URL = aURL; //new CFURL(aName, aParent && aParent.URL().asDirectoryPathURL());
 13    this._isResolved = !!isResolved;
 14    this._filenameTranslateDictionary = aFilenameTranslateDictionary;
 15
 16    if (isDirectory)
 17        this._URL = this._URL.asDirectoryPathURL();
 18
 19    if (!aParent)
 20        rootResources[name] = this;
 21
 22    this._isDirectory = !!isDirectory;
 23    this._isNotFound = NO;
 24
 25    if (aParent)
 26        aParent._children[name] = this;
 27
 28    if (isDirectory)
 29        this._children = { };
 30
 31    else
 32        this._contents = "";
 33}
 34
 35StaticResource.rootResources = function()
 36{
 37    return rootResources;
 38};
 39
 40function countProp(x) {
 41    var count = 0;
 42    for (var k in x) {
 43        if (x.hasOwnProperty(k)) {
 44            ++count;
 45        }
 46    }
 47    return count;
 48}
 49
 50StaticResource.resetRootResources = function()
 51{
 52    rootResources = {};
 53};
 54
 55StaticResource.prototype.filenameTranslateDictionary = function()
 56{
 57    return this._filenameTranslateDictionary || {};
 58};
 59
 60exports.StaticResource = StaticResource;
 61
 62function resolveStaticResource(/*StaticResource*/ aResource)
 63{
 64    aResource._isResolved = YES;
 65    aResource._eventDispatcher.dispatchEvent(
 66    {
 67        type:"resolve",
 68        staticResource:aResource
 69    });
 70}
 71
 72StaticResource.prototype.resolve = function()
 73{
 74    if (this.isDirectory())
 75    {
 76        var bundle = new CFBundle(this.URL());
 77
 78        // Eat any errors.
 79        bundle.onerror = function() { };
 80
 81        // The bundle will actually resolve this node.
 82        bundle.load(NO);
 83    }
 84    else
 85    {
 86        var self = this;
 87
 88        function onsuccess(/*anEvent*/ anEvent)
 89        {
 90            self._contents = anEvent.request.responseText();
 91            resolveStaticResource(self);
 92        }
 93
 94        function onfailure()
 95        {
 96            self._isNotFound = YES;
 97            resolveStaticResource(self);
 98        }
 99
100        var url = this.URL(),
101            aFilenameTranslateDictionary = this.filenameTranslateDictionary();
102
103        if (aFilenameTranslateDictionary)
104        {
105            var urlString = url.toString(),
106                lastPathComponent = url.lastPathComponent(),
107                basePath = urlString.substring(0, urlString.length - lastPathComponent.length),
108                translatedName = aFilenameTranslateDictionary[lastPathComponent];
109
110            if (translatedName && urlString.slice(-translatedName.length) !== translatedName)
111                url = new CFURL(basePath + translatedName);  // FIXME: do an add component to url or something better....
112        }
113        new FileRequest(url, onsuccess, onfailure);
114    }
115};
116
117StaticResource.prototype.name = function()
118{
119    return this._name;
120};
121
122StaticResource.prototype.URL = function()
123{
124    return this._URL;
125};
126
127StaticResource.prototype.contents = function()
128{
129    return this._contents;
130};
131
132StaticResource.prototype.children = function()
133{
134    return this._children;
135};
136
137StaticResource.prototype.parent = function()
138{
139    return this._parent;
140};
141
142StaticResource.prototype.isResolved = function()
143{
144    return this._isResolved;
145};
146
147StaticResource.prototype.write = function(/*String*/ aString)
148{
149    this._contents += aString;
150};
151
152function rootResourceForAbsoluteURL(/*CFURL*/ anAbsoluteURL)
153{
154    var schemeAndAuthority = anAbsoluteURL.schemeAndAuthority(),
155        resource = rootResources[schemeAndAuthority];
156
157    if (!resource)
158        resource = new StaticResource(new CFURL(schemeAndAuthority), NULL, YES, YES);
159
160    return resource;
161}
162
163StaticResource.resourceAtURL = function(/*CFURL|String*/ aURL, /*BOOL*/ resolveAsDirectoriesIfNecessary)
164{
165    aURL = makeAbsoluteURL(aURL).absoluteURL();
166
167    var resource = rootResourceForAbsoluteURL(aURL),
168        components = aURL.pathComponents(),
169        index = 0,
170        count = components.length;
171
172    for (; index < count; ++index)
173    {
174        var name = components[index];
175
176        if (hasOwnProperty.call(resource._children, name))
177            resource = resource._children[name];
178
179        else if (resolveAsDirectoriesIfNecessary)
180        {
181            // We do this because on Windows the path may start with C: and be
182            // misinterpreted as a scheme.
183            if (name !== "/")
184                name = "./" + name;
185
186            resource = new StaticResource(new CFURL(name, resource.URL()), resource, YES, YES);
187        }
188        else
189            throw new Error("Static Resource at " + aURL + " is not resolved (\"" + name + "\")");
190    }
191
192    return resource;
193};
194
195StaticResource.prototype.resourceAtURL = function(/*CFURL|String*/ aURL, /*BOOL*/ resolveAsDirectoriesIfNecessary)
196{
197    return StaticResource.resourceAtURL(new CFURL(aURL, this.URL()), resolveAsDirectoriesIfNecessary);
198};
199
200StaticResource.resolveResourceAtURL = function(/*CFURL|String*/ aURL, /*BOOL*/ isDirectory, /*Function*/ aCallback, /*Dictionary*/ aFilenameTranslateDictionary)
201{
202    aURL = makeAbsoluteURL(aURL).absoluteURL();
203
204    resolveResourceComponents(rootResourceForAbsoluteURL(aURL), isDirectory, aURL.pathComponents(), 0, aCallback, aFilenameTranslateDictionary);
205};
206
207StaticResource.prototype.resolveResourceAtURL = function(/*CFURL|String*/ aURL, /*BOOL*/ isDirectory, /*Function*/ aCallback)
208{
209    StaticResource.resolveResourceAtURL(new CFURL(aURL, this.URL()).absoluteURL(), isDirectory, aCallback);
210};
211
212function resolveResourceComponents(/*StaticResource*/ aResource, /*BOOL*/ isDirectory, /*Array*/ components, /*Integer*/ index, /*Function*/ aCallback, /*Dictionry*/ aFilenameTranslateDictionary)
213{
214    var count = components.length;
215
216    for (; index < count; ++index)
217    {
218        var name = components[index],
219            child = hasOwnProperty.call(aResource._children, name) && aResource._children[name];
220
221        // If the child doesn't exist, create and resolve it.
222        if (!child)
223        {
224            child = new StaticResource(new CFURL(name, aResource.URL()), aResource, index + 1 < count || isDirectory , NO, aFilenameTranslateDictionary);
225            child.resolve();
226        }
227
228        // If this resource is still being resolved, just wait and rerun this same method when it's ready.
229        if (!child.isResolved())
230            return child.addEventListener("resolve", function()
231            {
232                // Continue resolving once this is done.
233                resolveResourceComponents(aResource, isDirectory, components, index, aCallback, aFilenameTranslateDictionary);
234            });
235
236        // If we've already determined that this file doesn't exist...
237        if (child.isNotFound())
238            return aCallback(null, new Error("File not found: " + components.join("/")));
239
240        // If we have more path components and this is not a directory...
241        if ((index + 1 < count) && child.isFile())
242            return aCallback(null, new Error("File is not a directory: " + components.join("/")));
243
244        aResource = child;
245    }
246
247    aCallback(aResource);
248}
249
250function resolveResourceAtURLSearchingIncludeURLs(/*CFURL*/ aURL, /*Number*/ anIndex, /*Function*/ aCallback)
251{
252    var includeURLs = StaticResource.includeURLs(),
253        searchURL = new CFURL(aURL, includeURLs[anIndex]).absoluteURL();
254
255    StaticResource.resolveResourceAtURL(searchURL, NO, function(/*StaticResource*/ aStaticResource)
256    {
257        if (!aStaticResource)
258        {
259            if (anIndex + 1 < includeURLs.length)
260                resolveResourceAtURLSearchingIncludeURLs(aURL, anIndex + 1, aCallback);
261            else
262                aCallback(NULL);
263
264            return;
265        }
266
267        aCallback(aStaticResource);
268    });
269}
270
271StaticResource.resolveResourceAtURLSearchingIncludeURLs = function(/*CFURL*/ aURL, /*Function*/ aCallback)
272{
273    resolveResourceAtURLSearchingIncludeURLs(aURL, 0, aCallback);
274};
275
276StaticResource.prototype.addEventListener = function(/*String*/ anEventName, /*Function*/ anEventListener)
277{
278    this._eventDispatcher.addEventListener(anEventName, anEventListener);
279};
280
281StaticResource.prototype.removeEventListener = function(/*String*/ anEventName, /*Function*/ anEventListener)
282{
283    this._eventDispatcher.removeEventListener(anEventName, anEventListener);
284};
285
286StaticResource.prototype.isNotFound = function()
287{
288    return this._isNotFound;
289};
290
291StaticResource.prototype.isFile = function()
292{
293    return !this._isDirectory;
294};
295
296StaticResource.prototype.isDirectory = function()
297{
298    return this._isDirectory;
299};
300
301StaticResource.prototype.toString = function(/*BOOL*/ includeNotFounds)
302{
303    if (this.isNotFound())
304        return "<file not found: " + this.name() + ">";
305
306    var string = this.name();
307
308    if (this.isDirectory())
309    {
310        var children = this._children;
311
312        for (var name in children)
313            if (children.hasOwnProperty(name))
314            {
315                var child = children[name];
316
317                if (includeNotFounds || !child.isNotFound())
318                    string += "\n\t" + children[name].toString(includeNotFounds).split('\n').join("\n\t");
319            }
320    }
321
322    return string;
323};
324
325var includeURLs = NULL;
326
327StaticResource.includeURLs = function()
328{
329    if (includeURLs !== NULL)
330        return includeURLs;
331
332    includeURLs = [];
333
334    if (!global.OBJJ_INCLUDE_PATHS && !global.OBJJ_INCLUDE_URLS)
335        includeURLs = ["Frameworks", "Frameworks/Debug"];
336    else
337        includeURLs = (global.OBJJ_INCLUDE_PATHS || []).concat(global.OBJJ_INCLUDE_URLS || []);
338
339    var count = includeURLs.length;
340
341    while (count--)
342        includeURLs[count] = new CFURL(includeURLs[count]).asDirectoryPathURL();
343
344    return includeURLs;
345};