PageRenderTime 59ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

/bundles/plugins-trunk/XML/xml/cache/Cache.java

#
Java | 235 lines | 162 code | 24 blank | 49 comment | 39 complexity | ffdbdc340a9d3a035ea86d8a55010115 MD5 | raw file
Possible License(s): BSD-3-Clause, AGPL-1.0, Apache-2.0, LGPL-2.0, LGPL-3.0, GPL-2.0, CC-BY-SA-3.0, LGPL-2.1, GPL-3.0, MPL-2.0-no-copyleft-exception, IPL-1.0
  1. package xml.cache;
  2. import java.util.Set;
  3. import java.util.HashSet;
  4. import java.util.Iterator;
  5. import java.util.List;
  6. import java.util.ArrayList;
  7. import static org.gjt.sp.jedit.EditBus.EBHandler;
  8. import org.gjt.sp.jedit.jEdit;
  9. import org.gjt.sp.jedit.EditBus;
  10. import org.gjt.sp.jedit.msg.BufferUpdate;
  11. import org.gjt.sp.jedit.buffer.BufferAdapter;
  12. import org.gjt.sp.jedit.buffer.JEditBuffer;
  13. import org.gjt.sp.jedit.Buffer;
  14. import org.gjt.sp.util.Log;
  15. import static xml.Debug.*;
  16. import xml.PathUtilities;
  17. /**
  18. * caching policy :
  19. * - a file-based CacheEntry is valid until opened in jEdit
  20. * - a buffer-based CacheEntry is invalidated on change of the buffer
  21. * - a CacheEntry is discarded once all buffers requiring it are closed
  22. * (similar to reference-counting)
  23. * cache cleaners :
  24. * - listen to Buffer modifications and invalidates entries related to them
  25. * - listen to Buffer open and invalidates file based CacheEntry
  26. * - listen to Buffer close and invalidate buffer based CacheEntry
  27. * and invalidate cache entries no more required
  28. */
  29. public final class Cache extends BufferAdapter
  30. {
  31. private static final String DISABLE_PROP = "xml.cache.disable-cache";
  32. private static Cache instance;
  33. private Set<CacheEntry> entries;
  34. private boolean disabled;
  35. private Cache(){
  36. entries = new HashSet<CacheEntry>();
  37. disabled = jEdit.getBooleanProperty(DISABLE_PROP);
  38. }
  39. public static Cache instance()
  40. {
  41. if(instance == null)instance = new Cache();
  42. return instance;
  43. }
  44. /**
  45. * @param path path of cached resource (file:/ urls are equivalent to paths)
  46. * @param key unambiguously distinguish schema from completionInfo from...
  47. */
  48. public CacheEntry put(String path, Object key, Object value){
  49. if(DEBUG_CACHE)Log.log(Log.DEBUG,Cache.class,"put("+path+","+key+","+(value == null ? null : value.getClass())+")");
  50. if(disabled){
  51. if(DEBUG_CACHE)Log.log(Log.DEBUG,Cache.class,"cache disabled !");
  52. return null;
  53. }
  54. String npath = PathUtilities.urlToPath(path);
  55. if(npath != path){
  56. if(DEBUG_CACHE)Log.log(Log.DEBUG,Cache.class," really putting "+npath);
  57. path = npath;
  58. }
  59. CacheEntry en = new CacheEntry(path,key,value);
  60. // TODO: not sure about overwritting - not overwritting for now
  61. if(entries.contains(en)){
  62. if(DEBUG_CACHE)Log.log(Log.DEBUG,Cache.class," already in cache");
  63. }else{
  64. if(DEBUG_CACHE)Log.log(Log.DEBUG,Cache.class," not in cache");
  65. entries.add(en);
  66. }
  67. return en;
  68. }
  69. /**
  70. * @param path path of cached resource (file:/ urls are equivalent to paths)
  71. * @param key unambiguously distinguish schema from completionInfo from...
  72. */
  73. public CacheEntry get(String path, Object key){
  74. if(DEBUG_CACHE)Log.log(Log.DEBUG,Cache.class,"get("+path+","+key+")");
  75. if(disabled){
  76. if(DEBUG_CACHE)Log.log(Log.DEBUG,Cache.class,"cache disabled !");
  77. return null;
  78. }
  79. String npath = PathUtilities.urlToPath(path);
  80. if(npath != path){
  81. if(DEBUG_CACHE)Log.log(Log.DEBUG,Cache.class," really getting "+npath);
  82. path = npath;
  83. }
  84. for(Iterator<CacheEntry> it=entries.iterator();it.hasNext();){
  85. CacheEntry en = it.next();
  86. if(en.getPath().equals(path)
  87. && en.getKey().equals(key)){
  88. if(DEBUG_CACHE)Log.log(Log.DEBUG,Cache.class," found");
  89. return en;
  90. }
  91. }
  92. if(DEBUG_CACHE)Log.log(Log.DEBUG,Cache.class," not found");
  93. return null;
  94. }
  95. /**
  96. * invalidate cache entries corresponding to (not requested by) this buffer
  97. */
  98. public void contentInserted(JEditBuffer buffer, int startLine, int offset, int numLines, int length){
  99. handleBufferContentChanged((Buffer)buffer);
  100. }
  101. /**
  102. * invalidate cache entries corresponding to (not requested by) this buffer
  103. */
  104. public void contentRemoved(JEditBuffer buffer, int startLine, int offset, int numLines, int length){
  105. handleBufferContentChanged((Buffer)buffer);
  106. }
  107. /**
  108. * invalidate cache entries corresponding to (not requested by) this buffer
  109. */
  110. public void transactionComplete(JEditBuffer buffer){
  111. handleBufferContentChanged((Buffer)buffer);
  112. }
  113. @EBHandler
  114. public void handleBufferUpdate(BufferUpdate message)
  115. {
  116. if(BufferUpdate.CLOSED.equals(message.getWhat())){
  117. if(DEBUG_CACHE)Log.log(Log.DEBUG,Cache.class,"buffer closed");
  118. invalidateCacheEntriesFromPath(message.getBuffer().getPath());
  119. invalidateCacheEntriesRequiredByBuffer(message.getBuffer());
  120. message.getBuffer().removeBufferListener(this);
  121. }else if(BufferUpdate.LOADED.equals(message.getWhat())){
  122. if(DEBUG_CACHE)Log.log(Log.DEBUG,Cache.class,"buffer opened");
  123. invalidateCacheEntriesFromPath(message.getBuffer().getPath());
  124. message.getBuffer().addBufferListener(this);
  125. }
  126. }
  127. public void handleBufferContentChanged(Buffer buffer)
  128. {
  129. invalidateCacheEntriesFromPath(buffer.getPath());
  130. }
  131. private void invalidateCacheEntriesFromPath(String path){
  132. if(DEBUG_CACHE)Log.log(Log.DEBUG,Cache.class,"invalidateCacheEntriesFromPath("+path+")");
  133. List<CacheEntry> toRemove = new ArrayList<CacheEntry>();
  134. for(Iterator<CacheEntry> it=entries.iterator();it.hasNext();){
  135. CacheEntry en = it.next();
  136. if(en.getPath().equals(path)){
  137. if(DEBUG_CACHE)Log.log(Log.DEBUG,Cache.class,"invalidating "+en);
  138. it.remove();
  139. toRemove.addAll(en.getRelated());
  140. }
  141. }
  142. removeRelated(new HashSet<CacheEntry>(),toRemove);
  143. }
  144. private void invalidateCacheEntriesRequiredByBuffer(Buffer b){
  145. List<CacheEntry> toRemove = new ArrayList<CacheEntry>();
  146. for(Iterator<CacheEntry> it=entries.iterator();it.hasNext();){
  147. CacheEntry en = it.next();
  148. Set<Buffer> reqB = en.getRequestingBuffers();
  149. if(reqB.contains(b)){
  150. reqB.remove(b);
  151. if(reqB.isEmpty()){
  152. if(DEBUG_CACHE)Log.log(Log.DEBUG,Cache.class,"invalidating "+en);
  153. it.remove();
  154. toRemove.addAll(en.getRelated());
  155. }
  156. }
  157. }
  158. removeRelated(new HashSet<CacheEntry>(), toRemove);
  159. }
  160. /**
  161. * recursively remove related CacheEntries
  162. * @param removed avoid infinite recursion when related are recursive
  163. */
  164. private void removeRelated(Set<CacheEntry> removed,List<CacheEntry> toRemove){
  165. for(CacheEntry ce : toRemove){
  166. if(!removed.contains(ce)){
  167. if(DEBUG_CACHE)Log.log(Log.DEBUG,Cache.class,"invalidating related "+ce);
  168. entries.remove(ce);
  169. removed.add(ce);
  170. removeRelated(removed, ce.getRelated());
  171. }
  172. }
  173. }
  174. /**
  175. * add to EditBus
  176. */
  177. public void start(){
  178. EditBus.addToBus(this);
  179. }
  180. /**
  181. * clear, remove from EditBus, forget singleton
  182. */
  183. public void stop(){
  184. EditBus.removeFromBus(this);
  185. for(Buffer b:jEdit.getBuffers()){
  186. b.removeBufferListener(this);
  187. }
  188. entries.clear();
  189. instance = null;
  190. }
  191. /**
  192. * remove all cache entries
  193. */
  194. public void clear(){
  195. entries.clear();
  196. }
  197. /**
  198. * disable caching (persistent)
  199. */
  200. public void disable(){
  201. disabled = true;
  202. jEdit.setBooleanProperty(DISABLE_PROP,true);
  203. }
  204. /**
  205. * enable caching (persistent)
  206. */
  207. public void enable(){
  208. disabled = false;
  209. jEdit.unsetProperty(DISABLE_PROP);
  210. }
  211. }