alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

What this is

This file is included in the DevDaily.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

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-2004 Sun
 * Microsystems, Inc. All Rights Reserved.
 */

package org.openide.loaders;

import java.lang.reflect.*;
import java.io.*;

import org.openide.ErrorManager;
import org.openide.cookies.InstanceCookie;
import org.openide.filesystems.FileObject;
import org.openide.util.HelpCtx;

// imports for findHelp:
import java.beans.*;
import java.security.PermissionCollection;
import java.security.Permissions;
import java.util.PropertyPermission;
import org.openide.util.SharedClassObject;
import org.openide.util.Lookup;

// Encapsulates working with classes and optimize it.
/** An instance cookie implementation that works with files or entries.
*
* @author   Jan Jancura, Jaroslav Tulach
*/
public class InstanceSupport extends Object implements InstanceCookie.Of {
    /** entry to work with */
    private MultiDataObject.Entry entry;

    /** throw exception during loading of the class */
    private Throwable clazzException;

    /** the class of the instance */
    private Class clazz;

    /** the class is applet */
    private Boolean applet;
    /** the class is bean */
    private Boolean bean;

    /** New support for given entry. The file is taken from the
    * entry and is updated if the entry moves or renames itself.
    * @param entry entry to create instance from
    */
    public InstanceSupport(MultiDataObject.Entry entry) {
        this.entry = entry;
    }
    
    /** Accessor for the entry. Needed in InstanceDataObject.Ser
     * @return the entry
     */
    MultiDataObject.Entry entry () {
        return entry;
    }
    

    // main methods .........................................................................................................

    /* The bean name for the instance.
    * @return the name for the instance
    */
    public String instanceName () {
        // XXX does this make any sense? Is this method useful for anything?
        String p = instanceOrigin().getPath();
        int x = p.lastIndexOf('.');
        if (x != -1 && x > p.lastIndexOf('/')) {
            p = p.substring(0, x);
        }
        return p.replace('/', '.');
    }

    /* The class of the instance represented by this cookie.
    * Can be used to test whether the instance is of valid
    * class before it is created.
    *
    * 

Note that SecurityException could be thrown * if an attempt was made e.g. to create an instance of a class * in a java.* package. Clients of InstanceSupport * which expect that this might happen (e.g. creating instances of * freeform user classes) should explicitly catch security exceptions * and convert them into whatever else as needed. * * @return the class of the instance * @exception IOException an I/O error occured * @exception ClassNotFoundException the class has not been found */ public Class instanceClass () throws java.io.IOException, ClassNotFoundException { return instanceClass(null); } final Class instanceClass (ClassLoader cl) throws java.io.IOException, ClassNotFoundException { if (clazzException != null) { if (clazzException instanceof IOException) throw (IOException)clazzException; else if (clazzException instanceof ClassNotFoundException) throw (ClassNotFoundException)clazzException; else throw (ThreadDeath)clazzException; } if (clazz != null) return clazz; //System.out.println ("getClass " + fileName ); // NOI18N try { if (isSerialized ()) { // NOI18N // read class from ser file InputStream is = instanceOrigin ().getInputStream (); try { clazz = readClass (is); return clazz; } finally { is.close (); } } else { // find class by class loader clazz = findClass (instanceName (), cl); if (clazz == null) throw new ClassNotFoundException (instanceName()); return clazz; } } catch (IOException ex) { ErrorManager.getDefault().annotate (ex, ErrorManager.UNKNOWN, "From file: " + entry.getFile(), null, null, null); // NOI18N clazzException = ex; throw ex; } catch (ClassNotFoundException ex) { ErrorManager.getDefault().annotate (ex, ErrorManager.UNKNOWN, "From file: " + entry.getFile(), null, null, null); // NOI18N clazzException = ex; throw ex; } catch (RuntimeException re) { // turn other throwables into class not found ex. clazzException = new ClassNotFoundException("From file: " + entry.getFile() + " due to: " + re.toString()); // NOI18N ErrorManager.getDefault ().annotate (clazzException, re); throw (ClassNotFoundException) clazzException; } catch (LinkageError le) { clazzException = new ClassNotFoundException("From file: " + entry.getFile() + " due to: " + le.toString()); // NOI18N ErrorManager.getDefault ().annotate (clazzException, le); throw (ClassNotFoundException) clazzException; } } /*Query to found out if the object created by this cookie is * instance of given type. Does: *

    *    Class actualClass = instanceClass ();
    *    result = type.isAsignableFrom (actualClass);
    * 
* * @param type the class type we want to check * @return true if this cookie can produce object of given type */ public boolean instanceOf (Class type) { try { return type.isAssignableFrom (instanceClass ()); } catch (IOException ex) { return false; } catch (ClassNotFoundException ex) { return false; } } /** Returns the origin of the instance. * @return the origin */ public FileObject instanceOrigin () { // return getEntry ().getFile (); return entry.getFile (); } /* * @return an object to work with * @exception IOException an I/O error occured * @exception ClassNotFoundException the class has not been found */ public Object instanceCreate () throws java.io.IOException, ClassNotFoundException { try { if (isSerialized ()) { // create from ser file BufferedInputStream bis = new BufferedInputStream(instanceOrigin().getInputStream(), 1024); org.openide.util.io.NbObjectInputStream nbis = new org.openide.util.io.NbObjectInputStream(bis); Object o = nbis.readObject(); nbis.close(); return o; } else { Class c = instanceClass (); if (SharedClassObject.class.isAssignableFrom (c)) { // special support return SharedClassObject.findObject (c, true); } else { // create new instance return c.newInstance(); } } } catch (IOException ex) { // [PENDING] annotate with localized message ErrorManager.getDefault ().annotate (ex, instanceName ()); throw ex; } catch (ClassNotFoundException ex) { throw ex; } catch (Exception e) { // turn other throwables into class not found ex. throw new ClassNotFoundException(e.toString() + " from " + instanceName(), e); // NOI18N } catch (LinkageError e) { throw new ClassNotFoundException(e.toString() + " from " + instanceName(), e); // NOI18N } } /** Is this an applet? * @return true if this class is a java.applet.Applet * @deprecated This method probably should not be used, as it catches a variety of potentially * serious exceptions and errors, and swallows them so as to produce a simple boolean * result. (Notifying them all would be inappropriate as they typically come from user * code.) Better to directly parse the bytecode, using e.g. the classfile module, * which is immune to this class of errors. */ public boolean isApplet () { if (applet != null) return applet.booleanValue (); boolean b = instanceOf (java.applet.Applet.class); applet = b ? Boolean.TRUE : Boolean.FALSE; return b; } /** Is this a standalone executable? * @return true if this class has main method * (e.g., public static void main (String[] arguments)). * @deprecated This method probably should not be used, as it catches a variety of potentially * serious exceptions and errors, and swallows them so as to produce a simple boolean * result. (Notifying them all would be inappropriate as they typically come from user * code.) Better to directly parse the bytecode, using e.g. the classfile module, * which is immune to this class of errors. */ public boolean isExecutable () { try { Method main = instanceClass ().getDeclaredMethod ("main", new Class[] { // NOI18N String[].class }); int m = main.getModifiers (); return Modifier.isPublic (m) && Modifier.isStatic (m) && Void.TYPE.equals ( main.getReturnType () ); } catch (Exception ex) { return false; } catch (LinkageError re) { // false when other errors occur (NoClassDefFoundError etc...) return false; } } /** Is this a JavaBean? * @return true if this class represents JavaBean (is public and has a public default constructor). * @deprecated This method probably should not be used, as it catches a variety of potentially * serious exceptions and errors, and swallows them so as to produce a simple boolean * result. (Notifying them all would be inappropriate as they typically come from user * code.) Better to directly parse the bytecode, using e.g. the classfile module, * which is immune to this class of errors. */ public boolean isJavaBean () { if (bean != null) return bean.booleanValue (); // if from ser file => definitely it is a java bean if (isSerialized ()) { bean = Boolean.TRUE; return true; } // try to find out... try { Class clazz = instanceClass(); int modif = clazz.getModifiers (); if (!Modifier.isPublic (modif) || Modifier.isAbstract (modif)) { bean = Boolean.FALSE; return false; } Constructor c; try { c = clazz.getConstructor (new Class [0]); } catch (NoSuchMethodException e) { bean = Boolean.FALSE; return false; } if ((c == null) || !Modifier.isPublic (c.getModifiers ())) { bean = Boolean.FALSE; return false; } // check: if the class is an inner class, all outer classes have // to be public and in the static context: for (Class outer = clazz.getDeclaringClass(); outer != null; outer = outer.getDeclaringClass()) { // check if the enclosed class is static if (!Modifier.isStatic(modif)) return false; modif = outer.getModifiers(); // ... and the enclosing class is public if (!Modifier.isPublic(modif)) return false; } } catch (Exception ex) { bean = Boolean.FALSE; return true; } catch (LinkageError e) { // false when other errors occur (NoClassDefFoundError etc...) bean = Boolean.FALSE; return false; } // okay, this is bean... // return isBean = java.io.Serializable.class.isAssignableFrom (clazz); bean = Boolean.TRUE; return true; } /** Is this an interface? * @return true if the class is an interface * @deprecated This method probably should not be used, as it catches a variety of potentially * serious exceptions and errors, and swallows them so as to produce a simple boolean * result. (Notifying them all would be inappropriate as they typically come from user * code.) Better to directly parse the bytecode, using e.g. the classfile module, * which is immune to this class of errors. */ public boolean isInterface () { try { return instanceClass ().isInterface (); } catch (IOException ex) { return false; } catch (ClassNotFoundException cnfe) { return false; } } public String toString () { return instanceName (); } /** Find context help for some instance. * Helper method useful in nodes or data objects that provide an instance cookie; * they may choose to supply their own help context based on this. * All API classes which can provide help contexts will be tested for * (including HelpCtx instances themselves). * JComponents are checked for an attached help ID property, * as with {@link HelpCtx#findHelp(java.awt.Component)} (but not traversing parents). *

Also, partial compliance with the JavaHelp section on JavaBeans help is implemented--i.e., * if a Bean in its BeanInfo provides a BeanDescriptor which * has the attribute helpID, this will be returned. The value is not * defaulted (because it would usually be nonsense and would mask a useful default * help for the instance container), nor is the help set specification checked, * since someone should have installed the proper help set anyway, and the APIs * cannot add a new reference to a help set automatically. * See javax.help.HelpUtilities.getIDStringFromBean for details. *

Special IDs are added, corresponding to the class name, for all standard visual components. * @param instance the instance to check for help (it is permissible for the {@link InstanceCookie#instanceCreate} to return null) * @return the help context found on the instance or inferred from a Bean, * or null if none was found (or it was {@link HelpCtx#DEFAULT_HELP}) * * * @deprecated use org.openide.util.HelpCtx.findHelp (Object) */ public static HelpCtx findHelp (InstanceCookie instance) { try { Class clazz = instance.instanceClass(); // [a.n] I have moved the code here as those components's BeanInfo do not contain helpID // - it is faster // Help on some standard components. Note that borders/layout managers do not really work here. if (java.awt.Component.class.isAssignableFrom (clazz) || java.awt.MenuComponent.class.isAssignableFrom (clazz)) { String name = clazz.getName (); String[] pkgs = new String[] { "java.awt.", "javax.swing.", "javax.swing.border." }; // NOI18N for (int i = 0; i < pkgs.length; i++) { if (name.startsWith (pkgs[i]) && name.substring (pkgs[i].length ()).indexOf ('.') == -1) return new HelpCtx (name); } } Object o = instance.instanceCreate(); if (o != null) { HelpCtx h = HelpCtx.findHelp(o); if (h != HelpCtx.DEFAULT_HELP) { return h; } } } catch (Exception e) { ErrorManager.getDefault().notify(e); } return null; } /** Test whether the instance represents serialized version of a class * or not. * @return true if the file entry extension is ser */ private boolean isSerialized () { return instanceOrigin ().getExt ().equals ("ser"); // NOI18N } /** Reads a class from input stream. Expects a serialized object to be stored * in the stream and reads only a class from it. * @param is input stream to read from * @return the class of that stream * @exception IOException if something fails */ private Class readClass (InputStream is) throws IOException, ClassNotFoundException { /** object input stream */ class OIS extends ObjectInputStream { public OIS (InputStream iss) throws IOException { super (iss); } /** Throws exception to signal the kind of class found. */ public Class resolveClass (ObjectStreamClass osc) throws IOException, ClassNotFoundException { Class c = findClass (osc.getName (), null); if (c == writeRepl) { // if this is write replace of shared object then // continue in reading return c; } // stop the reading expecting that we have read the class // of the primary object throw new ClassEx (c); } }; ObjectInputStream ois = new OIS (new BufferedInputStream (is)); try { ois.readObject (); // should not happen throw new ClassNotFoundException (); } catch (ClassEx ex) { // good, we found the class return ex.clazz; } } /** the variable for access to SharedClassObject$WriteReplace */ private static Class writeRepl; static { try { writeRepl = Class.forName ("org.openide.util.SharedClassObject$WriteReplace"); // NOI18N } catch (Exception ex) { ex.printStackTrace(); } } /** Finds a class for given name. * @param name name of the class * @return the class for the name * @exception ClassNotFoundException if the class cannot be found */ private Class findClass (String name, ClassLoader customLoader) throws ClassNotFoundException { try { Class c; try { if (customLoader != null) { c = customLoader.loadClass(name); } else { // to save the space with wasting classloaders, try the system first ClassLoader loader = (ClassLoader)Lookup.getDefault().lookup(ClassLoader.class); if (loader == null) { loader = getClass ().getClassLoader (); } c = loader.loadClass (name); } } catch (ClassNotFoundException ex) { // ok, ignore and try our class loader c = createClassLoader().loadClass(name); } return c; } catch (ClassNotFoundException ex) { throw ex; } catch (RuntimeException ex) { throw ex; } catch (LinkageError le) { throw new ClassNotFoundException(le.toString(), le); } } /** Creates new NbClassLoader with restricted PermissionCollection * that contains only: * java.io.FilePermission("<>", "read") * java.util.PropertyPermission("*", "read") * * @return ClassLoader */ protected ClassLoader createClassLoader() { ClassLoader l = (ClassLoader)Lookup.getDefault().lookup(ClassLoader.class); return l; } /** Trivial supporting instance cookie for already-existing objects. */ public static class Instance extends Object implements InstanceCookie.Of { /** the object to represent */ private Object obj; /** Create a new instance cookie. * @param obj the object to represent in this cookie */ public Instance (Object obj) { this.obj = obj; } /* The bean name for the instance. * @return the name for the instance */ public String instanceName () { return obj.getClass ().getName (); } /* The class of the instance represented by this cookie. * Can be used to test whether the instance is of valid * class before it is created. * * @return the class of the instance */ public Class instanceClass () { return obj.getClass (); } /* * @return an object to work with */ public Object instanceCreate () { return obj; } public boolean instanceOf (Class type) { return type.isAssignableFrom (instanceClass ()); } } /** The exception to use to signal succesful find of a class. * Used in method readClass. */ private static class ClassEx extends IOException { /** founded class */ public Class clazz; static final long serialVersionUID =4810039297880922426L; /** @param c the class */ public ClassEx (Class c) { clazz = c; } } }

... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

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.