/* * Copyright 2005 by Oracle USA * 500 Oracle Parkway, Redwood Shores, California, 94065, U.S.A. * All rights reserved. */ package javax.ide.util; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; /** * A MetaClass describes a real {@link Class} with the purpose * of providing to an IDE class level information, and delaying the loading of * that class to the last possible moment: when an instance of the class is * required.

* * A MetaClass binds the {@link Class} object from its class name * using the appropriate class loader. Once the class is bound, new instances * can be created using the {@link #newInstance} method. */ public final class MetaClass { private final String _className; private final ClassLoader _classLoader; private Class _class; /** * Construct a meta class for the specified class name. * * @param classLoader the class loader to load the class from. Must not be * null. * @param className the fully qualified name of the class. Must not be null. */ public MetaClass( ClassLoader classLoader, String className ) { if ( classLoader == null ) { throw new NullPointerException( "null classLoader" ); } if ( className == null ) { throw new NullPointerException( "null className" ); } _classLoader = classLoader; _className = className; } /** * Get the fully qualified class name. This name is used to create the * real {@link Class} instance. * * @return The fully qualified class name. */ public String getClassName() { return _className; } /** * Get the classloader for this meta class. * * @return the class loader in which this meta class must be loaded. */ ClassLoader getClassLoader() { return _classLoader; } /** * Build the {@link Class} object from the class name. Uses the right * class loader in doing so. * * @return The real {@link Class} object. * @throws ClassNotFoundException if the class was not found. */ public Class toClass() throws ClassNotFoundException { if ( _class == null ) { _class = Class.forName( _className, true, _classLoader ); } return _class; } /** * Creates a new instance of the class represented by this * MetaClass object. * * @return A newly created instance. * * @exception IllegalAccessException if the {@link Class} or its * initializer is not accessible. * * @exception InstantiationException if the {@link Class} is an * abstract class, an interface, an array class, a primitive type, or * void; or if the instantiation fails for some other reason. * * @exception ClassNotFoundException if the {@link Class} is not found * using the MetaClass name. * * @exception ClassCastException if the {@link Class} is of the wrong type. */ public T newInstance() throws InstantiationException, IllegalAccessException, ClassNotFoundException { // Allow classes to be loaded even if their constructor is not // public. final Class clazz = toClass(); try { final Constructor ctor = clazz.getDeclaredConstructor( new Class[0] ); try { ctor.setAccessible( true ); return (T) ctor.newInstance( null ); } finally { ctor.setAccessible( false ); } } catch (InvocationTargetException e ) { return (T) clazz.newInstance(); } catch (NoSuchMethodException nsme ) { return (T) clazz.newInstance(); } } /*- * Object method. */ public String toString() { return "MetaClass[ classLoader="+_classLoader+", className="+_className+"]"; } /*- * Object method. */ public int hashCode() { int hash = 42; hash = 37 * hash + _className.hashCode(); hash = 37 * hash + _classLoader.hashCode(); return hash; } /*- * Object method. */ public boolean equals( Object object ) { if ( object == this ) { return true; } if ( !(object instanceof MetaClass) ) { return false; } MetaClass mc = (MetaClass) object; return mc._classLoader.equals( this._classLoader ) && mc._className.equals( this._className ); } }