KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > core > startup > layers > BinaryCacheManager


1 /*
2  * The contents of this file are subject to the terms of the Common Development
3  * and Distribution License (the License). You may not use this file except in
4  * compliance with the License.
5  *
6  * You can obtain a copy of the License at http://www.netbeans.org/cddl.html
7  * or http://www.netbeans.org/cddl.txt.
8  *
9  * When distributing Covered Code, include this CDDL Header Notice in each file
10  * and include the License file at http://www.netbeans.org/cddl.txt.
11  * If applicable, add the following below the CDDL Header, with the fields
12  * enclosed by brackets [] replaced by your own identifying information:
13  * "Portions Copyrighted [year] [name of copyright owner]"
14  *
15  * The Original Software is NetBeans. The Initial Developer of the Original
16  * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
17  * Microsystems, Inc. All Rights Reserved.
18  */

19
20 package org.netbeans.core.startup.layers;
21
22 import java.io.File JavaDoc;
23 import java.io.FileOutputStream JavaDoc;
24 import java.io.IOException JavaDoc;
25 import java.io.OutputStream JavaDoc;
26 import java.io.UnsupportedEncodingException JavaDoc;
27 import java.net.URL JavaDoc;
28 import java.util.HashMap JavaDoc;
29 import java.util.Iterator JavaDoc;
30 import org.openide.filesystems.FileSystem;
31
32 /**
33  * Partial implementation of the cache manager using BinaryFS as the layer
34  * implementation. Still not fully working because current LayerCacheManager
35  * don't support replacing of the layer.
36  * Not optimalized yet!
37  *
38  * @author Petr Nejedly
39  */

40 public class BinaryCacheManager extends ParsingLayerCacheManager {
41
42     private static final String JavaDoc ALL_LAYERS = "all-layers.dat"; // NOI18N
43
private File JavaDoc cacheFile;
44     
45     /** Creates a new instance of BinaryCacheManager */
46     public BinaryCacheManager(File JavaDoc cacheDir) throws IOException JavaDoc {
47         super(cacheDir);
48         cacheFile = new File JavaDoc(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 JavaDoc {
58         if (cacheFile.exists()) {
59             // all of this mess is here because Windows can't delete mmaped file.
60
File JavaDoc tmpFile = new File JavaDoc(cacheFile.getParentFile(), cacheFile.getName() + "." + fileCounter++);
61             tmpFile.delete(); // delete any leftover file from previous session
62
boolean renamed = false;
63             for (int i = 0; i < 5; i++) {
64                 renamed = cacheFile.renameTo(tmpFile); // try to rename it
65
if (renamed) {
66                     break;
67                 }
68                 LayerCacheManager.err.fine("cannot rename (#" + i + "): " + cacheFile); // NOI18N
69
// try harder
70
System.gc();
71                 System.runFinalization();
72                 LayerCacheManager.err.fine("after GC"); // NOI18N
73
}
74             if (!renamed) {
75                 // still delete on exit, so next start is ok
76
cacheFile.deleteOnExit();
77                 throw new IOException JavaDoc("Could not delete: " + cacheFile); // NOI18N
78
}
79             if (!tmpFile.delete()) tmpFile.deleteOnExit(); // delete now or later
80
}
81     }
82     
83     public boolean supportsLoad() {
84         return false;
85     }
86     
87     public FileSystem createLoadedFileSystem() throws IOException JavaDoc {
88         if (cacheFile.exists()) {
89             LayerCacheManager.err.fine("Loading from " + cacheFile);
90             FileSystem fs = new BinaryFS(cacheFile.getAbsolutePath());
91             /* ???
92         // pre-enumerate interesting resources
93             Enumeration en = fs.findResource("Services").getChildren(true);
94 // Enumeration en = fs.getRoot().getChildren(true);
95             while (en.hasMoreElements()) {
96                 ((FileObject)en.nextElement()).getAttribute("");
97             }
98              */

99             return fs;
100         } else {
101             throw new IllegalStateException JavaDoc();
102         }
103     }
104
105     protected boolean openURLs() {
106         return false;
107     }
108
109     protected FileSystem store(MemFolder root) throws IOException JavaDoc {
110         cleanupCache(); // move old file out of the way
111
OutputStream JavaDoc os = new FileOutputStream JavaDoc(cacheFile);
112         try {
113             sizes = new HashMap JavaDoc<MemFileOrFolder,Integer JavaDoc>(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; // free the cache
121
os.close();
122         }
123         return createLoadedFileSystem();
124     }
125     
126     private void writeFolder(BinaryWriter bw, MemFolder folder) throws IOException JavaDoc {
127         if (folder.attrs != null) {
128             bw.writeInt(folder.attrs.size()); // attr count
129
for (Iterator JavaDoc it = folder.attrs.iterator(); it.hasNext(); ) {
130                 writeAttribute(bw, (MemAttr)it.next()); // write attrs
131
}
132         } else {
133             bw.writeInt(0); // no attrs
134
}
135         
136         if (folder.children != null) {
137             bw.writeInt(folder.children.size()); // file count
138
// compute len of all FileRefs
139
int baseOffset = bw.getPosition();
140             for (Iterator JavaDoc it = folder.children.iterator(); it.hasNext(); ) {
141                 MemFileOrFolder item = (MemFileOrFolder)it.next();
142                 baseOffset += computeHeaderSize(item);
143             }
144             // baseOffset now contains the offset of the first file content
145

146             // write file headers
147
for (Iterator JavaDoc it = folder.children.iterator(); it.hasNext(); ) {
148                 MemFileOrFolder item = (MemFileOrFolder)it.next();
149                 bw.writeString(item.name); // String name
150
bw.writeByte((item instanceof MemFile) ? (byte)0 : (byte)1); //boolean isFolder
151
bw.writeInt(baseOffset); // int contentRef
152

153                 baseOffset += computeSize(item);
154                 // baseOffset now contains the offset of the next file content
155
}
156
157             // write file/folder contents
158
for (Iterator JavaDoc it = folder.children.iterator(); it.hasNext(); ) {
159                 MemFileOrFolder item = (MemFileOrFolder)it.next();
160                 // TODO: can check the correctenss of the offsets now
161
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); // no files
170
}
171     }
172     
173     private void writeFile(BinaryWriter bw, MemFile file) throws IOException JavaDoc {
174         if (file.attrs != null) {
175             bw.writeInt(file.attrs.size()); // attr count
176
for (Iterator JavaDoc it = file.attrs.iterator(); it.hasNext(); ) {
177                 writeAttribute(bw, (MemAttr)it.next()); // write attrs
178
}
179         } else {
180             bw.writeInt(0); // no attrs
181
}
182         
183         // int contentLength | -1, byte[contentLength] content | String URL
184
if (file.ref != null) {
185             bw.writeInt(-1); // uri
186
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); // empty file
192
}
193
194         bw.writeBaseURL (file.base);
195     }
196
197     private final static String JavaDoc[] ATTR_TYPES = {
198         "bytevalue", // NOI18N
199
"shortvalue", // NOI18N
200
"intvalue", // NOI18N
201
"longvalue", // NOI18N
202
"floatvalue", // NOI18N
203
"doublevalue", // NOI18N
204
"boolvalue", // NOI18N
205
"charvalue", // NOI18N
206
"stringvalue", // NOI18N
207
"urlvalue", // NOI18N
208
"methodvalue", // NOI18N
209
"newvalue", // NOI18N
210
"serialvalue", // NOI18N
211
};
212
213     private void writeAttribute(BinaryWriter bw, MemAttr attr) throws IOException JavaDoc {
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); // XXX - may write wrong value if unknown type!
220
bw.writeString(attr.data);
221     }
222     
223     // this map is actually valid only during BFS regeneration, null otherwise
224
private HashMap JavaDoc<MemFileOrFolder,Integer JavaDoc> sizes;
225     
226     private int computeSize(MemFileOrFolder mf) {
227         Integer JavaDoc i = sizes.get(mf);
228         if (i != null) return i;
229
230         int size = 4; // int attrCount
231
if (mf.attrs != null) {
232             for (Iterator JavaDoc it = mf.attrs.iterator(); it.hasNext(); ) {
233                 size += computeSize((MemAttr)it.next()); // Attribute[attrCount] attrs
234
}
235         }
236
237         if (mf instanceof MemFile) {
238              MemFile file = (MemFile)mf;
239              size += 4; // int contentLength
240
if (file.ref != null) {
241                  size += computeSize(file.ref.toString()); // String uri
242
} else if (file.contents != null) {
243                  size += file.contents.length;
244              } // else size += 0; // no content, no uri
245
// index to url:
246
size += 4;
247         } else { // mf instanceof MemFolder
248
MemFolder folder = (MemFolder)mf;
249             size += 4; // int fileCount
250
if (folder.children != null) {
251                 for (MemFileOrFolder item : folder.children) {
252                     size += computeHeaderSize(item); // File[fileCount] references
253
size += computeSize(item); // File/FolderContent[fileCount] contents
254
}
255             }
256         }
257         sizes.put(mf, size);
258         return size;
259     }
260     
261     private int computeHeaderSize(MemFileOrFolder mof) {
262         // String name, boolean isFolder, int contentRef
263
return computeSize(mof.name) + 1 + 4;
264     }
265
266     private static int computeSize(String JavaDoc s) { // int len, byte[len] utf8
267
try {
268             return 4 + s.getBytes("UTF-8").length; // NOI18N
269
} catch (UnsupportedEncodingException JavaDoc e) {
270             throw (IllegalStateException JavaDoc) new IllegalStateException JavaDoc(e.toString()).initCause(e);
271         }
272     }
273     
274     private int computeSize(MemAttr attr) { //String name, byte type, String value
275
return computeSize(attr.name) + 1 + computeSize(attr.data);
276     }
277
278     private static final class BinaryWriter {
279         private OutputStream JavaDoc os;
280         private int position;
281         /** map from base URL to int[1] value */
282         private java.util.Map JavaDoc urls;
283         BinaryWriter(OutputStream JavaDoc os, MemFolder root, int fsSize) throws IOException JavaDoc {
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 JavaDoc {
294             os.write(b);
295             position ++;
296         }
297
298         void writeBytes(byte[] bytes) throws IOException JavaDoc {
299             os.write(bytes);
300             position += bytes.length;
301         }
302         
303         void writeInt(int num) throws IOException JavaDoc {
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 JavaDoc str) throws IOException JavaDoc {
313             byte[] data;
314             try {
315                 data = str.getBytes("UTF-8"); // NOI18N
316
} catch (UnsupportedEncodingException JavaDoc e) {
317                 throw (IllegalStateException JavaDoc) new IllegalStateException JavaDoc(e.toString()).initCause(e);
318             }
319             
320             writeInt(data.length);
321             writeBytes(data);
322         }
323         
324         void writeBaseURL (java.net.URL JavaDoc url) throws IOException JavaDoc {
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 JavaDoc writeBaseUrls (MemFileOrFolder root, int fsSize) throws IOException JavaDoc {
331             java.util.LinkedHashMap JavaDoc<URL JavaDoc,Object JavaDoc> map = new java.util.LinkedHashMap JavaDoc<URL JavaDoc,Object JavaDoc> ();
332             int[] counter = new int[1];
333             
334             collectBaseUrls (root, map, counter);
335             
336             int size = 0;
337             java.util.Iterator JavaDoc 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 JavaDoc u = (java.net.URL JavaDoc)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); // size of the whole image
348
writeInt (size); // the size of urls part
349

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 JavaDoc u = (java.net.URL JavaDoc)entry.getKey ();
354                 
355                 writeString (u.toExternalForm ());
356             }
357             return map;
358         }
359         
360         private void collectBaseUrls (MemFileOrFolder f, java.util.Map JavaDoc<URL JavaDoc,Object JavaDoc/*int[]*/> 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 JavaDoc 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