PageRenderTime 47ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/modules/data/source/temple/data/cache/CacheURLLoader.as

http://templelibrary.googlecode.com/
ActionScript | 258 lines | 168 code | 20 blank | 70 comment | 26 complexity | 57713a2daeaa8f3b20cb51dcbfe6c8f1 MD5 | raw file
  1. /*
  2. * Temple Library for ActionScript 3.0
  3. * Copyright Š MediaMonks B.V.
  4. * All rights reserved.
  5. *
  6. * Redistribution and use in source and binary forms, with or without
  7. * modification, are permitted provided that the following conditions are met:
  8. * 1. Redistributions of source code must retain the above copyright
  9. * notice, this list of conditions and the following disclaimer.
  10. * 2. Redistributions in binary form must reproduce the above copyright
  11. * notice, this list of conditions and the following disclaimer in the
  12. * documentation and/or other materials provided with the distribution.
  13. * 3. All advertising materials mentioning features or use of this software
  14. * must display the following acknowledgement:
  15. * This product includes software developed by MediaMonks B.V.
  16. * 4. Neither the name of MediaMonks B.V. nor the
  17. * names of its contributors may be used to endorse or promote products
  18. * derived from this software without specific prior written permission.
  19. *
  20. * THIS SOFTWARE IS PROVIDED BY MEDIAMONKS B.V. ''AS IS'' AND ANY
  21. * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  22. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  23. * DISCLAIMED. IN NO EVENT SHALL MEDIAMONKS B.V. BE LIABLE FOR ANY
  24. * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  25. * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  26. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  27. * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  28. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  29. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  30. *
  31. *
  32. * Note: This license does not apply to 3rd party classes inside the Temple
  33. * repository with their own license!
  34. */
  35. package temple.data.cache
  36. {
  37. import temple.core.destruction.DestructEvent;
  38. import temple.core.net.CoreURLLoader;
  39. import temple.utils.FrameDelay;
  40. import flash.events.ErrorEvent;
  41. import flash.events.Event;
  42. import flash.events.HTTPStatusEvent;
  43. import flash.events.IOErrorEvent;
  44. import flash.events.ProgressEvent;
  45. import flash.events.SecurityErrorEvent;
  46. import flash.net.URLLoaderDataFormat;
  47. import flash.net.URLRequest;
  48. /**
  49. * The CacheLoader stores the data (bytes) of the loaded file into the LoaderCache by URL.
  50. * If the data of an URL is already in the LoaderCache it gets the bytes from the LoaderCache instead of reloading the file.
  51. *
  52. * @author Thijs Broerse
  53. */
  54. public class CacheURLLoader extends CoreURLLoader implements ICacheable
  55. {
  56. private var _cache:Boolean;
  57. private var _cacheData:LoaderCacheData;
  58. private var _owner:Boolean;
  59. public function CacheURLLoader(request:URLRequest = null, destructOnError:Boolean = true, logErrors:Boolean = true, cache:Boolean = true)
  60. {
  61. super(null, destructOnError, logErrors);
  62. this._cache = cache;
  63. if (request) new FrameDelay(this.load, 1, [request]);
  64. }
  65. /**
  66. * @inheritDoc
  67. */
  68. override public function get url():String
  69. {
  70. return this._cacheData ? this._cacheData.url : super.url;
  71. }
  72. /**
  73. * @inheritDoc
  74. */
  75. override public function get isLoading():Boolean
  76. {
  77. return this._cache ? this._cacheData && !this._cacheData.isLoaded : super.isLoading;
  78. }
  79. /**
  80. * @inheritDoc
  81. */
  82. override public function get isLoaded():Boolean
  83. {
  84. return this._cache ? this._cacheData && this._cacheData.isLoaded : super.isLoaded;
  85. }
  86. /**
  87. * @inheritDoc
  88. */
  89. override public function load(request:URLRequest):void
  90. {
  91. // check if our current load is competed
  92. if (this._owner && this._cacheData && this._cacheData.isLoading)
  93. {
  94. // we didn't finished the current load, delete it
  95. LoaderCache.clear(this.url);
  96. try
  97. {
  98. super.close();
  99. }
  100. catch (error:Error)
  101. {
  102. // ignore
  103. }
  104. }
  105. this._owner = false;
  106. this.clearCacheData();
  107. if (this._cache && (this._cacheData = LoaderCache.get(request.url)))
  108. {
  109. if (this._cacheData.isLoaded)
  110. {
  111. if (this.debug) this.logDebug("load: get data from cache, url:" + this.url);
  112. this.data = LoaderCache.get(this.url).bytes;
  113. this.dispatchEvent(new Event(Event.COMPLETE));
  114. }
  115. else
  116. {
  117. if (this.debug) this.logDebug("load: data is currently loading, wait... " + this._cacheData.url);
  118. this._cacheData.addEventListener(Event.COMPLETE, this.handleCacheDataComplete);
  119. this._cacheData.addEventListener(Event.OPEN, this.dispatchEvent);
  120. this._cacheData.addEventListener(ProgressEvent.PROGRESS, this.dispatchEvent);
  121. this._cacheData.addEventListener(HTTPStatusEvent.HTTP_STATUS, this.dispatchEvent);
  122. this._cacheData.addEventListener(IOErrorEvent.IO_ERROR, this.handleCacheDataError);
  123. this._cacheData.addEventListener(IOErrorEvent.DISK_ERROR, this.handleCacheDataError);
  124. this._cacheData.addEventListener(IOErrorEvent.NETWORK_ERROR, this.handleCacheDataError);
  125. this._cacheData.addEventListener(IOErrorEvent.VERIFY_ERROR, this.handleCacheDataError);
  126. this._cacheData.addEventListener(SecurityErrorEvent.SECURITY_ERROR, this.handleCacheDataError);
  127. this._cacheData.addEventListener(DestructEvent.DESTRUCT, this.handleCacheDataDestuct);
  128. this.dispatchEvent(new Event(Event.OPEN));
  129. }
  130. }
  131. else
  132. {
  133. if (this._cache)
  134. {
  135. this._cacheData = LoaderCache.create(request.url);
  136. this._owner = true;
  137. this.addEventListener(Event.OPEN, this._cacheData.dispatchEvent);
  138. this.addEventListener(ProgressEvent.PROGRESS, this._cacheData.dispatchEvent);
  139. this.addEventListener(IOErrorEvent.IO_ERROR, this._cacheData.dispatchEvent);
  140. this.addEventListener(IOErrorEvent.DISK_ERROR, this._cacheData.dispatchEvent);
  141. this.addEventListener(IOErrorEvent.NETWORK_ERROR, this._cacheData.dispatchEvent);
  142. this.addEventListener(IOErrorEvent.VERIFY_ERROR, this._cacheData.dispatchEvent);
  143. this.addEventListener(SecurityErrorEvent.SECURITY_ERROR, this._cacheData.dispatchEvent);
  144. if (this.debug) this.logDebug("load: new LoaderCacheData created: " + this._cacheData);
  145. }
  146. this.addEventListenerOnce(Event.COMPLETE, this.handleComplete);
  147. this.dataFormat = URLLoaderDataFormat.BINARY;
  148. super.load(request);
  149. }
  150. }
  151. /**
  152. * @inheritDoc
  153. */
  154. override public function close():void
  155. {
  156. // check if our current load is competed
  157. if (this._owner && this._cacheData && this._cacheData.isLoading)
  158. {
  159. // we didn't finished the current load, delete it
  160. LoaderCache.clear(this._cacheData.url);
  161. }
  162. super.close();
  163. }
  164. /**
  165. * @inheritDoc
  166. */
  167. public function get cache():Boolean
  168. {
  169. return this._cache;
  170. }
  171. /**
  172. * @inheritDoc
  173. */
  174. public function set cache(value:Boolean):void
  175. {
  176. this._cache = value;
  177. if (this.debug) this.logDebug("cache: " + value);
  178. }
  179. private function handleComplete(event:Event):void
  180. {
  181. if (this._cache && this._owner)
  182. {
  183. if (this.debug) this.logDebug("handleComplete: store data in cache, url:" + this.url);
  184. LoaderCache.set(this.url, this.data);
  185. }
  186. this.clearCacheData();
  187. }
  188. private function handleCacheDataComplete(event:Event):void
  189. {
  190. this.data = this._cacheData.bytes;
  191. this.clearCacheData();
  192. this.dispatchEvent(event);
  193. }
  194. private function handleCacheDataError(event:ErrorEvent):void
  195. {
  196. if (this.debug) this.logWarn(event.type + ": \"" + event.text + "\"");
  197. this.clearCacheData();
  198. LoaderCache.clear(this.url);
  199. this.dispatchEvent(event);
  200. }
  201. private function clearCacheData():void
  202. {
  203. if (this._cacheData)
  204. {
  205. this._cacheData.removeEventListener(Event.COMPLETE, this.handleCacheDataComplete);
  206. this._cacheData.removeEventListener(Event.OPEN, this.dispatchEvent);
  207. this._cacheData.removeEventListener(ProgressEvent.PROGRESS, this.dispatchEvent);
  208. this._cacheData.removeEventListener(HTTPStatusEvent.HTTP_STATUS, this.dispatchEvent);
  209. this._cacheData.removeEventListener(IOErrorEvent.IO_ERROR, this.handleCacheDataError);
  210. this._cacheData.removeEventListener(IOErrorEvent.DISK_ERROR, this.handleCacheDataError);
  211. this._cacheData.removeEventListener(IOErrorEvent.NETWORK_ERROR, this.handleCacheDataError);
  212. this._cacheData.removeEventListener(IOErrorEvent.VERIFY_ERROR, this.handleCacheDataError);
  213. this._cacheData.removeEventListener(SecurityErrorEvent.SECURITY_ERROR, this.handleCacheDataError);
  214. this._cacheData.removeEventListener(DestructEvent.DESTRUCT, this.handleCacheDataDestuct);
  215. this._cacheData = null;
  216. this._owner = false;
  217. }
  218. }
  219. private function handleCacheDataDestuct(event:DestructEvent):void
  220. {
  221. // reload
  222. if (this.debug) this.logDebug("handleCacheDataDestuct: LoaderCacheData has been destructed, reload.");
  223. if (this.isLoading) this.load(new URLRequest(this.url));
  224. }
  225. /**
  226. * @inheritDoc
  227. */
  228. override public function destruct():void
  229. {
  230. if (this._cacheData)
  231. {
  232. if (this._owner) LoaderCache.clear(this.url);
  233. this.clearCacheData();
  234. }
  235. super.destruct();
  236. }
  237. }
  238. }