|
What this is
Other links
The source code/* * Sun Public License Notice * * The contents of this file are subject to the Sun Public License * Version 1.0 (the "License"). You may not use this file except in * compliance with the License. A copy of the License is available at * http://www.sun.com/ * * The Original Code is NetBeans. The Initial Developer of the Original * Code is Sun Microsystems, Inc. Portions Copyright 1997-2002 Sun * Microsystems, Inc. All Rights Reserved. */ package org.netbeans.core.modules; // Permitted to reference API classes but should not directly do stuff with // the core, and should try to avoid loading TopManager. // ManifestSection itself can only reference generic module things and // utility APIs; other API references are made in the create() method // and in its subclasses. import java.beans.Beans; import java.util.*; import java.util.jar.Attributes; import org.openide.loaders.DataLoader; import org.openide.options.SystemOption; import org.openide.filesystems.FileSystem; import org.openide.ServiceType; import org.openide.util.actions.SystemAction; import org.openide.nodes.Node; import org.openide.util.HelpCtx; import org.openide.util.datatransfer.ExClipboard; import org.openide.util.SharedClassObject; import org.openide.ErrorManager; import org.openide.util.Lookup; // XXX probably should delete deprecated section handlers now (NbInstaller does not load them) // XXX synchronization? /** Class representing one specially-treated section in a module's manifest file. * For example, one section may describe a single action provided by the module. * * @author Jaroslav Tulach, Jesse Glick */ public abstract class ManifestSection { /** superclass of section */ private final Class superclazz; /** name of the class file, e.g. foo/Bar.class, or foo/bar.ser */ private final String name; /** name of the class, e.g. foo.bar */ private final String className; /** the class involved */ private Class clazz; /** instance of the class if possible */ private Object result; /** any exception associated with loading the object */ private Exception problem; /** associated module */ private final Module module; /** Create a manifest section generally. * @param name name of section, should be a class file, e.g. foo/Bar.class * @param module associated module * @param superclazz super-class of instances of this section * @throws InvalidException if the name is not valid for an OpenIDE section * (exception must include module for reference) */ protected ManifestSection(String name, Module module, Class superclazz) throws InvalidException { this.name = name; this.module = module; this.superclazz = superclazz; try { className = Util.createPackageName(name); } catch (IllegalArgumentException iae) { InvalidException ie = new InvalidException(module, iae.toString()); Util.err.annotate(ie, iae); throw ie; } } /** Get the associated module. */ public final Module getModule() { return module; } /** Get the classloader used to load this section. */ protected final ClassLoader getClassLoader() { return module.getClassLoader(); } /** Does this section represent a default instance? * Normally true, but false when deserializing beans. */ public final boolean isDefaultInstance() { return name.endsWith(".class"); // NOI18N } /** Get the class which the generated instances will have. * @return the class * @throws Exception for various reasons */ public final Class getSectionClass() throws Exception { if (clazz != null) { return clazz; } if (problem != null) { throw problem; } if (isDefaultInstance()) { try { clazz = getClassLoader().loadClass(className); if (! superclazz.isAssignableFrom(clazz)) { throw new ClassCastException("Class " + clazz.getName() + " is not a subclass of " + getSuperclass().getName()); // NOI18N } // Don't try to check .ser files: it is quite legitimate to // serialize in a module objects whose class is from elsewhere // (e.g. the core). if (clazz.getClassLoader() != getClassLoader()) { // NOI18N Events ev = module.getManager().getEvents(); ev.log(Events.WRONG_CLASS_LOADER, module, clazz, getClassLoader()); } return clazz; } catch (ClassNotFoundException cnfe) { Util.err.annotate(cnfe, ErrorManager.UNKNOWN, "Loader for ClassNotFoundException: " + getClassLoader(), null, null, null); problem = cnfe; throw problem; } catch (Exception e) { problem = e; throw problem; } catch (LinkageError t) { problem = new ClassNotFoundException(t.toString(), t); throw problem; } } else { return (clazz = getInstance().getClass()); } } /** Same as {@link #getSectionClass}, but only provides the name of the class. * Could be more efficient because it will not try to load the class unless * a serialized bean is in use. */ public String getSectionClassName() throws Exception { if (isDefaultInstance()) { return className; } else { return getSectionClass().getName(); } } /** Create a fresh instance. * @return the instance * @exception Exception if there is an error */ protected final Object createInstance() throws Exception { if (! isDefaultInstance()) { try { Object o = Beans.instantiate(getClassLoader(), className); clazz = o.getClass(); if (! superclazz.isAssignableFrom(clazz)) { throw new ClassCastException("Class " + clazz.getName() + " is not a subclass of " + getSuperclass().getName()); // NOI18N } return o; } catch (ClassNotFoundException cnfe) { Util.err.annotate(cnfe, ErrorManager.UNKNOWN, "Loader for ClassNotFoundException: " + getClassLoader(), null, null, null); throw cnfe; } catch (LinkageError le) { throw new ClassNotFoundException(le.toString(), le); } } else { getSectionClass(); // might throw some exceptions if (SharedClassObject.class.isAssignableFrom(clazz)) { return SharedClassObject.findObject(clazz, true); } else { return clazz.newInstance(); } } } /** Get a single cached instance. * @return the instance * @exception Exception if there is an error */ public final Object getInstance() throws Exception { if (problem != null) { problem.fillInStackTrace(); // XXX is this a good idea? throw problem; } if (result == null) { try { result = createInstance(); } catch (Exception ex) { // remember the exception problem = ex; throw problem; } catch (LinkageError t) { problem = new ClassNotFoundException(t.toString(), t); throw problem; } } return result; } /** Get the superclass which all instances of this section are expected to * be assignable to. */ public final Class getSuperclass() { return superclazz; } /** Dispose of a section. Used when a module will be uninstalled and all its * resources should be released. */ public void dispose() { result = null; problem = null; clazz = null; } /** String representation for debugging. */ public String toString() { return "ManifestSection[" + className + "]"; // NOI18N } /** Parse a manifest section and make an object representation of it. * @param name name of the section (i.e. file to load) * @param attr attributes of the manifest section * @param module the associated module * @return the section or null if this manifest section is not related to module installation * @exception InvalidException if the attributes are not valid */ public static ManifestSection create(String name, Attributes attr, Module module) throws InvalidException { String sectionName = attr.getValue("OpenIDE-Module-Class"); // NOI18N if (sectionName == null) { // no section tag return null; } else if (sectionName.equalsIgnoreCase("Action")) { // NOI18N return new ActionSection(name, attr, module); } else if (sectionName.equalsIgnoreCase("Option")) { // NOI18N warnObsolete(sectionName, module); return new OptionSection(name, attr, module); } else if (sectionName.equalsIgnoreCase("Loader")) { // NOI18N return new LoaderSection(name, attr, module); } else if (sectionName.equalsIgnoreCase("Filesystem")) { // NOI18N warnObsolete(sectionName, module); return new FileSystemSection(name, attr, module); } else if (sectionName.equalsIgnoreCase("Node")) { // NOI18N warnObsolete(sectionName, module); Util.err.log(ErrorManager.WARNING, "(See http://www.netbeans.org/issues/show_bug.cgi?id=19609, last comment, for howto.)"); return new NodeSection(name, attr, module); } else if (sectionName.equalsIgnoreCase("Service")) { // NOI18N warnObsolete(sectionName, module); return new ServiceSection(name, attr, module); } else if (sectionName.equalsIgnoreCase("Debugger")) { // NOI18N warnObsolete(sectionName, module); return new DebuggerSection(name, attr, module); } else if (sectionName.equalsIgnoreCase("ClipboardConvertor")) { // NOI18N warnObsolete(sectionName, module); return new ClipboardConvertorSection(name, attr, module); } else { throw new InvalidException(module, "Illegal manifest section type: " + sectionName); // NOI18N } } private static void warnObsolete(String sectionName, Module module) { Util.err.log(ErrorManager.WARNING, "Use of OpenIDE-Module-Class: " + sectionName + " in " + module.getCodeNameBase() + " is obsolete."); Util.err.log(ErrorManager.WARNING, "(Please use layer-based installation of objects instead.)"); } /** Module section for an Action. * @see SystemAction */ public static final class ActionSection extends ManifestSection { ActionSection(String name, Attributes attrs, Module module) throws InvalidException { super(name, module, SystemAction.class); } } /** Module section for an Option. * @see SystemOption */ public static final class OptionSection extends ManifestSection { OptionSection(String name, Attributes attrs, Module module) throws InvalidException { super(name, module, SystemOption.class); } } /** Module section for a Data Loader. * @see DataLoader */ public static final class LoaderSection extends ManifestSection { /** class name(s) of data object to * be inserted after loader that recognizes its */ private final String[] installAfter; /** class name(s) of data object to be inserted before its recognizing * data loader */ private final String[] installBefore; LoaderSection(String name, Attributes attrs, Module module) throws InvalidException { super (name, module, DataLoader.class); String val = attrs.getValue("Install-After"); // NOI18N StringTokenizer tok; List res; // XXX validate classnames etc. if (val != null) { tok = new StringTokenizer(val, ", "); // NOI18N res = new LinkedList(); while (tok.hasMoreTokens()) { String clazz = tok.nextToken(); if (! clazz.equals("")) // NOI18N res.add(clazz); } installAfter = (String[])res.toArray(new String[res.size()]); } else { installAfter = null; } val = attrs.getValue("Install-Before"); // NOI18N if (val != null) { tok = new StringTokenizer(val, ", "); // NOI18N res = new LinkedList(); while (tok.hasMoreTokens()) { String clazz = tok.nextToken(); if (! clazz.equals("")) // NOI18N res.add(clazz); } installBefore = (String[])res.toArray(new String[res.size()]); } else { installBefore = null; } } /** Get the representation class(es) of the loader(s) that this one should be installed after. * @return a list of class names, or |
... this post is sponsored by my books ... | |
#1 New Release! |
FP Best Seller |
Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.
A percentage of advertising revenue from
pages under the /java/jwarehouse
URI on this website is
paid back to open source projects.