duke@0: /* malenkov@1077: * Copyright 1996-2009 Sun Microsystems, Inc. All Rights Reserved. duke@0: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. duke@0: * duke@0: * This code is free software; you can redistribute it and/or modify it duke@0: * under the terms of the GNU General Public License version 2 only, as duke@0: * published by the Free Software Foundation. Sun designates this duke@0: * particular file as subject to the "Classpath" exception as provided duke@0: * by Sun in the LICENSE file that accompanied this code. duke@0: * duke@0: * This code is distributed in the hope that it will be useful, but WITHOUT duke@0: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or duke@0: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License duke@0: * version 2 for more details (a copy is included in the LICENSE file that duke@0: * accompanied this code). duke@0: * duke@0: * You should have received a copy of the GNU General Public License version duke@0: * 2 along with this work; if not, write to the Free Software Foundation, duke@0: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. duke@0: * duke@0: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, duke@0: * CA 95054 USA or visit www.sun.com if you need additional information or duke@0: * have any questions. duke@0: */ duke@0: duke@0: package java.beans; duke@0: duke@0: import com.sun.beans.finder.ClassFinder; duke@0: malenkov@1077: import java.awt.GraphicsEnvironment; duke@0: duke@0: import java.beans.beancontext.BeanContext; duke@0: malenkov@1077: import java.io.IOException; malenkov@1077: import java.io.InputStream; malenkov@1077: import java.io.ObjectInputStream; malenkov@1077: import java.io.ObjectStreamClass; malenkov@1077: import java.io.StreamCorruptedException; duke@0: malenkov@1077: malenkov@1077: import java.security.AccessController; malenkov@1077: import java.security.PrivilegedAction; malenkov@1077: malenkov@1077: import java.util.Iterator; jtulach@1238: import java.util.ServiceLoader; malenkov@1077: malenkov@1077: import sun.awt.AppContext; jtulach@1238: import sun.beans.AppletProxy; duke@0: duke@0: /** duke@0: * This class provides some general purpose beans control methods. duke@0: */ duke@0: duke@0: public class Beans { malenkov@1077: private static final Object DESIGN_TIME = new Object(); malenkov@1077: private static final Object GUI_AVAILABLE = new Object(); duke@0: duke@0: /** duke@0: *
duke@0: * Instantiate a JavaBean. duke@0: *
duke@0: * duke@0: * @param cls the class-loader from which we should create duke@0: * the bean. If this is null, then the system duke@0: * class-loader is used. duke@0: * @param beanName the name of the bean within the class-loader. duke@0: * For example "sun.beanbox.foobah" duke@0: * malenkov@1077: * @exception ClassNotFoundException if the class of a serialized duke@0: * object could not be found. malenkov@1077: * @exception IOException if an I/O error occurs. duke@0: */ duke@0: malenkov@1077: public static Object instantiate(ClassLoader cls, String beanName) throws IOException, ClassNotFoundException { duke@0: return Beans.instantiate(cls, beanName, null, null); duke@0: } duke@0: duke@0: /** duke@0: *duke@0: * Instantiate a JavaBean. duke@0: *
duke@0: * duke@0: * @param cls the class-loader from which we should create duke@0: * the bean. If this is null, then the system duke@0: * class-loader is used. duke@0: * @param beanName the name of the bean within the class-loader. duke@0: * For example "sun.beanbox.foobah" duke@0: * @param beanContext The BeanContext in which to nest the new bean duke@0: * malenkov@1077: * @exception ClassNotFoundException if the class of a serialized duke@0: * object could not be found. malenkov@1077: * @exception IOException if an I/O error occurs. duke@0: */ duke@0: malenkov@1077: public static Object instantiate(ClassLoader cls, String beanName, BeanContext beanContext) throws IOException, ClassNotFoundException { duke@0: return Beans.instantiate(cls, beanName, beanContext, null); duke@0: } duke@0: duke@0: /** duke@0: * Instantiate a bean. duke@0: *duke@0: * The bean is created based on a name relative to a class-loader. duke@0: * This name should be a dot-separated name such as "a.b.c". duke@0: *
duke@0: * In Beans 1.0 the given name can indicate either a serialized object duke@0: * or a class. Other mechanisms may be added in the future. In duke@0: * beans 1.0 we first try to treat the beanName as a serialized object duke@0: * name then as a class name. duke@0: *
duke@0: * When using the beanName as a serialized object name we convert the duke@0: * given beanName to a resource pathname and add a trailing ".ser" suffix. duke@0: * We then try to load a serialized object from that resource. duke@0: *
duke@0: * For example, given a beanName of "x.y", Beans.instantiate would first duke@0: * try to read a serialized object from the resource "x/y.ser" and if duke@0: * that failed it would try to load the class "x.y" and create an duke@0: * instance of that class. duke@0: *
duke@0: * If the bean is a subtype of java.applet.Applet, then it is given duke@0: * some special initialization. First, it is supplied with a default duke@0: * AppletStub and AppletContext. Second, if it was instantiated from duke@0: * a classname the applet's "init" method is called. (If the bean was duke@0: * deserialized this step is skipped.) duke@0: *
duke@0: * Note that for beans which are applets, it is the caller's responsiblity duke@0: * to call "start" on the applet. For correct behaviour, this should be done duke@0: * after the applet has been added into a visible AWT container. duke@0: *
duke@0: * Note that applets created via beans.instantiate run in a slightly
duke@0: * different environment than applets running inside browsers. In
duke@0: * particular, bean applets have no access to "parameters", so they may
duke@0: * wish to provide property get/set methods to set parameter values. We
duke@0: * advise bean-applet developers to test their bean-applets against both
duke@0: * the JDK appletviewer (for a reference browser environment) and the
duke@0: * BDK BeanBox (for a reference bean container).
duke@0: *
duke@0: * @param cls the class-loader from which we should create
duke@0: * the bean. If this is null, then the system
duke@0: * class-loader is used.
duke@0: * @param beanName the name of the bean within the class-loader.
duke@0: * For example "sun.beanbox.foobah"
duke@0: * @param beanContext The BeanContext in which to nest the new bean
duke@0: * @param initializer The AppletInitializer for the new bean
duke@0: *
malenkov@1077: * @exception ClassNotFoundException if the class of a serialized
duke@0: * object could not be found.
malenkov@1077: * @exception IOException if an I/O error occurs.
duke@0: */
duke@0:
jtulach@1238: public static Object instantiate(ClassLoader cls, String beanName, BeanContext beanContext,
jtulach@1238: /** TBD: Oops , this is bad. The AppletInitializer is used from
jtulach@1238: * public API. I have not noticed that sooner. Opps.
jtulach@1238: AppletInitializer initializer
jtulach@1238: * meanwhile turning into object, but this cannot be final solution:
jtulach@1238: */
jtulach@1238: Object initializer
jtulach@1238: ) throws IOException, ClassNotFoundException {
duke@0:
malenkov@1077: InputStream ins;
malenkov@1077: ObjectInputStream oins = null;
duke@0: Object result = null;
duke@0: boolean serialized = false;
malenkov@1077: IOException serex = null;
duke@0:
duke@0: // If the given classloader is null, we check if an
duke@0: // system classloader is available and (if so)
duke@0: // use that instead.
duke@0: // Note that calls on the system class loader will
duke@0: // look in the bootstrap class loader first.
duke@0: if (cls == null) {
duke@0: try {
duke@0: cls = ClassLoader.getSystemClassLoader();
duke@0: } catch (SecurityException ex) {
duke@0: // We're not allowed to access the system class loader.
duke@0: // Drop through.
duke@0: }
duke@0: }
duke@0:
duke@0: // Try to find a serialized object with this name
duke@0: final String serName = beanName.replace('.','/').concat(".ser");
duke@0: final ClassLoader loader = cls;
malenkov@1077: ins = (InputStream)AccessController.doPrivileged
malenkov@1077: (new PrivilegedAction() {
duke@0: public Object run() {
duke@0: if (loader == null)
duke@0: return ClassLoader.getSystemResourceAsStream(serName);
duke@0: else
duke@0: return loader.getResourceAsStream(serName);
duke@0: }
duke@0: });
duke@0: if (ins != null) {
duke@0: try {
duke@0: if (cls == null) {
duke@0: oins = new ObjectInputStream(ins);
duke@0: } else {
duke@0: oins = new ObjectInputStreamWithLoader(ins, cls);
duke@0: }
duke@0: result = oins.readObject();
duke@0: serialized = true;
duke@0: oins.close();
malenkov@1077: } catch (IOException ex) {
duke@0: ins.close();
duke@0: // Drop through and try opening the class. But remember
duke@0: // the exception in case we can't find the class either.
duke@0: serex = ex;
duke@0: } catch (ClassNotFoundException ex) {
duke@0: ins.close();
duke@0: throw ex;
duke@0: }
duke@0: }
duke@0:
duke@0: if (result == null) {
duke@0: // No serialized object, try just instantiating the class
duke@0: Class cl;
duke@0:
duke@0: try {
duke@0: cl = ClassFinder.findClass(beanName, cls);
duke@0: } catch (ClassNotFoundException ex) {
duke@0: // There is no appropriate class. If we earlier tried to
duke@0: // deserialize an object and got an IO exception, throw that,
duke@0: // otherwise rethrow the ClassNotFoundException.
duke@0: if (serex != null) {
duke@0: throw serex;
duke@0: }
duke@0: throw ex;
duke@0: }
duke@0:
duke@0: /*
duke@0: * Try to instantiate the class.
duke@0: */
duke@0:
jtulach@1238: try {
duke@0: result = cl.newInstance();
duke@0: } catch (Exception ex) {
duke@0: // We have to remap the exception to one in our signature.
duke@0: // But we pass extra information in the detail message.
duke@0: throw new ClassNotFoundException("" + cl + " : " + ex, ex);
duke@0: }
duke@0: }
duke@0:
duke@0: if (result != null) {
duke@0:
duke@0: // Ok, if the result is an applet initialize it.
jtulach@1238: Iterator
duke@0: * The result may be the same object or a different object. If
duke@0: * the requested target view isn't available then the given
duke@0: * bean is returned.
duke@0: *
duke@0: * This method is provided in Beans 1.0 as a hook to allow the
duke@0: * addition of more flexible bean behaviour in the future.
duke@0: *
duke@0: * @param bean Object from which we want to obtain a view.
duke@0: * @param targetType The type of view we'd like to get.
duke@0: *
duke@0: */
duke@0: public static Object getInstanceOf(Object bean, Class> targetType) {
duke@0: return bean;
duke@0: }
duke@0:
duke@0: /**
duke@0: * Check if a bean can be viewed as a given target type.
duke@0: * The result will be true if the Beans.getInstanceof method
duke@0: * can be used on the given bean to obtain an object that
duke@0: * represents the specified targetType type view.
duke@0: *
duke@0: * @param bean Bean from which we want to obtain a view.
duke@0: * @param targetType The type of view we'd like to get.
duke@0: * @return "true" if the given bean supports the given targetType.
duke@0: *
duke@0: */
duke@0: public static boolean isInstanceOf(Object bean, Class> targetType) {
duke@0: return Introspector.isSubclass(bean.getClass(), targetType);
duke@0: }
duke@0:
duke@0:
duke@0: /**
duke@0: * Test if we are in design-mode.
duke@0: *
duke@0: * @return True if we are running in an application construction
duke@0: * environment.
duke@0: *
malenkov@1077: * @see DesignMode
duke@0: */
duke@0: public static boolean isDesignTime() {
malenkov@1077: Object value = AppContext.getAppContext().get(DESIGN_TIME);
malenkov@1077: return (value instanceof Boolean) && (Boolean) value;
duke@0: }
duke@0:
duke@0: /**
duke@0: * Determines whether beans can assume a GUI is available.
duke@0: *
duke@0: * @return True if we are running in an environment where beans
duke@0: * can assume that an interactive GUI is available, so they
duke@0: * can pop up dialog boxes, etc. This will normally return
duke@0: * true in a windowing environment, and will normally return
duke@0: * false in a server environment or if an application is
duke@0: * running as part of a batch job.
duke@0: *
malenkov@1077: * @see Visibility
duke@0: *
duke@0: */
duke@0: public static boolean isGuiAvailable() {
malenkov@1077: Object value = AppContext.getAppContext().get(GUI_AVAILABLE);
malenkov@1077: return (value instanceof Boolean) ? (Boolean) value : !GraphicsEnvironment.isHeadless();
duke@0: }
duke@0:
duke@0: /**
duke@0: * Used to indicate whether of not we are running in an application
duke@0: * builder environment.
duke@0: *
duke@0: * Note that this method is security checked
duke@0: * and is not available to (for example) untrusted applets.
duke@0: * More specifically, if there is a security manager,
duke@0: * its Note that this method is security checked
duke@0: * and is not available to (for example) untrusted applets.
duke@0: * More specifically, if there is a security manager,
duke@0: * its checkPropertiesAccess
duke@0: * method is called. This could result in a SecurityException.
duke@0: *
duke@0: * @param isDesignTime True if we're in an application builder tool.
duke@0: * @exception SecurityException if a security manager exists and its
duke@0: * checkPropertiesAccess
method doesn't allow setting
duke@0: * of system properties.
duke@0: * @see SecurityManager#checkPropertiesAccess
duke@0: */
duke@0:
duke@0: public static void setDesignTime(boolean isDesignTime)
duke@0: throws SecurityException {
duke@0: SecurityManager sm = System.getSecurityManager();
duke@0: if (sm != null) {
duke@0: sm.checkPropertiesAccess();
duke@0: }
malenkov@1077: AppContext.getAppContext().put(DESIGN_TIME, Boolean.valueOf(isDesignTime));
duke@0: }
duke@0:
duke@0: /**
duke@0: * Used to indicate whether of not we are running in an environment
duke@0: * where GUI interaction is available.
duke@0: *
duke@0: * checkPropertiesAccess
duke@0: * method is called. This could result in a SecurityException.
duke@0: *
duke@0: * @param isGuiAvailable True if GUI interaction is available.
duke@0: * @exception SecurityException if a security manager exists and its
duke@0: * checkPropertiesAccess
method doesn't allow setting
duke@0: * of system properties.
duke@0: * @see SecurityManager#checkPropertiesAccess
duke@0: */
duke@0:
duke@0: public static void setGuiAvailable(boolean isGuiAvailable)
duke@0: throws SecurityException {
duke@0: SecurityManager sm = System.getSecurityManager();
duke@0: if (sm != null) {
duke@0: sm.checkPropertiesAccess();
duke@0: }
malenkov@1077: AppContext.getAppContext().put(GUI_AVAILABLE, Boolean.valueOf(isGuiAvailable));
duke@0: }
duke@0: }
duke@0:
duke@0: /**
duke@0: * This subclass of ObjectInputStream delegates loading of classes to
duke@0: * an existing ClassLoader.
duke@0: */
duke@0:
duke@0: class ObjectInputStreamWithLoader extends ObjectInputStream
duke@0: {
duke@0: private ClassLoader loader;
duke@0:
duke@0: /**
duke@0: * Loader must be non-null;
duke@0: */
duke@0:
duke@0: public ObjectInputStreamWithLoader(InputStream in, ClassLoader loader)
duke@0: throws IOException, StreamCorruptedException {
duke@0:
duke@0: super(in);
duke@0: if (loader == null) {
duke@0: throw new IllegalArgumentException("Illegal null argument to ObjectInputStreamWithLoader");
duke@0: }
duke@0: this.loader = loader;
duke@0: }
duke@0:
duke@0: /**
duke@0: * Use the given ClassLoader rather than using the system class
duke@0: */
duke@0: protected Class resolveClass(ObjectStreamClass classDesc)
duke@0: throws IOException, ClassNotFoundException {
duke@0:
duke@0: String cname = classDesc.getName();
duke@0: return ClassFinder.resolveClass(cname, this.loader);
duke@0: }
duke@0: }
duke@0: