KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > core > startup > ManifestSection


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;
21
22 import java.beans.Beans JavaDoc;
23 import java.util.LinkedList JavaDoc;
24 import java.util.List JavaDoc;
25 import java.util.StringTokenizer JavaDoc;
26 import java.util.jar.Attributes JavaDoc;
27 import org.netbeans.Events;
28 import org.netbeans.InvalidException;
29 import org.netbeans.Module;
30 import org.netbeans.Util;
31 import org.openide.util.Exceptions;
32 import org.openide.util.actions.SystemAction;
33 import org.openide.util.datatransfer.ExClipboard;
34 import org.openide.util.SharedClassObject;
35 import org.openide.util.Lookup;
36
37 // XXX synchronization?
38

39 /** Class representing one specially-treated section in a module's manifest file.
40  * For example, one section may describe a single action provided by the module.
41  *
42  * @author Jaroslav Tulach, Jesse Glick
43  */

44 public abstract class ManifestSection<T> {
45     /** superclass of section either Class or String name of the class*/
46     private final Object JavaDoc superclazz;
47     /** name of the class file, e.g. foo/Bar.class, or foo/bar.ser */
48     private final String JavaDoc name;
49     /** name of the class, e.g. foo.bar */
50     private final String JavaDoc className;
51     /** the class involved */
52     private Class JavaDoc<?> clazz;
53     /** instance of the class if possible */
54     private Object JavaDoc result;
55     /** any exception associated with loading the object */
56     private Exception JavaDoc problem;
57     /** associated module */
58     private final Module module;
59     
60     /** Create a manifest section generally.
61      * @param name name of section, should be a class file, e.g. foo/Bar.class
62      * @param module associated module
63      * @param superclazz super-class of instances of this section
64      * @throws InvalidException if the name is not valid for an OpenIDE section
65      * (exception must include module for reference)
66      */

67     protected ManifestSection(String JavaDoc name, Module module, Object JavaDoc superclazz) throws InvalidException {
68         this.name = name;
69         this.module = module;
70         this.superclazz = superclazz;
71         try {
72             className = Util.createPackageName(name);
73         } catch (IllegalArgumentException JavaDoc iae) {
74             InvalidException ie = new InvalidException(module, iae.toString());
75             ie.initCause(iae);
76             throw ie;
77         }
78     }
79     
80     /** Get the associated module. */
81     public final Module getModule() {
82         return module;
83     }
84     
85     /** Get the classloader used to load this section. */
86     protected final ClassLoader JavaDoc getClassLoader() {
87         return module != null ? module.getClassLoader() : getClass().getClassLoader();
88     }
89     
90     /** Does this section represent a default instance?
91      * Normally true, but false when deserializing beans.
92      */

93     public final boolean isDefaultInstance() {
94         return name.endsWith(".class"); // NOI18N
95
}
96     
97     /** Get the class which the generated instances will have.
98      * @return the class
99      * @throws Exception for various reasons
100      */

101     public final Class JavaDoc<?> getSectionClass() throws Exception JavaDoc {
102         if (clazz != null) {
103             return clazz;
104         }
105         if (problem != null) {
106             throw problem;
107         }
108         if (isDefaultInstance()) {
109             try {
110                 clazz = getClassLoader().loadClass(className);
111                 if (! getSuperclass().isAssignableFrom(clazz)) {
112                     throw new ClassCastException JavaDoc("Class " + clazz.getName() + " is not a subclass of " + getSuperclass().getName()); // NOI18N
113
}
114                 // Don't try to check .ser files: it is quite legitimate to
115
// serialize in a module objects whose class is from elsewhere
116
// (e.g. the core).
117
if (clazz.getClassLoader() != getClassLoader()) { // NOI18N
118
Events ev = module.getManager().getEvents();
119                     ev.log(Events.WRONG_CLASS_LOADER, module, clazz, getClassLoader());
120                 }
121                 return clazz;
122             } catch (ClassNotFoundException JavaDoc cnfe) {
123                 Exceptions.attachMessage(cnfe,
124                                          "Loader for ClassNotFoundException: " +
125                                          getClassLoader());
126                 problem = cnfe;
127                 throw problem;
128             } catch (Exception JavaDoc e) {
129                 problem = e;
130                 throw problem;
131             } catch (LinkageError JavaDoc t) {
132                 problem = new ClassNotFoundException JavaDoc(t.toString(), t);
133                 throw problem;
134             }
135         } else {
136             return (clazz = getInstance().getClass());
137         }
138     }
139     
140     /** Same as {@link #getSectionClass}, but only provides the name of the class.
141      * Could be more efficient because it will not try to load the class unless
142      * a serialized bean is in use.
143      */

144     public String JavaDoc getSectionClassName() throws Exception JavaDoc {
145         if (isDefaultInstance()) {
146             return className;
147         } else {
148             return getSectionClass().getName();
149         }
150     }
151     
152     /** Create a fresh instance.
153      * @return the instance
154      * @exception Exception if there is an error
155      */

156     protected final Object JavaDoc createInstance() throws Exception JavaDoc {
157         if (! isDefaultInstance()) {
158             try {
159                 Object JavaDoc o = Beans.instantiate(getClassLoader(), className);
160                 clazz = o.getClass();
161                 if (! getSectionClass().isAssignableFrom(clazz)) {
162                     throw new ClassCastException JavaDoc("Class " + clazz.getName() + " is not a subclass of " + getSuperclass().getName()); // NOI18N
163
}
164                 return o;
165             } catch (ClassNotFoundException JavaDoc cnfe) {
166                 Exceptions.attachMessage(cnfe,
167                                          "Loader for ClassNotFoundException: " +
168                                          getClassLoader());
169                 throw cnfe;
170             } catch (LinkageError JavaDoc le) {
171                 throw new ClassNotFoundException JavaDoc(le.toString(), le);
172             }
173         } else {
174             getSectionClass(); // might throw some exceptions
175
if (SharedClassObject.class.isAssignableFrom(clazz)) {
176                 return SharedClassObject.findObject(clazz.asSubclass(SharedClassObject.class), true);
177             } else {
178                 return clazz.newInstance();
179             }
180         }
181     }
182     
183     /** Get a single cached instance.
184      * @return the instance
185      * @exception Exception if there is an error
186      */

187     public final Object JavaDoc getInstance() throws Exception JavaDoc {
188         if (problem != null) {
189             problem.fillInStackTrace(); // XXX is this a good idea?
190
throw problem;
191         }
192         if (result == null) {
193             try {
194                 result = createInstance();
195             } catch (Exception JavaDoc ex) {
196                 // remember the exception
197
problem = ex;
198                 throw problem;
199             } catch (LinkageError JavaDoc t) {
200                 problem = new ClassNotFoundException JavaDoc(t.toString(), t);
201                 throw problem;
202             }
203         }
204         return result;
205     }
206     
207     /** Get the superclass which all instances of this section are expected to
208      * be assignable to.
209      */

210     public final Class JavaDoc<?> getSuperclass() {
211         if (superclazz instanceof Class JavaDoc) {
212             return (Class JavaDoc)superclazz;
213         } else {
214             try {
215                 return getClazz ((String JavaDoc)superclazz, module);
216             } catch (InvalidException ex) {
217                 throw (IllegalStateException JavaDoc)new IllegalStateException JavaDoc (superclazz.toString()).initCause (ex);
218             }
219         }
220     }
221     
222     /** Dispose of a section. Used when a module will be uninstalled and all its
223      * resources should be released.
224      */

225     public void dispose() {
226         result = null;
227         problem = null;
228         clazz = null;
229     }
230     
231     /** String representation for debugging. */
232     public String JavaDoc toString() {
233         return "ManifestSection[" + className + "]"; // NOI18N
234
}
235     
236     /** Parse a manifest section and make an object representation of it.
237      * @param name name of the section (i.e. file to load)
238      * @param attr attributes of the manifest section
239      * @param module the associated module
240      * @return the section or null if this manifest section is not related to module installation
241      * @exception InvalidException if the attributes are not valid
242      */

243     public static ManifestSection create(String JavaDoc name, Attributes JavaDoc attr, Module module) throws InvalidException {
244         String JavaDoc sectionName = attr.getValue("OpenIDE-Module-Class"); // NOI18N
245
if (sectionName == null) {
246             // no section tag
247
return null;
248         } else if (sectionName.equalsIgnoreCase("Action")) { // NOI18N
249
return new ActionSection(name, module);
250         } else if (sectionName.equalsIgnoreCase("Option")) { // NOI18N
251
warnObsolete(sectionName, module);
252             return null;
253         } else if (sectionName.equalsIgnoreCase("Loader")) { // NOI18N
254
return new LoaderSection(name, attr, module);
255         } else if (sectionName.equalsIgnoreCase("Filesystem")) { // NOI18N
256
warnObsolete(sectionName, module);
257             return null;
258         } else if (sectionName.equalsIgnoreCase("Node")) { // NOI18N
259
warnObsolete(sectionName, module);
260             Util.err.warning("(See http://www.netbeans.org/issues/show_bug.cgi?id=19609, last comment, for howto.)");
261             return null;
262         } else if (sectionName.equalsIgnoreCase("Service")) { // NOI18N
263
warnObsolete(sectionName, module);
264             return null;
265         } else if (sectionName.equalsIgnoreCase("Debugger")) { // NOI18N
266
// XXX should support for this be dropped entirely?
267
warnObsolete(sectionName, module);
268             return new DebuggerSection(name, module);
269         } else if (sectionName.equalsIgnoreCase("ClipboardConvertor")) { // NOI18N
270
// XXX should support for this be dropped entirely?
271
warnObsolete(sectionName, module);
272             return new ClipboardConvertorSection(name, module);
273         } else {
274             throw new InvalidException(module, "Illegal manifest section type: " + sectionName); // NOI18N
275
}
276     }
277     
278     private static void warnObsolete(String JavaDoc sectionName, Module module) {
279         Util.err.warning("Use of OpenIDE-Module-Class: " + sectionName + " in " + module.getCodeNameBase() + " is obsolete.");
280         Util.err.warning("(Please use layer-based installation of objects instead.)");
281     }
282     
283     /** Module section for an Action.
284      * @see SystemAction
285      */

286     public static final class ActionSection extends ManifestSection {
287         ActionSection(String JavaDoc name, Module module) throws InvalidException {
288             super(name, module, SystemAction.class);
289         }
290     }
291     
292     /** Module section for a Data Loader.
293      */

294     public static final class LoaderSection extends ManifestSection {
295         /** class name(s) of data object to
296          * be inserted after loader that recognizes its
297          */

298         private final String JavaDoc[] installAfter;
299         /** class name(s) of data object to be inserted before its recognizing
300          * data loader
301          */

302         private final String JavaDoc[] installBefore;
303         
304         LoaderSection(String JavaDoc name, Attributes JavaDoc attrs, Module module) throws InvalidException {
305             super (name, module, "org.openide.loaders.DataLoader"); // NOI18N
306
String JavaDoc val = attrs.getValue("Install-After"); // NOI18N
307
StringTokenizer JavaDoc tok;
308             List JavaDoc<String JavaDoc> res;
309             // XXX validate classnames etc.
310
if (val != null) {
311                 tok = new StringTokenizer JavaDoc(val, ", "); // NOI18N
312
res = new LinkedList JavaDoc<String JavaDoc>();
313                 while (tok.hasMoreTokens()) {
314                     String JavaDoc clazz = tok.nextToken();
315                     if (! clazz.equals("")) // NOI18N
316
res.add(clazz);
317                 }
318                 installAfter = res.toArray(new String JavaDoc[res.size()]);
319             } else {
320                 installAfter = null;
321             }
322             val = attrs.getValue("Install-Before"); // NOI18N
323
if (val != null) {
324                 tok = new StringTokenizer JavaDoc(val, ", "); // NOI18N
325
res = new LinkedList JavaDoc<String JavaDoc>();
326                 while (tok.hasMoreTokens()) {
327                     String JavaDoc clazz = tok.nextToken();
328                     if (! clazz.equals("")) // NOI18N
329
res.add(clazz);
330                 }
331                 installBefore = res.toArray(new String JavaDoc[res.size()]);
332             } else {
333                 installBefore = null;
334             }
335         }
336         
337         /** Get the representation class(es) of the loader(s) that this one should be installed after.
338          * @return a list of class names, or <code>null</code>
339          */

340         public String JavaDoc[] getInstallAfter() {
341             return installAfter;
342         }
343         
344         /** Get the representation class(es) of the loader(s) that this one should be installed before.
345          * @return a list of class names, or <code>null</code>
346          */

347         public String JavaDoc[] getInstallBefore() {
348             return installBefore;
349         }
350     }
351     
352     /** @deprecated use new debugger API
353      */

354     @Deprecated JavaDoc
355     public static final class DebuggerSection extends ManifestSection {
356         DebuggerSection(String JavaDoc name, Module module) throws InvalidException {
357             super(name, module, getClazz("org.openide.debugger.Debugger", module)); // NOI18N
358
}
359     }
360     
361     /** @deprecated use META-INF/services to register convertors.
362      */

363     @Deprecated JavaDoc
364     public static final class ClipboardConvertorSection extends ManifestSection {
365         ClipboardConvertorSection(String JavaDoc name, Module module) throws InvalidException {
366             super(name, module, ExClipboard.Convertor.class);
367         }
368     }
369
370     /** Loads class of given name.
371      */

372     static Class JavaDoc<?> getClazz(String JavaDoc name, Module m) throws InvalidException {
373         try {
374             return Lookup.getDefault().lookup(ClassLoader JavaDoc.class).loadClass(name);
375         } catch (ClassNotFoundException JavaDoc cnfe) {
376             InvalidException e = new InvalidException(m, "Unable to locate class: " + name + " maybe you do not have its module enabled!?"); // NOI18N
377
e.initCause(cnfe);
378             throw e;
379         }
380     }
381     
382 }
383
Popular Tags