1 19 20 package org.netbeans.core.startup.layers; 21 22 import java.io.File ; 23 import java.io.FileOutputStream ; 24 import java.io.IOException ; 25 import java.io.OutputStream ; 26 import java.io.UnsupportedEncodingException ; 27 import java.net.URL ; 28 import java.util.HashMap ; 29 import java.util.Iterator ; 30 import org.openide.filesystems.FileSystem; 31 32 40 public class BinaryCacheManager extends ParsingLayerCacheManager { 41 42 private static final String ALL_LAYERS = "all-layers.dat"; private File cacheFile; 44 45 46 public BinaryCacheManager(File cacheDir) throws IOException { 47 super(cacheDir); 48 cacheFile = new File (cacheDir, ALL_LAYERS); 49 } 50 51 public boolean cacheExists() { 52 return cacheFile.exists(); 53 } 54 55 private static int fileCounter; 56 57 public void cleanupCache() throws IOException { 58 if (cacheFile.exists()) { 59 File tmpFile = new File (cacheFile.getParentFile(), cacheFile.getName() + "." + fileCounter++); 61 tmpFile.delete(); boolean renamed = false; 63 for (int i = 0; i < 5; i++) { 64 renamed = cacheFile.renameTo(tmpFile); if (renamed) { 66 break; 67 } 68 LayerCacheManager.err.fine("cannot rename (#" + i + "): " + cacheFile); System.gc(); 71 System.runFinalization(); 72 LayerCacheManager.err.fine("after GC"); } 74 if (!renamed) { 75 cacheFile.deleteOnExit(); 77 throw new IOException ("Could not delete: " + cacheFile); } 79 if (!tmpFile.delete()) tmpFile.deleteOnExit(); } 81 } 82 83 public boolean supportsLoad() { 84 return false; 85 } 86 87 public FileSystem createLoadedFileSystem() throws IOException { 88 if (cacheFile.exists()) { 89 LayerCacheManager.err.fine("Loading from " + cacheFile); 90 FileSystem fs = new BinaryFS(cacheFile.getAbsolutePath()); 91 99 return fs; 100 } else { 101 throw new IllegalStateException (); 102 } 103 } 104 105 protected boolean openURLs() { 106 return false; 107 } 108 109 protected FileSystem store(MemFolder root) throws IOException { 110 cleanupCache(); OutputStream os = new FileOutputStream (cacheFile); 112 try { 113 sizes = new HashMap <MemFileOrFolder,Integer >(1000); 114 int fsSize = computeSize(root); 115 LayerCacheManager.err.fine("Writing binary layer cache of length " + (fsSize + BinaryFS.MAGIC.length) + " to " + cacheFile); 116 os.write(BinaryFS.MAGIC); 117 BinaryWriter bw = new BinaryWriter (os, root, fsSize); 118 writeFolder(bw, root); 119 } finally { 120 sizes = null; os.close(); 122 } 123 return createLoadedFileSystem(); 124 } 125 126 private void writeFolder(BinaryWriter bw, MemFolder folder) throws IOException { 127 if (folder.attrs != null) { 128 bw.writeInt(folder.attrs.size()); for (Iterator it = folder.attrs.iterator(); it.hasNext(); ) { 130 writeAttribute(bw, (MemAttr)it.next()); } 132 } else { 133 bw.writeInt(0); } 135 136 if (folder.children != null) { 137 bw.writeInt(folder.children.size()); int baseOffset = bw.getPosition(); 140 for (Iterator it = folder.children.iterator(); it.hasNext(); ) { 141 MemFileOrFolder item = (MemFileOrFolder)it.next(); 142 baseOffset += computeHeaderSize(item); 143 } 144 146 for (Iterator it = folder.children.iterator(); it.hasNext(); ) { 148 MemFileOrFolder item = (MemFileOrFolder)it.next(); 149 bw.writeString(item.name); bw.writeByte((item instanceof MemFile) ? (byte)0 : (byte)1); bw.writeInt(baseOffset); 153 baseOffset += computeSize(item); 154 } 156 157 for (Iterator it = folder.children.iterator(); it.hasNext(); ) { 159 MemFileOrFolder item = (MemFileOrFolder)it.next(); 160 if (item instanceof MemFile) { 162 writeFile(bw, (MemFile)item); 163 } else { 164 writeFolder(bw, (MemFolder)item); 165 } 166 } 167 168 } else { 169 bw.writeInt(0); } 171 } 172 173 private void writeFile(BinaryWriter bw, MemFile file) throws IOException { 174 if (file.attrs != null) { 175 bw.writeInt(file.attrs.size()); for (Iterator it = file.attrs.iterator(); it.hasNext(); ) { 177 writeAttribute(bw, (MemAttr)it.next()); } 179 } else { 180 bw.writeInt(0); } 182 183 if (file.ref != null) { 185 bw.writeInt(-1); bw.writeString(file.ref.toString()); 187 } else if (file.contents != null) { 188 bw.writeInt(file.contents.length); 189 bw.writeBytes(file.contents); 190 } else { 191 bw.writeInt(0); } 193 194 bw.writeBaseURL (file.base); 195 } 196 197 private final static String [] ATTR_TYPES = { 198 "bytevalue", "shortvalue", "intvalue", "longvalue", "floatvalue", "doublevalue", "boolvalue", "charvalue", "stringvalue", "urlvalue", "methodvalue", "newvalue", "serialvalue", }; 212 213 private void writeAttribute(BinaryWriter bw, MemAttr attr) throws IOException { 214 bw.writeString(attr.name); 215 int i = 0; 216 for(; i<ATTR_TYPES.length; i++) { 217 if(ATTR_TYPES[i].equals(attr.type)) break; 218 } 219 bw.writeByte((byte)i); bw.writeString(attr.data); 221 } 222 223 private HashMap <MemFileOrFolder,Integer > sizes; 225 226 private int computeSize(MemFileOrFolder mf) { 227 Integer i = sizes.get(mf); 228 if (i != null) return i; 229 230 int size = 4; if (mf.attrs != null) { 232 for (Iterator it = mf.attrs.iterator(); it.hasNext(); ) { 233 size += computeSize((MemAttr)it.next()); } 235 } 236 237 if (mf instanceof MemFile) { 238 MemFile file = (MemFile)mf; 239 size += 4; if (file.ref != null) { 241 size += computeSize(file.ref.toString()); } else if (file.contents != null) { 243 size += file.contents.length; 244 } size += 4; 247 } else { MemFolder folder = (MemFolder)mf; 249 size += 4; if (folder.children != null) { 251 for (MemFileOrFolder item : folder.children) { 252 size += computeHeaderSize(item); size += computeSize(item); } 255 } 256 } 257 sizes.put(mf, size); 258 return size; 259 } 260 261 private int computeHeaderSize(MemFileOrFolder mof) { 262 return computeSize(mof.name) + 1 + 4; 264 } 265 266 private static int computeSize(String s) { try { 268 return 4 + s.getBytes("UTF-8").length; } catch (UnsupportedEncodingException e) { 270 throw (IllegalStateException ) new IllegalStateException (e.toString()).initCause(e); 271 } 272 } 273 274 private int computeSize(MemAttr attr) { return computeSize(attr.name) + 1 + computeSize(attr.data); 276 } 277 278 private static final class BinaryWriter { 279 private OutputStream os; 280 private int position; 281 282 private java.util.Map urls; 283 BinaryWriter(OutputStream os, MemFolder root, int fsSize) throws IOException { 284 this.os = os; 285 urls = writeBaseUrls (root, fsSize); 286 position = 0; 287 } 288 289 int getPosition() { 290 return position; 291 } 292 293 void writeByte(byte b) throws IOException { 294 os.write(b); 295 position ++; 296 } 297 298 void writeBytes(byte[] bytes) throws IOException { 299 os.write(bytes); 300 position += bytes.length; 301 } 302 303 void writeInt(int num) throws IOException { 304 byte[] data = new byte[4]; 305 data[0] = (byte)num; 306 data[1] = (byte)(num >> 8); 307 data[2] = (byte)(num >> 16); 308 data[3] = (byte)(num >> 24); 309 writeBytes(data); 310 } 311 312 void writeString(String str) throws IOException { 313 byte[] data; 314 try { 315 data = str.getBytes("UTF-8"); } catch (UnsupportedEncodingException e) { 317 throw (IllegalStateException ) new IllegalStateException (e.toString()).initCause(e); 318 } 319 320 writeInt(data.length); 321 writeBytes(data); 322 } 323 324 void writeBaseURL (java.net.URL url) throws IOException { 325 int[] number = (int[])urls.get (url); 326 assert number != null : "Should not be null, because it was collected: " + url + " map: " + urls; 327 writeInt (number[0]); 328 } 329 330 private java.util.Map writeBaseUrls (MemFileOrFolder root, int fsSize) throws IOException { 331 java.util.LinkedHashMap <URL ,Object > map = new java.util.LinkedHashMap <URL ,Object > (); 332 int[] counter = new int[1]; 333 334 collectBaseUrls (root, map, counter); 335 336 int size = 0; 337 java.util.Iterator it = map.entrySet ().iterator (); 338 for (int i = 0; i < counter[0]; i++) { 339 java.util.Map.Entry entry = (java.util.Map.Entry)it.next (); 340 java.net.URL u = (java.net.URL )entry.getKey (); 341 342 assert ((int[])entry.getValue ())[0] == i : i + "th key should be it " + ((int[])entry.getValue ())[0]; 343 344 size += computeSize (u.toExternalForm ()); 345 } 346 347 writeInt(BinaryFS.MAGIC.length + 4 + 4 + size + fsSize); writeInt (size); 350 it = map.entrySet ().iterator (); 351 for (int i = 0; i < counter[0]; i++) { 352 java.util.Map.Entry entry = (java.util.Map.Entry)it.next (); 353 java.net.URL u = (java.net.URL )entry.getKey (); 354 355 writeString (u.toExternalForm ()); 356 } 357 return map; 358 } 359 360 private void collectBaseUrls (MemFileOrFolder f, java.util.Map <URL ,Object > map, int[] counter) { 361 if (f.base != null) { 362 int[] exists = (int[])map.get (f.base); 363 if (exists == null) { 364 map.put (f.base, counter.clone ()); 365 counter[0]++; 366 } 367 } 368 369 if (f instanceof MemFolder && ((MemFolder)f).children != null) { 370 Iterator it = ((MemFolder)f).children.iterator (); 371 while (it.hasNext ()) { 372 collectBaseUrls ((MemFileOrFolder)it.next (), map, counter); 373 } 374 } 375 } 376 } 377 378 } 379 | Popular Tags |