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