KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > modules > java > JavaDataLoader


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.modules.java;
21
22 import java.io.FileNotFoundException JavaDoc;
23 import java.io.FilterInputStream JavaDoc;
24 import java.io.IOException JavaDoc;
25 import java.io.InputStream JavaDoc;
26 import java.io.ObjectInput JavaDoc;
27 import java.text.DateFormat JavaDoc;
28 import java.util.Collection JavaDoc;
29 import java.util.Date JavaDoc;
30 import java.util.LinkedList JavaDoc;
31 import java.util.Map JavaDoc;
32 import org.netbeans.api.java.classpath.ClassPath;
33 import org.netbeans.modules.java.settings.JavaSettings;
34 import org.openide.ErrorManager;
35 import org.openide.filesystems.FileObject;
36 import org.openide.loaders.DataObjectExistsException;
37 import org.openide.loaders.FileEntry;
38 import org.openide.loaders.MultiDataObject;
39 import org.openide.loaders.MultiFileLoader;
40 import org.openide.util.NbBundle;
41
42 /** Data loader which recognizes Java source files.
43 *
44 * @author Petr Hamernik
45 */

46 public class JavaDataLoader extends MultiFileLoader {
47     /** The standard extension for Java source files. */
48     public static final String JavaDoc JAVA_EXTENSION = "java"; // NOI18N
49

50     public static final String JavaDoc PROP_PARSER_ENGINE = "parserEngine"; // NOI18N
51

52     static final long serialVersionUID =-6286836352608877232L;
53
54     /** Create the loader.
55     * Should <em>not</em> be used by subclasses.
56     */

57     public JavaDataLoader() {
58         this("org.netbeans.modules.java.JavaDataObject"); // NOI18N
59
}
60
61     /** Create the loader from a subclass.
62     * @param recognizedObject the class of data object
63     * recognized by the loader
64     */

65     public JavaDataLoader(String JavaDoc recognizedObject) {
66         super(recognizedObject);
67     }
68
69     public JavaDataLoader(Class JavaDoc recognizedObject) {
70         super(recognizedObject);
71     }
72     
73     protected String JavaDoc actionsContext () {
74         return "Loaders/text/x-java/Actions/"; // NOI18N
75
}
76     
77     protected String JavaDoc defaultDisplayName() {
78         return NbBundle.getMessage(JavaDataLoader.class, "PROP_JavaLoader_Name");
79     }
80     
81     /** Create the <code>JavaDataObject</code>.
82     * Subclasses should rather create their own data object type.
83     *
84     * @param primaryFile the primary file
85     * @return the data object for this file
86     * @exception DataObjectExistsException if the primary file already has a data object
87     */

88     protected MultiDataObject createMultiObject (FileObject primaryFile)
89     throws DataObjectExistsException, java.io.IOException JavaDoc {
90         return new JavaDataObject(primaryFile, this);
91     }
92
93     /** For a given file find the primary file.
94     * Subclasses should override this, but still look for the {@link #JAVA_EXTENSION},
95     * as the Java source file should typically remain the primary file for the data object.
96     * @param fo the file to find the primary file for
97     *
98     * @return the primary file for this file or <code>null</code> if this file is not
99     * recognized by this loader
100     */

101     protected FileObject findPrimaryFile (FileObject fo) {
102     // never recognize folders.
103
if (fo.isFolder()) return null;
104         if (fo.getExt().equals(JAVA_EXTENSION))
105             return fo;
106         return null;
107     }
108
109     /** Create the primary file entry.
110     * Subclasses may override {@link JavaDataLoader.JavaFileEntry} and return a new instance
111     * of the overridden entry type.
112     *
113     * @param primaryFile primary file recognized by this loader
114     * @return primary entry for that file
115     */

116     protected MultiDataObject.Entry createPrimaryEntry (MultiDataObject obj, FileObject primaryFile) {
117         return new JavaFileEntry(obj, primaryFile);
118     }
119
120     /** Create a secondary file entry.
121     * By default, {@link FileEntry.Numb} is used for the class files; subclasses wishing to have useful
122     * secondary files should override this for those files, typically to {@link FileEntry}.
123     *
124     * @param secondaryFile secondary file to create entry for
125     * @return the entry
126     */

127     protected MultiDataObject.Entry createSecondaryEntry (MultiDataObject obj, FileObject secondaryFile) {
128         //The JavaDataObject itself has no secondary entries, but its subclasses have.
129
//So we have to keep it as MultiFileLoader
130
ErrorManager.getDefault().log ("Subclass of JavaDataLoader ("+this.getClass().getName()
131                 +") has secondary entries but does not override createSecondaryEntries (MultidataObject, FileObject) method."); // NOI18N
132
return new FileEntry.Numb(obj, secondaryFile);
133     }
134
135     /** Create the map of replaceable strings which is used
136     * in the <code>JavaFileEntry</code>. This method may be extended in subclasses
137     * to provide the appropriate map for other loaders.
138     * This implementation gets the map from the Java system option;
139     * subclasses may add other key/value pairs which may be created without knowledge of the
140     * file itself.
141     *
142     * @return the map of string which are replaced during instantiation
143     * from template
144     */

145     protected Map JavaDoc createStringsMap() {
146         Map JavaDoc map = JavaSettings.getDefault().getReplaceableStringsProps();
147         map.put("DATE", DateFormat.getDateInstance(DateFormat.LONG).format(new Date JavaDoc())); // NOI18N
148
map.put("TIME", DateFormat.getTimeInstance(DateFormat.SHORT).format(new Date JavaDoc())); // NOI18N
149
return map;
150     }
151     
152     public void readExternal(ObjectInput JavaDoc in) throws IOException JavaDoc, ClassNotFoundException JavaDoc {
153     super.readExternal(in);
154     if (in.available() > 0) {
155         int v;
156
157         v = in.readInt();
158             if (v >= 1)
159                 in.readObject();
160             if (v >= 2)
161                 in.readBoolean();
162     }
163     }
164     
165     /** This entry defines the format for replacing text during
166     * instantiation the data object.
167     * Used to substitute keys in the source file.
168     */

169     public class JavaFileEntry extends IndentFileEntry {
170         static final long serialVersionUID =8244159045498569616L;
171         
172         /**
173          * If true, the Entry refuses to open InputStream to prevent races
174          * between readers and attempts to delete the file.
175          */

176         boolean disableInputStream;
177         
178         /**
179          * Holds a collection of readers that read the file.
180          */

181         private Collection JavaDoc activeReaders;
182
183         /** Creates new entry. */
184         public JavaFileEntry(MultiDataObject obj, FileObject file) {
185             super(obj, file);
186         }
187
188         /** Provide suitable format for substitution of lines.
189         * Should not typically be overridden.
190         * @param target the target folder of the installation
191         * @param n the name the file will have
192         * @param e the extension the file will have
193         * @return format to use for formating lines
194         */

195         protected java.text.Format JavaDoc createFormat (FileObject target, String JavaDoc n, String JavaDoc e) {
196             Map JavaDoc map = createStringsMap();
197
198             modifyMap(map, target, n, e);
199
200             JMapFormat format = new JMapFormat(map);
201             format.setLeftBrace("__"); // NOI18N
202
format.setRightBrace("__"); // NOI18N
203
format.setCondDelimiter("$"); // NOI18N
204
format.setExactMatch(false);
205             return format;
206         }
207
208         /** Modify the replacement map.
209         * May be extended in subclasses to provide additional key/value
210         * pairs sensitive to the details of instantiation.
211         * @param map the map to add to
212         * @param target the destination folder for instantiation
213         * @param n the new file name
214         * @param e the new file extension
215         */

216         protected void modifyMap(Map JavaDoc map, FileObject target, String JavaDoc n, String JavaDoc e) {
217             ClassPath cp = ClassPath.getClassPath(target, ClassPath.SOURCE);
218             String JavaDoc resourcePath = "";
219             if (cp != null) {
220                 resourcePath = cp.getResourceName(target);
221             } else {
222                 ErrorManager.getDefault().log(ErrorManager.WARNING, "No classpath was found for folder: "+target);
223             }
224             map.put("NAME", n); // NOI18N
225
// Yes, this is package sans filename (target is a folder).
226
map.put("PACKAGE", resourcePath.replace('/', '.')); // NOI18N
227
map.put("PACKAGE_SLASHES", resourcePath); // NOI18N
228
// Fully-qualified name:
229
if (target.isRoot ()) {
230         map.put ("PACKAGE_AND_NAME", n); // NOI18N
231
map.put ("PACKAGE_AND_NAME_SLASHES", n); // NOI18N
232
} else {
233         map.put ("PACKAGE_AND_NAME", resourcePath.replace('/', '.') + '.' + n); // NOI18N
234
map.put ("PACKAGE_AND_NAME_SLASHES", resourcePath + '/' + n); // NOI18N
235
}
236             // No longer needed due to #6025. (You can just put in quotes, they will not
237
// prevent things from being escaped.) But leave the token here for
238
// compatibility with old templates. --jglick 26/08/00
239
map.put("QUOTES","\""); // NOI18N
240
}
241         
242         public synchronized void addReader(InputStream JavaDoc r) {
243             if (activeReaders == null) {
244                 activeReaders = new LinkedList JavaDoc();
245             }
246             activeReaders.add(r);
247         }
248         
249         public synchronized void removeReader(InputStream JavaDoc r) {
250             if (activeReaders == null)
251                 return;
252             activeReaders.remove(r);
253         }
254         
255         public void delete() throws IOException JavaDoc {
256             synchronized (this) {
257                 if (activeReaders != null) {
258                     int size=activeReaders.size();
259                     
260                     if (size>0) {
261                         InputStream JavaDoc[] readers=(InputStream JavaDoc[])activeReaders.toArray(new InputStream JavaDoc[size]);
262                         int i;
263                     
264                         for (i=0; i<readers.length; i++) readers[i].close();
265                     }
266                 }
267                 activeReaders = null;
268                 disableInputStream = true;
269             }
270             super.delete();
271         }
272         
273         public InputStream JavaDoc getInputStream() throws FileNotFoundException JavaDoc {
274             FileObject fob = getFile();
275             synchronized (this) {
276                 if (disableInputStream) {
277                     // refuse to create the stream.
278
throw new FileNotFoundException JavaDoc("File is being deleted."); // NOI18N
279
}
280                 InputStream JavaDoc s = new NotifyInputStream(fob.getInputStream());
281                 addReader(s);
282                 return s;
283             }
284         }
285         
286         private class NotifyInputStream extends FilterInputStream JavaDoc {
287             public NotifyInputStream(InputStream JavaDoc is) {
288                 super(is);
289             }
290             
291             public void close() throws IOException JavaDoc {
292                 super.close();
293                 removeReader(this);
294             }
295         }
296     }
297 }
298
Popular Tags