KickJava   Java API By Example, From Geeks To Geeks.

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


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.beans.PropertyVetoException JavaDoc;
23 import java.io.ByteArrayInputStream JavaDoc;
24 import java.io.File JavaDoc;
25 import java.io.FileNotFoundException JavaDoc;
26 import java.io.IOException JavaDoc;
27 import java.io.InputStream JavaDoc;
28 import java.io.OutputStream JavaDoc;
29 import java.io.RandomAccessFile JavaDoc;
30 import java.lang.reflect.Field JavaDoc;
31 import java.lang.reflect.Method JavaDoc;
32 import java.net.URL JavaDoc;
33 import java.nio.ByteBuffer JavaDoc;
34 import java.nio.ByteOrder JavaDoc;
35 import java.util.AbstractMap JavaDoc;
36 import java.util.AbstractSet JavaDoc;
37 import java.nio.MappedByteBuffer JavaDoc;
38 import java.nio.channels.FileChannel JavaDoc;
39 import java.util.ArrayList JavaDoc;
40 import java.util.Arrays JavaDoc;
41 import java.util.Collections JavaDoc;
42 import java.util.Date JavaDoc;
43 import java.util.Iterator JavaDoc;
44 import java.util.Enumeration JavaDoc;
45 import java.util.List JavaDoc;
46 import java.util.Set JavaDoc;
47 import java.util.HashMap JavaDoc;
48 import java.util.Map JavaDoc;
49 import java.util.StringTokenizer JavaDoc;
50 import java.util.logging.Level JavaDoc;
51 import java.util.logging.Logger JavaDoc;
52 import org.openide.filesystems.FileChangeListener;
53 import org.openide.filesystems.FileLock;
54 import org.openide.filesystems.FileObject;
55 import org.openide.filesystems.FileSystem;
56 import org.openide.util.Enumerations;
57 import org.openide.util.Exceptions;
58 import org.openide.util.Lookup;
59 import org.openide.util.SharedClassObject;
60 import org.openide.util.Union2;
61 import org.openide.util.actions.SystemAction;
62 import org.openide.util.io.NbObjectInputStream;
63
64 /**
65  * Read-only and fixed FileSystem over a binary file.
66  * Its content can't be changed in any way, it can only be replaced by a new
67  * instance over a different binary file.
68  *
69  * @author Petr Nejedly
70  */

71 public class BinaryFS extends FileSystem {
72     /* Format:
73      * MAGIC
74      * 4B length of the full image
75      * 4B offset to the start of the FS data (beyond modifications list)
76      * Modifications list
77      * FS data
78      */

79
80     static final byte[] MAGIC = "org.netbeans.core.projects.cache.BinaryV3".getBytes(); // NOI18N
81

82     /** An empty array of SystemActions. */
83     static final SystemAction[] NO_ACTIONS = new SystemAction[0];
84
85     /** An empty array of FileObjects. */
86     static final FileObject[] NO_CHILDREN = new FileObject[0];
87
88     String JavaDoc binaryFile;
89
90     // a template-buffer. Should not be operated directly, only duplicated.
91
ByteBuffer JavaDoc content;
92
93     private FileObject root;
94     /** list of URLs or time of their modification */
95     private List JavaDoc<Union2<String JavaDoc,Long JavaDoc>> modifications;
96     private final Date JavaDoc lastModified = new Date JavaDoc();
97
98     @SuppressWarnings JavaDoc("deprecation")
99     private void _setSystemName(String JavaDoc s) throws PropertyVetoException JavaDoc {
100         setSystemName(s);
101     }
102
103     /** Creates a new instance of BinaryFS */
104     public BinaryFS(String JavaDoc binaryFile) throws IOException JavaDoc {
105         try {
106             _setSystemName("BinaryFS" + binaryFile.replace('/', '-').replace(File.separatorChar, '-')); // NOI18N
107
} catch (PropertyVetoException JavaDoc ex) {
108             throw (IOException JavaDoc)new IOException JavaDoc().initCause(ex);
109         }
110         this.binaryFile = binaryFile;
111         RandomAccessFile JavaDoc file = new RandomAccessFile JavaDoc(binaryFile, "r"); // NOI18N
112
long len = file.length();
113         MappedByteBuffer JavaDoc buff = file.getChannel().map(FileChannel.MapMode.READ_ONLY, 0, len);
114         buff.order(ByteOrder.LITTLE_ENDIAN);
115         file.close();
116
117         // verify the magic in header and expected image length
118
byte[] magic = new byte[MAGIC.length];
119         buff.get(magic);
120         if (!Arrays.equals(magic, MAGIC)) {
121             throw new IOException JavaDoc("Bad magic header: " + new String JavaDoc(magic)); // NOI18N
122
}
123         long storedLen = buff.getInt();
124         if (len != storedLen) {
125             throw new IOException JavaDoc("Corrupted image, correct length=" + storedLen); // NOI18N
126
}
127
128
129         // fill the modifications array
130
int stop = buff.getInt() + 8 + MAGIC.length;
131         modifications = new ArrayList JavaDoc<Union2<String JavaDoc,Long JavaDoc>>();
132         while (buff.position() < stop) {
133             modifications.add(Union2.<String JavaDoc,Long JavaDoc>createFirst(getString(buff)));
134         }
135
136
137         // prepare the content buffer and root
138
content = buff.slice().order(ByteOrder.LITTLE_ENDIAN);
139         root = new BFSFolder("", null, 0);
140     }
141
142     /** Finds a file given its full resource path.
143      * @param name the resource path, e.g. "dir/subdir/file.ext" or "dir/subdir" or "dir"
144      * @return a file object with the given path or
145      * <CODE>null</CODE> if no such file exists
146      *
147      */

148     public FileObject findResource(String JavaDoc name) {
149         if (name.length () == 0) {
150             return root;
151         }
152
153         StringTokenizer JavaDoc st = new StringTokenizer JavaDoc(name, "/");
154         FileObject fo = root;
155         while (fo != null && st.hasMoreTokens()) {
156             String JavaDoc next = st.nextToken();
157             fo = fo.getFileObject(next, null); // XXX ??
158
}
159
160         return fo;
161     }
162
163     /** Returns an array of actions that can be invoked on any file in
164      * this filesystem.
165      * These actions should preferably
166      * support the {@link org.openide.util.actions.Presenter.Menu Menu},
167      * {@link org.openide.util.actions.Presenter.Popup Popup},
168      * and {@link org.openide.util.actions.Presenter.Toolbar Toolbar} presenters.
169      *
170      * @return array of available actions
171      *
172      */

173     public SystemAction[] getActions() {
174         return NO_ACTIONS;
175     }
176
177     /** Provides a name for the system that can be presented to the user.
178      * <P>
179      * This call should <STRONG>never</STRONG> be used to attempt to identify the file root
180      * of the filesystem. On some systems it may happen to look the same but this is a
181      * coincidence and may well change in the future. Either check whether
182      * you are working with a {@link org.openide.filesystems.LocalFileSystem} or similar implementation and use
183      * {@link org.openide.filesystems.LocalFileSystem#getRootDirectory}; or better, try
184      * {@link org.openide.filesystems.FileUtil#toFile} which is designed to do this correctly.
185      *
186      * @return user presentable name of the filesystem
187      *
188      */

189     public String JavaDoc getDisplayName() {
190         return "BinaryFS[" + binaryFile + "]";
191     }
192
193     /** Getter for root folder in the filesystem.
194      *
195      * @return root folder of whole filesystem
196      *
197      */

198     public FileObject getRoot() {
199 // System.err.println("returning root: " + root);
200
return root;
201     }
202
203     /** Test if the filesystem is read-only or not.
204      * @return true if the system is read-only
205      *
206      */

207     public boolean isReadOnly() {
208         return true;
209     }
210
211     static String JavaDoc getString(ByteBuffer JavaDoc buffer) throws IOException JavaDoc {
212         int len = buffer.getInt();
213         byte[] arr = new byte[len];
214         buffer.get(arr);
215         return new String JavaDoc(arr, "UTF-8"); //.intern();
216
}
217
218
219     /** Base class for read-only FileObject, both file and folder
220      * Handles common operations and throws exception for any modification
221      * attempt.
222      * Also handles attribute reading/parsing.
223      * The layout in the bfs file is (beggining from the offset):
224      * <pre>
225      * int attrCount
226      * Attribute[attrCount] attrs
227      * int fileCount/filesize
228      * content
229      * </pre>
230      */

231     private abstract class BFSBase extends FileObject { // PENDING make static to save references
232
// fields from the constructor
233
private final FileObject parent;
234         protected final String JavaDoc name;
235         protected final int offset;
236
237         // fetched fields
238
private boolean initialized = false;
239         private Map JavaDoc<String JavaDoc, AttrImpl> attrs = Collections.emptyMap();
240
241         public BFSBase(String JavaDoc name, FileObject parent, int offset) {
242             this.name = name;
243             this.parent = parent;
244             this.offset = offset;
245         }
246
247         public final boolean equals(Object JavaDoc o) {
248             if (!(o instanceof BFSBase)) return false;
249             if (o == this) return true;
250             BFSBase f = (BFSBase)o;
251             return f.getPath().equals(getPath()) && specificEquals(f) && attributeEquals(f);
252         }
253
254         private final boolean attributeEquals(BFSBase base) {
255             initialize();
256             base.initialize();
257             return attrs.equals(base.attrs);
258         }
259
260         public final int hashCode() {
261             return getPath().hashCode();
262         }
263
264         protected abstract boolean specificEquals(BFSBase f);
265
266         /** no-op implementations of read-only, fixed, never firing FS */
267         public void addFileChangeListener(FileChangeListener fcl) {}
268         public void removeFileChangeListener(FileChangeListener fcl) {}
269         @Deprecated JavaDoc
270         public boolean isReadOnly() { return true; }
271         @Deprecated JavaDoc
272         public void setImportant(boolean b) {}
273
274         public FileObject createData(String JavaDoc name, String JavaDoc ext) throws IOException JavaDoc {
275             throw new IOException JavaDoc(); // Read-only
276
}
277         public FileObject createFolder(String JavaDoc name) throws IOException JavaDoc {
278             throw new IOException JavaDoc(); // Read-only
279
}
280         public void delete(FileLock lock) throws IOException JavaDoc {
281             throw new IOException JavaDoc(); // Read-only
282
}
283         public OutputStream JavaDoc getOutputStream(FileLock lock) throws java.io.IOException JavaDoc {
284             throw new IOException JavaDoc(); // Read-only
285
}
286         public FileLock lock() throws IOException JavaDoc {
287             throw new IOException JavaDoc(); // Read-only
288
}
289         public void rename(FileLock lock, String JavaDoc name, String JavaDoc ext) throws IOException JavaDoc {
290             throw new IOException JavaDoc(); // Read-only
291
}
292         public void setAttribute(String JavaDoc attrName, Object JavaDoc value) throws IOException JavaDoc {
293             throw new IOException JavaDoc(); // Read-only
294
}
295
296
297         // simple common implementations:
298

299         /** Get the filesystem containing this file. */
300         public FileSystem getFileSystem() {
301             return BinaryFS.this;
302         }
303
304         /** Get the parent folder. */
305         public FileObject getParent() {
306             return parent;
307         }
308
309         /** Test whether this object is the root folder. */
310         public boolean isRoot() {
311             return parent == null;
312         }
313
314         public boolean isValid() {
315             return true;
316         }
317
318         /** Get last modification time. */
319         public java.util.Date JavaDoc lastModified() {
320             return lastModified;
321         }
322
323         /** Get the name without extension of this file or folder. */
324         public String JavaDoc getName () {
325             int i = name.lastIndexOf ('.');
326             return i <= 0 ? name : name.substring (0, i);
327         }
328
329         /** Get the extension of this file or folder. */
330         public String JavaDoc getExt () {
331             int i = name.lastIndexOf ('.') + 1;
332             return i <= 1 || i == name.length () ? "" : name.substring (i); // NOI18N
333
}
334
335         /** Getter for name and extension of a file object. */
336         public String JavaDoc getNameExt () {
337             return name;
338         }
339
340         // Attributes implementation:
341

342         /** Get the file attribute with the specified name. */
343         public Object JavaDoc getAttribute(String JavaDoc attrName) {
344             initialize();
345             AttrImpl attr = attrs.get(attrName);
346             return (attr != null) ? attr.getValue(this, attrName) : null;
347         }
348         
349         public FileObject getFileObjectForAttr() {
350             FileObject topFO = null;
351             // XXX big hack! See #29356 for explanation for this nonsense.
352
try {
353                 Class JavaDoc mfoClass = Class.forName("org.openide.filesystems.MultiFileObject"); //NOI18N
354
Field JavaDoc field = mfoClass.getDeclaredField("attrAskedFileObject"); //NOI18N
355
field.setAccessible(true);
356
357                 ThreadLocal JavaDoc<?> attrAskedFileObject = ThreadLocal JavaDoc.class.cast(field.get(null));
358                 topFO = (FileObject)attrAskedFileObject.get();
359                 attrAskedFileObject.set(null);
360             } catch (Exception JavaDoc e) {
361                 Exceptions.printStackTrace(e);
362             }
363
364             return topFO == null ? this : topFO;
365         }
366
367         /** Get all file attribute names for this file. */
368         public Enumeration JavaDoc<String JavaDoc> getAttributes() {
369             initialize();
370             if (attrs == null) {
371                 return Enumerations.empty();
372             }
373             return Collections.enumeration(attrs.keySet());
374         }
375
376         /**
377          * A method for fetching/parsing the content of the file/folder
378          * to the memory. Should be called before any access operation
379          * to check the content of the entity.
380          */

381         protected final void initialize() {
382             if (initialized) return;
383
384             try {
385                 ByteBuffer JavaDoc sub = (ByteBuffer JavaDoc)content.duplicate().order(ByteOrder.LITTLE_ENDIAN).position(offset);
386                 int attrCount = sub.getInt();
387                 if (attrCount > 0) attrs = new HashMap JavaDoc<String JavaDoc, AttrImpl>(attrCount*4/3+1);
388
389                 for (int i=0; i< attrCount; i++) { // do read attribute
390
// attribute names are highly duplicated, intern!
391
String JavaDoc name = getString(sub).intern(); // String attrName
392
byte type = sub.get(); // byte attrType
393
// values have high redundancy as well,
394
// like "true", "JSeparator", paths to orig files from
395
// shadow, ...
396
String JavaDoc value = getString(sub).intern(); // String attrValue
397
attrs.put(name, new AttrImpl(type, value));
398                 }
399
400                 doInitialize(sub);
401             } catch (Exception JavaDoc e) {
402                 System.err.println("exception in initialize() on " + name + ": " + e);
403             }
404             initialized = true;
405         }
406
407         /** A method called to finish the initialization in the subclasses.
408          * When this method is called, the contentOffset field is already set up.
409          */

410         protected abstract void doInitialize(ByteBuffer JavaDoc sub) throws Exception JavaDoc;
411     }
412
413     static final class AttrImpl {
414         private int index;
415         private String JavaDoc value;
416
417         AttrImpl(int type, String JavaDoc textValue) {
418             index = type;
419             value = textValue;
420         }
421
422         public boolean equals(Object JavaDoc o) {
423             if (o instanceof AttrImpl) {
424                 AttrImpl impl = (AttrImpl)o;
425                 return index == impl.index && value.equals(impl.value);
426             }
427             return false;
428         }
429
430         public int hashCode() {
431             return 2343 + index + value.hashCode();
432         }
433
434         public Object JavaDoc getValue( BFSBase foProvider, String JavaDoc attrName) {
435             try {
436                 switch(index) {
437                     case 0: // bytevalue
438
return Byte.valueOf(value);
439                     case 1: // shortvalue
440
return Short.valueOf(value);
441                     case 2: // intvalue
442
return Integer.valueOf(value);
443                     case 3: // longvalue
444
return Long.valueOf(value);
445                     case 4: // floatvalue
446
return Float.valueOf(value);
447                     case 5: // doublevalue
448
return Double.valueOf(value);
449                     case 6: // boolvalue
450
return Boolean.valueOf(value);
451                     case 7: // charvalue
452
if (value.trim().length() != 1) break;
453                         return new Character JavaDoc(value.charAt(0));
454                     case 8: // stringvalue
455
return value;
456                     case 9: // urlvalue
457
return new URL JavaDoc(value);
458                     case 10: // methodvalue
459
return methodValue (value,foProvider,attrName);
460                     case 11: // newvalue
461
Class JavaDoc<?> cls = findClass (value);
462                         // special support for singletons
463
if (SharedClassObject.class.isAssignableFrom(cls)) {
464                             return SharedClassObject.findObject(cls.asSubclass(SharedClassObject.class), true);
465                         } else {
466                             return cls.newInstance();
467                         }
468
469                     case 12: // serialvalue
470
return decodeValue(value);
471                     default:
472                         throw new IllegalStateException JavaDoc("Bad index: " + index); // NOI18N
473
}
474             } catch (Exception JavaDoc exc) {
475                 Exceptions.attachLocalizedMessage(exc, "value = " + value); //NOI18N
476
Logger.getLogger(BinaryFS.class.getName()).log(Level.WARNING, null, exc);
477             }
478             return null; // problem getting the value...
479
}
480
481         /** Constructs new attribute as Object. Used for dynamic creation: methodvalue. */
482         private Object JavaDoc methodValue(String JavaDoc method, BFSBase foProvider, String JavaDoc attr) throws Exception JavaDoc {
483             String JavaDoc className,methodName;
484             int i = method.lastIndexOf('.');
485             if (i != -1) {
486                 methodName = value.substring(i+1);
487                 className = value.substring(0,i);
488                 Class JavaDoc cls = findClass (className);
489
490                 Object JavaDoc objArray[][] = {null,null,null};
491                 Method JavaDoc methArray[] = {null,null,null};
492
493                 FileObject fo = null;
494
495                 Method JavaDoc[] allMethods = cls.getDeclaredMethods();
496                 Class JavaDoc<?>[] paramClss;
497
498                 for (int j=0; j < allMethods.length; j++) {
499                     if (!allMethods[j].getName().equals(methodName)) continue;
500
501                     paramClss = allMethods[j].getParameterTypes();
502                     if (paramClss.length == 0) {
503                         if (methArray[0] == null) {
504                             methArray[0] = allMethods[j];
505                             objArray[0] = new Object JavaDoc[] {};
506                             continue;
507                         }
508                         continue;
509                     }
510
511                     if (paramClss.length == 2 && methArray[2] == null) {
512                         if (paramClss[0].isAssignableFrom(FileObject.class) && paramClss[1].isAssignableFrom(String JavaDoc.class)) {
513                             methArray[2] = allMethods[j];
514                             if (fo == null) fo = foProvider.getFileObjectForAttr();
515                             objArray[2] = new Object JavaDoc[] {fo,attr};
516                             break;
517                         }
518                         if (paramClss[0].isAssignableFrom(Map JavaDoc.class) && paramClss[1].isAssignableFrom(String JavaDoc.class)) {
519                             methArray[2] = allMethods[j];
520                             if (fo == null) fo = foProvider.getFileObjectForAttr();
521                             objArray[2] = new Object JavaDoc[]{wrapToMap(fo),attr};
522                         }
523
524                         if (paramClss[0].isAssignableFrom(String JavaDoc.class) && paramClss[1].isAssignableFrom(FileObject.class)) {
525                             methArray[2] = allMethods[j];
526                             if (fo == null) fo = foProvider.getFileObjectForAttr();
527                             objArray[2] = new Object JavaDoc[] {attr,fo};
528                             break;
529                         }
530                         continue;
531                     }
532
533                     if (paramClss.length == 1 && methArray[1] == null) {
534                         if (paramClss[0].isAssignableFrom(FileObject.class)) {
535                             methArray[1] = allMethods[j];
536                             if (fo == null) fo = foProvider.getFileObjectForAttr();
537                             objArray[1] = new Object JavaDoc[] {fo};
538                             continue;
539                         }
540                         if (paramClss[0].isAssignableFrom(Map JavaDoc.class)) {
541                             methArray[2] = allMethods[j];
542                             if (fo == null) fo = foProvider.getFileObjectForAttr();
543                             objArray[2] = new Object JavaDoc[]{wrapToMap(fo)};
544                         }
545
546                         if (paramClss[0].isAssignableFrom(String JavaDoc.class)) {
547                             methArray[1] = allMethods[j];
548                             objArray[1] = new Object JavaDoc[] {attr};
549                             continue;
550                         }
551                         continue;
552                     }
553                 }
554
555                 for (int k = 2; k >= 0; k-- ) {//clsArray.length
556
if (methArray[k] != null) {
557                         //Method meth = cls.getDeclaredMethod(methodName,clsArray[k]);
558
methArray[k].setAccessible(true); //otherwise cannot invoke private
559
return methArray[k].invoke(null,objArray[k]);
560                     }
561                 }
562             }
563             // Some message to logFile
564
throw new InstantiationException JavaDoc (value);
565         }
566
567         private Object JavaDoc decodeValue(String JavaDoc value) throws Exception JavaDoc {
568             if ((value == null) ||(value.length() == 0)) return null;
569
570             byte[] bytes = new byte[value.length()/2];
571             int count = 0;
572             for (int i = 0; i < value.length(); i += 2) {
573                 // way from effective!!!!!
574
int tempI = Integer.parseInt(value.substring(i,i+2),16);
575                 if (tempI > 127) tempI -=256; // ?? necessary ??
576
bytes[count++] = (byte) tempI;
577             }
578
579             ByteArrayInputStream JavaDoc bis = new ByteArrayInputStream JavaDoc(bytes, 0, count);
580             return new NbObjectInputStream(bis).readObject();
581         }
582
583         /** Loads a class of given name
584          * @param name name of the class
585          * @return the class
586          * @exception ClassNotFoundException if class was not found
587          */

588         private Class JavaDoc findClass (String JavaDoc name) throws ClassNotFoundException JavaDoc {
589             ClassLoader JavaDoc c = Lookup.getDefault().lookup(ClassLoader JavaDoc.class);
590             String JavaDoc tname = org.openide.util.Utilities.translate (name);
591             try {
592                 if (c == null) {
593                     return Class.forName (tname);
594                 } else {
595                     return Class.forName (tname, true, c);
596                 }
597             } catch (NoClassDefFoundError JavaDoc err) {
598                 throw new ClassNotFoundException JavaDoc ("Cannot read " + name, err);
599             }
600         }
601     }
602
603
604     /** FileContent:
605           int attrCount
606           Attribute[attrCount] attrs
607           int contentLength (or -1 for uri)
608           byte[contentLength] content (or String uri)
609      */

610     final class BFSFile extends BFSBase {
611         private int len;
612         private int contentOffset;
613         private String JavaDoc uri;
614         private long lastModified = -1;
615
616         public BFSFile(String JavaDoc name, FileObject parent, int offset) {
617             super(name, parent, offset);
618         }
619
620
621         /** Get all children of this folder (files and subfolders). */
622         public FileObject[] getChildren() {
623             return NO_CHILDREN;
624         }
625
626         /** Retrieve file or folder contained in this folder by name. */
627         public FileObject getFileObject(String JavaDoc name, String JavaDoc ext) {
628             return null; // File have no children
629
}
630
631         /** Test whether this object is a data object. */
632         public boolean isData() {
633             return true;
634         }
635
636         /** Test whether this object is a folder. */
637         public boolean isFolder() {
638             return false;
639         }
640
641         private byte[] data() throws IOException JavaDoc {
642             if (len == -1) throw new IllegalArgumentException JavaDoc();
643             byte[] data = new byte[len];
644             ((ByteBuffer JavaDoc)content.duplicate().position(contentOffset)).get(data);
645             return data;
646         }
647
648         /** Get input stream. */
649         public InputStream JavaDoc getInputStream() throws java.io.FileNotFoundException JavaDoc {
650             initialize();
651             try {
652                 return len == -1 ? // URI or not
653
new URL JavaDoc(uri).openConnection().getInputStream() : // len from URI
654
new ByteArrayInputStream JavaDoc(data());
655             } catch (Exception JavaDoc e) {
656                 throw (FileNotFoundException JavaDoc) new FileNotFoundException JavaDoc(e.toString()).initCause(e);
657             }
658         }
659
660         /** Get the size of the file. */
661         public long getSize() {
662             initialize();
663             try {
664                 return len == -1 ? // URI or not
665
new URL JavaDoc(uri).openConnection().getContentLength() : // len from URI
666
len; // len from dump
667
} catch (Exception JavaDoc e) {
668                 System.err.println("exception in getSize() on " + name + ": " + e);
669                 return 0;
670             }
671         }
672
673         /** A method called to finish the initialization in the subclasses.
674          * When this method is called, the contentOffset field is already set up.
675          *
676          * the rest of the FileContent:
677          * int contentLength (or -1)
678          * byte[contentLength] content (or String uri);
679          */

680         protected void doInitialize(ByteBuffer JavaDoc sub) throws Exception JavaDoc {
681             len = sub.getInt();;
682             contentOffset = sub.position();
683             if (len == -1) {
684                 uri = getString(sub);
685             } else {
686                 sub.position(contentOffset+len);
687             }
688             int base = sub.getInt ();
689             lastModified = -10 - base;
690         }
691
692         // equals compares data: URI or byte contents.
693

694         protected boolean specificEquals(BFSBase _f) {
695             if (!(_f instanceof BFSFile)) return false;
696             BFSFile f = (BFSFile)_f;
697             initialize();
698             f.initialize();
699             if (len == -1 && f.len == -1) {
700                 return uri.equals(f.uri);
701             } else if (len != -1 && f.len != -1) {
702                 byte[] data, fdata;
703                 try {
704                     data = data();
705                     fdata = f.data();
706                 } catch (IOException JavaDoc ioe) {
707                     return false;
708                 }
709                 if (data.length != fdata.length) return false;
710                 for (int i = 0; i < data.length; i++) {
711                     if (data[i] != fdata[i]) return false;
712                 }
713                 return true;
714             } else {
715                 return false;
716             }
717         }
718
719         public Date JavaDoc lastModified() {
720             initialize();
721             synchronized (modifications) {
722                 if (lastModified >= 0) {
723                     return new Date JavaDoc(lastModified);
724                 }
725                 try {
726                     int index = -1;
727                     java.net.URLConnection JavaDoc conn = null;
728                     if (len == -1) {
729                         conn = new URL JavaDoc(uri).openConnection ();
730                     } else {
731                         index = ((int)-lastModified) - 10;
732                         Union2<String JavaDoc,Long JavaDoc> obj = modifications.get(index);
733                         if (obj.hasSecond()) {
734                             return new Date JavaDoc(obj.second());
735                         }
736                         conn = new URL JavaDoc(obj.first()).openConnection();
737                     }
738
739                     if (conn instanceof java.net.JarURLConnection JavaDoc) {
740                         conn = ((java.net.JarURLConnection JavaDoc)conn).getJarFileURL ().openConnection ();
741                     }
742
743                     if (conn != null) {
744                         long date = conn.getLastModified ();
745                         if (date > 0) {
746
747                             lastModified = date;
748                             if (index >= 0) {
749                                 modifications.set(index, Union2.<String JavaDoc,Long JavaDoc>createSecond(date));
750                             }
751                             return new Date JavaDoc(date);
752                         }
753                     }
754                 } catch (Exception JavaDoc e) {
755                     Logger.getLogger(BinaryFS.class.getName()).log(Level.WARNING, null, e);
756                 }
757             }
758             return super.lastModified ();
759         }
760     }
761
762     private class BFSFolder extends BFSBase {
763         Map JavaDoc<String JavaDoc,BFSBase> childrenMap = Collections.<String JavaDoc,BFSBase>emptyMap();
764
765         public BFSFolder(String JavaDoc name, FileObject parent, int offset) {
766             super(name, parent, offset);
767         }
768
769         /** Test whether this object is a data object. */
770         public boolean isData() {
771             return false;
772         }
773
774         /** Test whether this object is a folder. */
775         public boolean isFolder() {
776             return true;
777         }
778
779         /** Get the size of the file. */
780         public long getSize() {
781             return 0; // Folder is zero
782
}
783
784         /** Get input stream. */
785         public InputStream JavaDoc getInputStream() throws java.io.FileNotFoundException JavaDoc {
786             throw new FileNotFoundException JavaDoc("Is a directory: " + this);
787         }
788
789
790         /** Get all children of this folder (files and subfolders). */
791         public FileObject[] getChildren() {
792             initialize();
793             return childrenMap.values().toArray(NO_CHILDREN);
794         }
795
796         /** Retrieve file or folder contained in this folder by name. */
797         public FileObject getFileObject(String JavaDoc name, String JavaDoc ext) {
798             initialize();
799             String JavaDoc fullName = ext == null ? name : name + "." + ext; // XXX - ??
800
return childrenMap.get(fullName);
801         }
802
803         /** A method called to finish the initialization in the subclasses.
804          * When this method is called, the contentOffset field is already set up.
805          *
806          * the rest of the FolderContent:
807          * int fileCount
808          * File[fileCount] references
809          * File/FolderContent[fileCount] contents
810          */

811         protected void doInitialize(ByteBuffer JavaDoc sub) throws Exception JavaDoc {
812             int files = sub.getInt();
813             if (files > 0) {
814                 childrenMap = new HashMap JavaDoc<String JavaDoc,BFSBase>(files*4/3+1);
815                 for (int i=0; i<files; i++) { //read file desc:
816
String JavaDoc name = getString(sub); // String name
817
byte isFolder = sub.get(); // boolean isFolder
818
int off = sub.getInt(); // int contentRef
819
childrenMap.put(name, isFolder == 0 ?
820                         new BFSFile(name, this, off) :
821                         new BFSFolder(name, this, off));
822                 }
823             }
824         }
825
826         // equals compares contents recursively.
827

828         protected boolean specificEquals(BFSBase _f) {
829             if (!(_f instanceof BFSFolder)) return false;
830             BFSFolder f = (BFSFolder)_f;
831             initialize();
832             return childrenMap.equals(f.childrenMap);
833         }
834
835     }
836
837     static final Map JavaDoc wrapToMap(FileObject fo) {
838         return fo == null ? Collections.emptyMap() : new FileMap(fo);
839     }
840
841
842     private static final class FileMap extends AbstractMap JavaDoc<String JavaDoc,Object JavaDoc> {
843         private FileObject fo;
844
845         private FileMap(FileObject fo) {
846             this.fo = fo;
847         }
848
849         public Set JavaDoc<Map.Entry JavaDoc<String JavaDoc,Object JavaDoc>> entrySet() {
850             return new AttrFileSet(fo);
851         }
852
853         public Object JavaDoc get(String JavaDoc key) {
854             return fo.getAttribute(key);
855         }
856
857         public Object JavaDoc remove(Object JavaDoc key) {
858             throw new UnsupportedOperationException JavaDoc();
859         }
860
861         public Object JavaDoc put(String JavaDoc key, Object JavaDoc value) {
862             throw new UnsupportedOperationException JavaDoc();
863         }
864
865     }
866     private static final class AttrFileSet extends AbstractSet JavaDoc<Map.Entry JavaDoc<String JavaDoc,Object JavaDoc>> {
867         private FileObject fo;
868
869         private AttrFileSet(FileObject fo) {
870             this.fo = fo;
871         }
872
873         public Iterator JavaDoc<Map.Entry JavaDoc<String JavaDoc, Object JavaDoc>> iterator() {
874             class Iter implements Iterator JavaDoc<Map.Entry JavaDoc<String JavaDoc, Object JavaDoc>> {
875                 Enumeration JavaDoc<String JavaDoc> attrs = fo.getAttributes();
876
877                 public boolean hasNext() {
878                     return attrs.hasMoreElements();
879                 }
880
881                 public Map.Entry JavaDoc<String JavaDoc, Object JavaDoc> next() {
882                     String JavaDoc s = attrs.nextElement();
883                     return new FOEntry(fo, s);
884                 }
885
886                 public void remove() {
887                     throw new UnsupportedOperationException JavaDoc();
888                 }
889             }
890             return new Iter();
891         }
892
893         public int size() {
894             Enumeration JavaDoc<String JavaDoc> all = fo.getAttributes();
895             int cnt = 0;
896             while (all.hasMoreElements()) {
897                 cnt++;
898                 all.nextElement();
899             }
900             return cnt;
901         }
902
903         public boolean remove(Object JavaDoc o) {
904             throw new UnsupportedOperationException JavaDoc();
905         }
906     } // end of AttrFileSet
907

908     private static final class FOEntry implements Map.Entry JavaDoc<String JavaDoc, Object JavaDoc> {
909         private FileObject fo;
910         private String JavaDoc attr;
911
912         private FOEntry(FileObject fo, String JavaDoc attr) {
913             this.fo = fo;
914             this.attr = attr;
915         }
916
917         public String JavaDoc getKey() {
918             return attr;
919         }
920
921         public Object JavaDoc getValue() {
922             return fo.getAttribute(attr);
923         }
924
925         public Object JavaDoc setValue(Object JavaDoc value) {
926             throw new UnsupportedOperationException JavaDoc();
927         }
928     } // end of FOEntry
929
}
930
Popular Tags