Frames | No Frames |
1: /* java.beans.Beans 2: Copyright (C) 1998, 1999, 2004, 2005 Free Software Foundation, Inc. 3: 4: This file is part of GNU Classpath. 5: 6: GNU Classpath is free software; you can redistribute it and/or modify 7: it under the terms of the GNU General Public License as published by 8: the Free Software Foundation; either version 2, or (at your option) 9: any later version. 10: 11: GNU Classpath is distributed in the hope that it will be useful, but 12: WITHOUT ANY WARRANTY; without even the implied warranty of 13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14: General Public License for more details. 15: 16: You should have received a copy of the GNU General Public License 17: along with GNU Classpath; see the file COPYING. If not, write to the 18: Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 19: 02110-1301 USA. 20: 21: Linking this library statically or dynamically with other modules is 22: making a combined work based on this library. Thus, the terms and 23: conditions of the GNU General Public License cover the whole 24: combination. 25: 26: As a special exception, the copyright holders of this library give you 27: permission to link this library with independent modules to produce an 28: executable, regardless of the license terms of these independent 29: modules, and to copy and distribute the resulting executable under 30: terms of your choice, provided that you also meet, for each linked 31: independent module, the terms and conditions of the license of that 32: module. An independent module is a module which is not derived from 33: or based on this library. If you modify this library, you may extend 34: this exception to your version of the library, but you are not 35: obligated to do so. If you do not wish to do so, delete this 36: exception statement from your version. */ 37: 38: package java.beans; 39: 40: import gnu.java.beans.DummyAppletStub; 41: import gnu.java.io.ClassLoaderObjectInputStream; 42: 43: import java.applet.Applet; 44: import java.beans.beancontext.BeanContext; 45: import java.io.IOException; 46: import java.io.ObjectInputStream; 47: import java.net.URL; 48: 49: /** 50: * <code>Beans</code> provides some helper methods that allow the basic 51: * operations of Bean-ness. 52: * 53: * @author John Keiser 54: * @author Robert Schuster 55: * 56: * @since 1.1 57: * @status updated to 1.4 58: * 59: */ 60: public class Beans 61: { 62: static boolean designTime = false; 63: static boolean guiAvailable = true; 64: 65: /** 66: * Once again, we have a java.beans class with only 67: * static methods that can be instantiated. When 68: * will the madness end? :) 69: */ 70: public Beans() 71: { 72: // Does intentionally nothing here. 73: } 74: 75: /** Creates a bean. 76: * <p>This is a convenience method that calls <code>instantiate(cl, beanName, null, null)</code>.</p> 77: * 78: * @see instantiate(ClassLoader, String, BeanContext, AppletInitializer) 79: * @param cl ClassLoader to be used or <code>null</code> for the system classloader. 80: * @param beanName Name of a serialized bean or class name. 81: * @return A newly created bean. 82: * @throws IOException If access of an IO resource failed. 83: * @throws ClassNotFoundException If the class name is not known or does not lead to a proper bean class. 84: */ 85: public static Object instantiate(ClassLoader cl, String beanName) 86: throws IOException, ClassNotFoundException 87: { 88: return instantiate(cl, beanName, null, null); 89: } 90: 91: /** Creates a bean. 92: * 93: * <p>This is a convenience method that calls <code>instantiate(cl, beanName, beanContext, null)</code>.</p> 94: * 95: * @see instantiate(ClassLoader, String, BeanContext, AppletInitializer) 96: * @param cl ClassLoader to be used or <code>null</code> for the system classloader. 97: * @param beanName Name of a serialized bean or class name. 98: * @param beanContext Context to which the newly created Bean should be added. 99: * @return A newly created bean. 100: * @throws IOException If access of an IO resource failed. 101: * @throws ClassNotFoundException If the class name is not known or does not lead to a proper bean class. 102: */ 103: public static Object instantiate( 104: ClassLoader cl, 105: String beanName, 106: BeanContext beanContext) 107: throws IOException, ClassNotFoundException 108: { 109: return instantiate(cl, beanName, beanContext, null); 110: } 111: 112: /** Instantiates a bean according to Beans 1.0. 113: * 114: * <p>In Beans 1.0 the instantiation scheme is as follows:</p> 115: * <p>The name should be dot-separated (e.g "place.for.beans.myBean") and indicate either a 116: * serialized object or a class name. In the first case all dots in the name are replaced with 117: * slashes ('/') and ".ser" is appended ("place.for.beans.myBean" becomes "place/for/beans/myBean.ser"). 118: * The bean is then loaded as an application or system resource depending on whether a 119: * <code>ClassLoader</code> was provided.</p> 120: * 121: * <p>If no such resource exists or if it contains no bean the name is interpreted as a class name of 122: * which an instance is then created.</p> 123: * 124: * <p>If a <code>BeanContext</code> instance is available the created bean is added to it.</p> 125: * 126: * <p>If the created Bean is an <code>Applet</code> or subclass and an <code>AppletInitializer</code> 127: * instance is available the applet is initialized and afterwards activated using the initializer. Additionally 128: * every instantiated <code>Applet</code> bean is initialized using the {@link Applet.init} method. 129: * Furthermore every applet gets a default <code>AppletStub</code>. The <code>Applet</code>'s 130: * document base is the location of the ".ser" file if it was deserialized or the location of its class 131: * file if it was instantiated.</p> 132: * 133: * <p>A <code>ClassNotFoundException</code> is not only thrown when a class name was unknown 134: * but even when the class has public no-argument constructor 135: * (<code>IllegalAccessException</code> is wrapped) or an exception is thrown while 136: * invoking such a constructor (causing exception is wrapped).</p> 137: * 138: * @param cl ClassLoader to be used or <code>null</code> for the system classloader. 139: * @param beanName Name of a serialized bean or class name. 140: * @param beanContext Context to which the newly created Bean should be added. 141: * @param initializer The AppletInitializer which is used for initializing <code>Applet</code> beans. 142: * @return A newly created bean. 143: * @throws IOException If access of an IO resource failed. 144: * @throws ClassNotFoundException If the class name is not known or does not lead to a proper bean class. 145: */ 146: public static Object instantiate( 147: ClassLoader cl, 148: String beanName, 149: BeanContext beanContext, 150: AppletInitializer initializer) 151: throws IOException, ClassNotFoundException 152: { 153: Object bean = null; 154: URL beanLocation = null; 155: URL classLocation = null; 156: 157: // Converts bean name into a resource name (eg. "a.b.c" -> "a/b/c"). 158: String resourceName = beanName.replace('.', '/'); 159: 160: /* Tries to get an input stream of the Bean, reading it as a system resource 161: * if no ClassLoader is present or as an application resource if a classloader 162: * is given. 163: */ 164: beanLocation = 165: (cl == null) 166: ? ClassLoader.getSystemResource(resourceName + ".ser") 167: : cl.getResource(resourceName + ".ser"); 168: 169: // Reads the serialized Bean from the returned URL. 170: if (beanLocation != null) 171: { 172: // Deserializes the bean instance. 173: ObjectInputStream ois = 174: (cl == null) 175: ? new ObjectInputStream(beanLocation.openStream()) 176: : new ClassLoaderObjectInputStream( 177: beanLocation.openStream(), 178: cl); 179: 180: bean = ois.readObject(); 181: 182: /* Implementation note: The result of ObjectInputStream.readObject() 183: * may have been null at this point (its a valid value to deserialize) 184: * and we explicitly want to try instantiation in such a case 185: * (this is important for compatibility). 186: */ 187: } 188: 189: // Instantiates the Bean using reflective instantiation if it has not been created yet. 190: if (bean == null) 191: { 192: // Makes sure that the deserialization was NOT done. 193: beanLocation = null; 194: 195: Class beanClass; 196: if (cl == null) 197: { 198: beanClass = Class.forName(beanName); 199: classLocation = 200: ClassLoader.getSystemResource(resourceName + ".class"); 201: } 202: else 203: { 204: beanClass = cl.loadClass(beanName); 205: classLocation = cl.getResource(resourceName + ".class"); 206: } 207: 208: // Instantiates and optionally registers the new bean. 209: try 210: { 211: bean = beanClass.newInstance(); 212: } 213: catch(Exception e) { 214: /* Wraps all kinds of Exceptions in a ClassNotFoundException (this behavior 215: * matches with official >= 1.5, this was different for <=1.4) 216: */ 217: throw new ClassNotFoundException(null, e); 218: } 219: } 220: 221: /* Applet beans are treated in the following way: 222: * - all AppletS get a default AppletStub 223: * - all AppletS are initialized using the AppletInitializer instance (if it is available) 224: * - as every other Bean Applets are added to a BeanContext if one is available 225: * - each instantiated Applet is initialized using Applet.init() (this is not done for deserialized ones) 226: * - finally AppletS get activated using the AppletInitializerS activate-Method 227: * 228: * The order of operations is important for compatibility. 229: */ 230: Applet applet = null; 231: if (bean instanceof Applet) 232: { 233: // Makes a second instanceof call unneccessary (instanceof is expensive). 234: applet = (Applet) bean; 235: 236: /* The AppletStub's code and document base is set as follows: 237: * The code base is always the URL from where the class data originated 238: * (without the package name). 239: * If the Applet was deserialized the document base is the location of 240: * the serialized instance (usually the ".ser" file) otherwise its the URL 241: * from where the class data originated (usually the absolute directory 242: * location of the ".class" file). 243: */ 244: applet.setStub( 245: new DummyAppletStub( 246: applet 247: .getClass() 248: .getProtectionDomain() 249: .getCodeSource() 250: .getLocation(), 251: (beanLocation == null) ? classLocation : beanLocation)); 252: 253: // Runs the Applet's initialization using an AppletInitializer. 254: if (initializer != null) 255: { 256: initializer.initialize(applet, beanContext); 257: } 258: } 259: 260: // Adds the new bean to its BeanContext. 261: if (beanContext != null) 262: { 263: beanContext.add(bean); 264: } 265: 266: if (applet != null) 267: { 268: 269: // Initializes an instantiated (not deserialized) Applet using its own method. 270: if (beanLocation == null) 271: { 272: applet.init(); 273: } 274: 275: // Runs the Applet's activation using an AppletInitializer. 276: if (initializer != null) 277: { 278: initializer.activate(applet); 279: } 280: } 281: 282: return bean; 283: } 284: 285: /** 286: * Returns the Bean as a different class type. 287: * This should be used instead of casting to get a new 288: * type view of a Bean, because in the future there may 289: * be new types of Bean, even Beans spanning multiple 290: * Objects. 291: * 292: * @param bean the Bean to cast. 293: * @param newClass the Class to cast it to. 294: * 295: * @return the Bean as a new view, or if the operation 296: * could not be performed, the Bean itself. 297: */ 298: public static Object getInstanceOf(Object bean, Class<?> newClass) 299: { 300: return bean; 301: } 302: 303: /** 304: * Determines whether the Bean can be cast to a different 305: * class type. 306: * This should be used instead of instanceof to determine 307: * a Bean's castability, because in the future there may 308: * be new types of Bean, even Beans spanning multiple 309: * Objects. 310: * 311: * @param bean the Bean to cast. 312: * @param newBeanClass the Class to cast it to. 313: * 314: * @return whether the Bean can be cast to the class type 315: * in question. 316: */ 317: public static boolean isInstanceOf(Object bean, Class<?> newBeanClass) 318: { 319: return newBeanClass.isInstance(bean); 320: } 321: 322: /** 323: * Returns whether the GUI is available to use. 324: * <p>Defaults to true.</p> 325: * 326: * @return whether the GUI is available to use. 327: */ 328: public static boolean isGuiAvailable() 329: { 330: return guiAvailable; 331: } 332: 333: /** 334: * Returns whether it is design time. Design time means 335: * we are in a RAD tool. 336: * <p>Defaults to false.</p> 337: * 338: * @return whether it is design time. 339: */ 340: public static boolean isDesignTime() 341: { 342: return designTime; 343: } 344: 345: /** 346: * Sets whether the GUI is available to use. 347: * 348: * @param guiAvailable whether the GUI is available to use. 349: */ 350: public static void setGuiAvailable(boolean guiAvailable) 351: throws SecurityException 352: { 353: Beans.guiAvailable = guiAvailable; 354: } 355: 356: /** 357: * Sets whether it is design time. Design time means we 358: * are in a RAD tool. 359: * 360: * @param designTime whether it is design time. 361: */ 362: public static void setDesignTime(boolean designTime) 363: throws SecurityException 364: { 365: Beans.designTime = designTime; 366: } 367: 368: }