1 11 12 package org.eclipse.osgi.baseadaptor.bundlefile; 13 14 import java.io.IOException ; 15 import org.eclipse.osgi.framework.eventmgr.*; 16 17 24 public class MRUBundleFileList implements EventDispatcher{ 25 private static final String PROP_FILE_LIMIT = "osgi.bundlefile.limit"; private static final int MIN = 10; 27 private static final int PROP_FILE_LIMIT_VALUE; 28 static { 29 int propValue = 0; 30 try { 31 String prop = BundleFile.secureAction.getProperty(PROP_FILE_LIMIT); 32 if (prop != null) 33 propValue = Integer.parseInt(prop); 34 } catch (NumberFormatException e) { 35 } 37 PROP_FILE_LIMIT_VALUE = propValue; 38 } 39 final private BundleFile[] bundleFileList; 41 final private long[] useStampList; 43 final private int fileLimit; final private EventManager bundleFileCloserManager; 46 final private EventListeners bundleFileCloser; 47 private int numOpen = 0; 49 private long curUseStamp = 0; 51 52 public MRUBundleFileList() { 53 this(PROP_FILE_LIMIT_VALUE); 54 } 55 56 public MRUBundleFileList(int fileLimit) { 57 this.fileLimit = fileLimit; 59 if (fileLimit >= MIN) { 60 this.bundleFileList = new BundleFile[fileLimit]; 61 this.useStampList = new long[fileLimit]; 62 this.bundleFileCloserManager = new EventManager("Bundle File Closer"); this.bundleFileCloser = new EventListeners(); 64 this.bundleFileCloser.addListener(this, this); 65 } else { 66 this.bundleFileList = null; 67 this.useStampList = null; 68 this.bundleFileCloserManager = null; 69 this.bundleFileCloser = null; 70 } 71 } 72 73 79 public void add(BundleFile bundleFile) { 80 if (fileLimit < MIN) 81 return; BundleFile toRemove = null; 83 synchronized (this) { 84 if (bundleFile.getMruIndex() >= 0) 85 return; int index = 0; if (numOpen < fileLimit) { 88 for (int i = 0; i < fileLimit; i++) 91 if (bundleFileList[i] == null) { 92 index = i; 93 break; 94 } 95 } else { 96 index = 0; 100 for (int i = 1; i < fileLimit; i++) 101 if (useStampList[i] < useStampList[index]) 102 index = i; 103 toRemove = bundleFileList[index]; 104 if (toRemove.getMruIndex() != index) 105 throw new IllegalStateException ("The BundleFile has the incorrect mru index: " + index + " != " + toRemove.getMruIndex()); removeInternal(toRemove); 107 } 108 bundleFileList[index] = bundleFile; 110 bundleFile.setMruIndex(index); 111 incUseStamp(index); 112 numOpen++; 113 } 114 closeBundleFile(toRemove); 117 } 118 119 124 public boolean remove(BundleFile bundleFile) { 125 if (fileLimit < MIN) 126 return false; synchronized (this) { 128 int index = bundleFile.getMruIndex(); 129 if ((index >= 0 && index < fileLimit) && bundleFileList[index] == bundleFile) { 130 removeInternal(bundleFile); 131 return true; 132 } 133 } 134 return false; 135 } 136 137 private void removeInternal(BundleFile bundleFile) { 139 int index = bundleFile.getMruIndex(); 140 bundleFile.setMruIndex(-1); 141 bundleFileList[index] = null; 142 useStampList[index] = -1; 143 numOpen--; 144 } 145 146 150 public void use(BundleFile bundleFile) { 151 if (fileLimit < MIN) 152 return; synchronized (this) { 154 int index = bundleFile.getMruIndex(); 155 if ((index >= 0 && index < fileLimit) && bundleFileList[index] == bundleFile) 156 incUseStamp(index); 157 } 158 } 159 160 private void incUseStamp(int index) { 162 if (curUseStamp == Long.MAX_VALUE) { 163 for (int i = 0; i < fileLimit; i++) 165 useStampList[i] = 0; 166 curUseStamp = 0; 167 } 168 useStampList[index] = ++curUseStamp; 169 } 170 171 public final void dispatchEvent(Object eventListener, Object listenerObject, int eventAction, Object eventObject) { 172 try { 173 ((BundleFile) eventObject).close(); 174 } catch (IOException e) { 175 } 177 } 178 179 private void closeBundleFile(BundleFile toRemove) { 180 if (toRemove == null) 181 return; 182 183 ListenerQueue queue = new ListenerQueue(bundleFileCloserManager); 184 185 queue.queueListeners(bundleFileCloser, this); 186 187 queue.dispatchEventAsynchronous(0, toRemove); 188 } 189 190 193 public void shutdown() { 194 if (bundleFileCloserManager != null) 195 bundleFileCloserManager.close(); 196 } 197 } 198 | Popular Tags |