KickJava   Java API By Example, From Geeks To Geeks.

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


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.ByteArrayInputStream JavaDoc;
23 import java.io.File JavaDoc;
24 import java.io.IOException JavaDoc;
25 import java.io.InputStream JavaDoc;
26 import java.net.MalformedURLException JavaDoc;
27 import java.net.URL JavaDoc;
28 import java.net.URLConnection JavaDoc;
29 import java.util.ArrayList JavaDoc;
30 import java.util.Arrays JavaDoc;
31 import java.util.Collections JavaDoc;
32 import java.util.HashSet JavaDoc;
33 import java.util.Iterator JavaDoc;
34 import java.util.LinkedList JavaDoc;
35 import java.util.List JavaDoc;
36 import java.util.Set JavaDoc;
37 import java.util.Stack JavaDoc;
38 import java.util.logging.Level JavaDoc;
39 import org.openide.filesystems.FileSystem;
40 import org.openide.util.NotImplementedException;
41 import org.openide.xml.XMLUtil;
42 import org.xml.sax.Attributes JavaDoc;
43 import org.xml.sax.ContentHandler JavaDoc;
44 import org.xml.sax.EntityResolver JavaDoc;
45 import org.xml.sax.ErrorHandler JavaDoc;
46 import org.xml.sax.InputSource JavaDoc;
47 import org.xml.sax.Locator JavaDoc;
48 import org.xml.sax.SAXException JavaDoc;
49 import org.xml.sax.SAXParseException JavaDoc;
50 import org.xml.sax.XMLReader JavaDoc;
51
52 /** A cache manager which parses the layers according to the Filesystems 1.x DTDs.
53  * This class just handles the parsing during cache rewrite time; subclasses are
54  * responsible for loading from and saving to the storage format.
55  * @author Jesse Glick
56  */

57 public abstract class ParsingLayerCacheManager extends LayerCacheManager implements ContentHandler JavaDoc, ErrorHandler JavaDoc, EntityResolver JavaDoc {
58     
59     private final static String JavaDoc[] ATTR_TYPES = {
60         "boolvalue",
61         "bytevalue",
62         "charvalue",
63         "doublevalue",
64         "floatvalue",
65         "intvalue",
66         "longvalue",
67         "methodvalue",
68         "newvalue",
69         "serialvalue",
70         "shortvalue",
71         "stringvalue",
72         "urlvalue"
73     };
74     
75     private final static String JavaDoc DTD_1_0 = "-//NetBeans//DTD Filesystem 1.0//EN";
76     private final static String JavaDoc DTD_1_1 = "-//NetBeans//DTD Filesystem 1.1//EN";
77     
78     private Locator JavaDoc locator;
79     private MemFolder root;
80     private Stack JavaDoc<Object JavaDoc> curr; // Stack<MemFileOrFolder | MemAttr>
81
private URL JavaDoc base;
82     private StringBuffer JavaDoc buf = new StringBuffer JavaDoc();
83     private int fileCount, folderCount, attrCount;
84     // Folders, files, and attrs already encountered in this layer.
85
// By path; attrs as folder/file path plus "//" plus attr name.
86
private Set JavaDoc<String JavaDoc> oneLayerFiles; // Set<String>
87
// Related:
88
private boolean checkingForDuplicates;
89     private String JavaDoc currPath;
90     private boolean atLeastOneFileOrFolderInLayer;
91
92     /** Constructor for subclasses.
93      */

94     protected ParsingLayerCacheManager(File JavaDoc cacheDir) throws IOException JavaDoc {
95         super(cacheDir);
96     }
97     
98     /** Implements storage by parsing the layers and calling
99      * store(FileSystem,ParsingLayerCacheManager.MemFolder).
100      */

101     public final void store(FileSystem fs, List JavaDoc<URL JavaDoc> urls) throws IOException JavaDoc {
102         store(fs, createRoot(urls));
103     }
104     
105     /** Implements storage by parsing the layers and calling
106      * store(ParsingLayerCacheManager.MemFolder).
107      */

108     public final FileSystem store(List JavaDoc<URL JavaDoc> urls) throws IOException JavaDoc {
109         return store(createRoot(urls));
110     }
111     
112     /**
113      * Do the actual parsing.
114      */

115     private MemFolder createRoot(List JavaDoc<URL JavaDoc> urls) throws IOException JavaDoc {
116         root = new MemFolder(null);
117         curr = new Stack JavaDoc<Object JavaDoc>();
118         curr.push(root);
119         try {
120             // XMLReader r = SAXParserFactory.newInstance().newSAXParser().getXMLReader();
121
XMLReader JavaDoc r = XMLUtil.createXMLReader();
122             // Speed enhancements.
123
// XXX these are not really necessary; OK to run validation here!
124
r.setFeature("http://xml.org/sax/features/validation", false);
125             r.setFeature("http://xml.org/sax/features/namespaces", false);
126             // XXX this is not standard, should not rely on it:
127
r.setFeature("http://xml.org/sax/features/string-interning", true);
128             r.setContentHandler(this);
129             r.setErrorHandler(this);
130             r.setEntityResolver(this);
131             Exception JavaDoc carrier = null;
132             // #23609: reverse these...
133
urls = new ArrayList JavaDoc<URL JavaDoc>(urls);
134             Collections.reverse(urls);
135             checkingForDuplicates = LayerCacheManager.err.isLoggable(Level.FINE);
136             Iterator JavaDoc<URL JavaDoc> it = urls.iterator();
137             while (it.hasNext()) {
138                 base = it.next(); // store base for resolving in parser
139
if (checkingForDuplicates) {
140                     oneLayerFiles = new HashSet JavaDoc<String JavaDoc>(100);
141                     currPath = null;
142                 }
143                 LayerCacheManager.err.log(Level.FINE, "Parsing: {0}", base);
144                 atLeastOneFileOrFolderInLayer = false;
145                 try {
146                     r.parse(base.toExternalForm());
147                     if (!atLeastOneFileOrFolderInLayer) {
148                         LayerCacheManager.err.log(Level.WARNING, "Inefficient to include an empty layer in a module: {0}", base);
149                     }
150                 } catch (Exception JavaDoc e) {
151                     curr.clear();
152                     curr.push(root);
153                     LayerCacheManager.err.fine("Caught " + e + " while parsing: " + base);
154                     if (carrier == null) {
155                         carrier = e;
156                     } else {
157                         Throwable JavaDoc t = carrier;
158                         while (t.getCause() != null) {
159                             t = t.getCause();
160                         }
161                         t.initCause(e);
162                     }
163                 }
164             }
165             if (carrier != null) throw carrier;
166             LayerCacheManager.err.fine("Finished layer parsing; " + fileCount + " files, " + folderCount + " folders, " + attrCount + " attributes");
167             return root;
168         } catch (IOException JavaDoc ioe) {
169             throw ioe;
170         } catch (Exception JavaDoc e) {
171             throw (IOException JavaDoc) new IOException JavaDoc(e.toString()).initCause(e);
172         } finally {
173             fileCount = folderCount = attrCount = 0;
174             base = null;
175             locator = null;
176             curr = null;
177             root = null;
178             oneLayerFiles = null;
179             currPath = null;
180         }
181     }
182
183     /** Delegated storage method supplied with a merged layer parse.
184      * Not called if the manager does not support loading;
185      * otherwise must be overridden.
186      */

187     protected void store(FileSystem fs, MemFolder root) throws IOException JavaDoc {
188         throw new NotImplementedException();
189     }
190     
191     /** Delegated storage method supplied with a merged layer parse.
192      * Not called if the manager supports loading;
193      * otherwise must be overridden.
194      */

195     protected FileSystem store(MemFolder root) throws IOException JavaDoc {
196         throw new NotImplementedException();
197     }
198     
199     /** If true, file content URLs should be opened and the contents extracted,
200      * if they are of an appropriate type (locally stored). If false, the original
201      * URLs should be left alone.
202      */

203     protected abstract boolean openURLs();
204     
205     public void startElement(String JavaDoc ns, String JavaDoc lname, String JavaDoc qname, Attributes JavaDoc attrs) throws SAXException JavaDoc {
206         if (qname == "filesystem") {
207             return;
208         } else if (qname == "folder") {
209             fileOrFolder(qname, attrs);
210         } else if (qname == "file") {
211             MemFile file = (MemFile)fileOrFolder(qname, attrs);
212             file.contents = null;
213             String JavaDoc u = attrs.getValue("url");
214             if (u != null) {
215                 try {
216                     file.ref = new URL JavaDoc(base, u);
217                 } catch (MalformedURLException JavaDoc mfue) {
218                     throw (SAXException JavaDoc) new SAXException JavaDoc(mfue.toString()).initCause(mfue);
219                 }
220             } else {
221                 file.ref = null;
222             }
223         } else if (qname == "attr") {
224             attrCount++;
225             MemAttr attr = new MemAttr();
226             int len = attrs.getLength();
227             for (int i = 0; i < len; i++) {
228                 String JavaDoc attrName = attrs.getQName(i);
229                 if ("name".equals(attrName)) {
230                     attr.name = attrs.getValue(i);
231                 }
232                 else {
233                     int idx = Arrays.binarySearch(ATTR_TYPES, attrName);
234                     if (idx >= 0) {
235                         attr.type = ATTR_TYPES[idx];
236                         attr.data = attrs.getValue(i);
237                     }
238                 }
239                 if (attr.name != null && attr.data != null) {
240                     break;
241                 }
242             }
243 // System.out.println("found attr "+attr);
244
/*
245             attr.name = attrs.getValue("name");
246             for (int i = 0; i < ATTR_TYPES.length; i++) {
247                 String v = attrs.getValue(ATTR_TYPES[i]);
248                 if (v != null) {
249                     attr.type = ATTR_TYPES[i];
250                     attr.data = v;
251                     break;
252                 }
253             }
254              */

255             if (attr.type == null) throw new SAXParseException JavaDoc("unknown <attr> value type for " + attr.name, locator);
256             MemFileOrFolder parent = (MemFileOrFolder)curr.peek();
257             if (parent.attrs == null) parent.attrs = new LinkedList JavaDoc<MemAttr>();
258             Iterator JavaDoc it = parent.attrs.iterator();
259             while (it.hasNext()) {
260                 if (((MemAttr)it.next()).name.equals(attr.name)) {
261                     attrCount--;
262                     it.remove();
263                 }
264             }
265             parent.attrs.add(attr);
266             if (checkingForDuplicates && !oneLayerFiles.add(currPath + "//" + attr.name)) { // NOI18N
267
LayerCacheManager.err.warning("layer " + base + " contains duplicate attributes " + attr.name + " for " + currPath);
268             }
269         } else {
270             throw new SAXException JavaDoc(qname);
271         }
272     }
273     
274     private MemFileOrFolder fileOrFolder(String JavaDoc qname, Attributes JavaDoc attrs) {
275         atLeastOneFileOrFolderInLayer = true;
276         String JavaDoc name = attrs.getValue("name");
277         if (name == null) throw new NullPointerException JavaDoc("No name"); // NOI18N
278
if (!(curr.peek() instanceof MemFolder)) throw new ClassCastException JavaDoc("Stack: " + curr); // NOI18N
279
MemFolder parent = (MemFolder)curr.peek();
280         MemFileOrFolder f = null;
281         if (parent.children == null) {
282             parent.children = new LinkedList JavaDoc<MemFileOrFolder>();
283         }
284         else {
285             Iterator JavaDoc it = parent.children.iterator();
286             while (it.hasNext()) {
287                 MemFileOrFolder f2 = (MemFileOrFolder)it.next();
288                 if (f2.name.equals(name)) {
289                     f = f2;
290                     break;
291                 }
292             }
293         }
294         if (f == null) {
295             if (qname == "folder") { // NOI18N
296
f = new MemFolder(base);
297                 folderCount++;
298             } else {
299                 f = new MemFile(base);
300                 fileCount++;
301             }
302             f.name = name;
303             parent.children.add(f);
304         }
305         curr.push(f);
306         if (checkingForDuplicates) {
307             if (currPath == null) {
308                 currPath = name;
309             } else {
310                 currPath += "/" + name;
311             }
312             if (!oneLayerFiles.add(currPath)) {
313                 LayerCacheManager.err.warning("layer " + base + " contains duplicate " + qname + "s named " + currPath);
314             }
315         }
316         return f;
317     }
318     
319     public void endElement(String JavaDoc ns, String JavaDoc lname, String JavaDoc qname) throws SAXException JavaDoc {
320         if (qname == "file" && buf.length() > 0) {
321             String JavaDoc text = buf.toString().trim();
322             if (text.length() > 0) {
323                 MemFile file = (MemFile)curr.peek();
324                 if (file.ref != null) throw new SAXParseException JavaDoc("CDATA plus url= in <file>", locator);
325                 LayerCacheManager.err.warning("use of inline CDATA text contents in <file name=\"" + file.name + "\"> deprecated for performance and charset safety at " + locator.getSystemId() + ":" + locator.getLineNumber() + ". Please use the 'url' attribute instead, or the file attribute 'originalFile' on *.shadow files (with IDE/1 > 2.23).");
326                 // Note: platform default encoding used. If you care about the encoding,
327
// you had better be using url= instead.
328
file.contents = text.getBytes();
329             }
330             buf.setLength(0);
331         }
332         if (qname == "file" && openURLs()) {
333             MemFile file = (MemFile)curr.peek();
334             // Only open simple URLs. Assume that JARs are the same JARs with the layers.
335
if (file.ref != null && file.ref.toExternalForm().startsWith("jar:file:")) { // NOI18N
336
try {
337                     URLConnection JavaDoc conn = file.ref.openConnection();
338                     conn.connect();
339                     byte[] buf = new byte[conn.getContentLength()];
340                     InputStream JavaDoc is = conn.getInputStream();
341                     try {
342                         int pos = 0;
343                         while (pos < buf.length) {
344                             int read = is.read(buf, pos, buf.length - pos);
345                             if (read < 1) throw new IOException JavaDoc("Premature EOF on " + file.ref.toExternalForm()); // NOI18N
346
pos += read;
347                         }
348                         if (is.read() != -1) throw new IOException JavaDoc("Delayed EOF on " + file.ref.toExternalForm()); // NOI18N
349
} finally {
350                         is.close();
351                     }
352                     file.contents = buf;
353                     file.ref = null;
354                 } catch (IOException JavaDoc ioe) {
355                     throw new SAXException JavaDoc(ioe);
356                 }
357             }
358         }
359         if (qname == "file" || qname == "folder") { // NOI18N
360
curr.pop();
361             if (checkingForDuplicates) {
362                 int i = currPath.lastIndexOf('/'); // NOI18N
363
if (i == -1) {
364                     currPath = null;
365                 } else {
366                     currPath = currPath.substring(0, i);
367                 }
368             }
369         }
370     }
371     
372     public void characters(char[] ch, int start, int len) throws SAXException JavaDoc {
373         Object JavaDoc currF = curr.peek();
374         if (!(currF instanceof MemFile)) {
375             return;
376         }
377         // Usually this will just be whitespace which we will ignore anyway.
378
// Do it anyway, so that people who accidentally write:
379
// <file name="x" url="y"><![CDATA[z]]></file>
380
// will at least get an error.
381
buf.append(ch, start, len);
382     }
383     
384     public void warning(SAXParseException JavaDoc e) throws SAXException JavaDoc {
385         LayerCacheManager.err.log(Level.WARNING, null, e);
386     }
387     
388     public void fatalError(SAXParseException JavaDoc e) throws SAXException JavaDoc {
389         throw e;
390     }
391     
392     public void error(SAXParseException JavaDoc e) throws SAXException JavaDoc {
393         throw e;
394     }
395     
396     public InputSource JavaDoc resolveEntity(String JavaDoc pubid, String JavaDoc sysid) throws SAXException JavaDoc, IOException JavaDoc {
397         if (pubid != null && (pubid.equals(DTD_1_0) || pubid.equals(DTD_1_1))) {
398             return new InputSource JavaDoc(new ByteArrayInputStream JavaDoc(new byte[0]));
399         } else {
400             return null;
401         }
402     }
403     
404     public void setDocumentLocator(Locator JavaDoc locator) {
405         this.locator = locator;
406     }
407     
408     public void endDocument() throws SAXException JavaDoc {
409         if (curr.size() != 1) throw new SAXException JavaDoc("Wrong stack: " + curr); // NOI18N
410
}
411     
412     public void startDocument() throws SAXException JavaDoc {}
413     
414     public void startPrefixMapping(String JavaDoc str, String JavaDoc str1) throws SAXException JavaDoc {}
415     
416     public void skippedEntity(String JavaDoc str) throws SAXException JavaDoc {}
417     
418     public void processingInstruction(String JavaDoc str, String JavaDoc str1) throws SAXException JavaDoc {}
419     
420     public void ignorableWhitespace(char[] values, int param, int param2) throws SAXException JavaDoc {}
421     
422     public void endPrefixMapping(String JavaDoc str) throws SAXException JavaDoc {}
423
424     /** Struct for <file> or <folder>.
425      */

426     protected static abstract class MemFileOrFolder {
427         public String JavaDoc name;
428         public List JavaDoc<MemAttr> attrs = null; // {null | List<MemAttr>}
429
public final URL JavaDoc base;
430         
431         public MemFileOrFolder (URL JavaDoc base) {
432             this.base = base;
433         }
434     }
435     
436     /** Struct for <folder>.
437      */

438     protected static final class MemFolder extends MemFileOrFolder {
439         public List JavaDoc<MemFileOrFolder> children = null;
440         
441         public MemFolder (URL JavaDoc base) {
442             super (base);
443         }
444         
445         public String JavaDoc toString() {
446             return "MemFolder[" + name + "]"; // NOI18N
447
}
448     }
449     
450     /** Struct for <file>.
451      */

452     protected static final class MemFile extends MemFileOrFolder {
453         public byte[] contents = null; // {null | byte[]}
454
public URL JavaDoc ref = null; // {null | URL}
455

456         public MemFile (URL JavaDoc base) {
457             super (base);
458         }
459         
460         public String JavaDoc toString() {
461             return "MemFile[" + name + "]"; // NOI18N
462
}
463     }
464     
465     /** Struct for <attr>.
466      */

467     protected static final class MemAttr {
468         public String JavaDoc name;
469         public String JavaDoc type;
470         public String JavaDoc data;
471         public String JavaDoc toString() {
472             return "MemAttr[" + name + "," + type + "," + data + "]"; // NOI18N
473
}
474     }
475     
476 }
477
Popular Tags