home *** CD-ROM | disk | FTP | other *** search
/ Chip 1998 July / Chip_1998-07_cd.bin / zkuste / JBuilder / BDK / Win / bdk_sep97.exe / _SETUP.1 / Beans.java < prev    next >
Encoding:
Java Source  |  1997-06-05  |  13.5 KB  |  444 lines

  1. /*
  2.  * @(#)Beans.java    1.24 97/01/06  
  3.  * 
  4.  * Copyright (c) 1996 Sun Microsystems, Inc. All Rights Reserved.
  5.  * 
  6.  * This software is the confidential and proprietary information of Sun
  7.  * Microsystems, Inc. ("Confidential Information").  You shall not
  8.  * disclose such Confidential Information and shall use it only in
  9.  * accordance with the terms of the license agreement you entered into
  10.  * with Sun.
  11.  * 
  12.  * SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE
  13.  * SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
  14.  * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
  15.  * PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR ANY DAMAGES
  16.  * SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING
  17.  * THIS SOFTWARE OR ITS DERIVATIVES.
  18.  * 
  19.  * CopyrightVersion bdk_beta
  20.  * 
  21.  */
  22.  
  23. package java.beans;
  24.  
  25. import java.io.*;
  26. import java.awt.*;
  27. import java.applet.*;
  28. import java.net.URL;
  29.  
  30. /**
  31.  * This class provides some general purpose beans control methods.
  32.  */
  33.  
  34. public class Beans {
  35.  
  36.     /**
  37.      * Instantiate a bean.
  38.      * <p>
  39.      * The bean is created based on a name relative to a class-loader.
  40.      * This name should be a dot-separated name such as "a.b.c".
  41.      * <p>
  42.      * In Beans 1.0 the given name can indicate either a serialized object
  43.      * or a class.  Other mechanisms may be added in the future.  In
  44.      * beans 1.0 we first try to treat the beanName as a serialized object
  45.      * name then as a class name.
  46.      * <p>
  47.      * When using the beanName as a serialized object name we convert the
  48.      * given beanName to a resource pathname and add a trailing ".ser" suffix.
  49.      * We then try to load a serialized object from that resource.
  50.      * <p>
  51.      * For example, given a beanName of "x.y", Beans.instantiate would first
  52.      * try to read a serialized object from the resource "x/y.ser" and if
  53.      * that failed it would try to load the class "x.y" and create an
  54.      * instance of that class.
  55.      * <p>
  56.      * If the bean is a subtype of java.applet.Applet, then it is given
  57.      * some special initialization.  First, it is supplied with a default
  58.      * AppletStub and AppletContext.  Second, if it was instantiated from 
  59.      * a classname the applet's "init" method is called.  (If the bean was
  60.      * deserialized this step is skipped.) 
  61.      * <p>
  62.      * Note that for beans which are applets, it is the caller's responsiblity
  63.      * to call "start" on the applet.  For correct behaviour, this should be done
  64.      * after the applet has been added into a visible AWT container.
  65.      * <p>
  66.      * Note that applets created via beans.instantiate run in a slightly
  67.      * different environment than applets running inside browsers.  In
  68.      * particular, bean applets have no access to "parameters", so they may 
  69.      * wish to provide property get/set methods to set parameter values.  We
  70.      * advise bean-applet developers to test their bean-applets against both
  71.      * the JDK appletviewer (for a reference browser environment) and the
  72.      * BDK BeanBox (for a reference bean container).
  73.      * 
  74.      * @param     classLoader the class-loader from which we should create
  75.      *                       the bean.  If this is null, then the system
  76.      *                        class-loader is used.
  77.      * @param     beanName    the name of the bean within the class-loader.
  78.      *                     For example "sun.beanbox.foobah"
  79.      * @exception java.lang.ClassNotFoundException if the class of a serialized
  80.      *              object could not be found.
  81.      * @exception java.io.IOException if an I/O error occurs.
  82.      */
  83.     public static Object instantiate(ClassLoader cls, String beanName) 
  84.             throws java.io.IOException, ClassNotFoundException {
  85.  
  86.     java.io.InputStream ins;
  87.     java.io.ObjectInputStream oins = null;
  88.     Object result = null;
  89.     boolean serialized = false;
  90.  
  91.     // Try to find a serialized object with this name
  92.     String serName = beanName.replace('.','/').concat(".ser");
  93.     if (cls == null) {
  94.         ins = ClassLoader.getSystemResourceAsStream(serName);
  95.     } else {
  96.         ins  = cls.getResourceAsStream(serName);
  97.     }
  98.     if (ins != null) {
  99.         try {
  100.             if (cls == null) {
  101.             oins = new ObjectInputStream(ins);
  102.             } else {
  103.             oins = new ObjectInputStreamWithLoader(ins, cls);
  104.             }
  105.             result = oins.readObject();
  106.         serialized = true;
  107.             oins.close();
  108.         } catch (java.io.IOException ex) {
  109.         ins.close();
  110.         // For now, drop through and try opening the class.
  111.         // throw ex;
  112.         } catch (ClassNotFoundException ex) {
  113.         ins.close();
  114.         throw ex;
  115.         }
  116.     }
  117.  
  118.     if (result == null) {
  119.         // No serialized object, try just instantiating the class
  120.         Class cl;
  121.         if (cls == null) {
  122.             cl = Class.forName(beanName);
  123.         } else {
  124.             cl = cls.loadClass(beanName);
  125.         }
  126.         try {
  127.             result = cl.newInstance();
  128.         } catch (Exception ex) {
  129.             throw new ClassNotFoundException();
  130.         }
  131.     }
  132.     // Ok, if the result is an applet initialize it.
  133.     if (result != null && result instanceof Applet) {
  134.         Applet applet = (Applet) result;
  135.  
  136.         // Figure our the codebase and docbase URLs.  We do this
  137.         // by locating the URL for a known resource, and then
  138.         // massaging the URL.
  139.  
  140.         // First find the "resource name" corresponding to the bean
  141.         // itself.  So a serialzied bean "a.b.c" would imply a resource
  142.         // name of "a/b/c.ser" and a classname of "x.y" would imply
  143.         // a resource name of "x/y.class".
  144.  
  145.         String resourceName;
  146.         if (serialized) {
  147.         // Serialized bean
  148.         resourceName = beanName.replace('.','/').concat(".ser");
  149.         } else {
  150.         // Regular class
  151.         resourceName = beanName.replace('.','/').concat(".class");
  152.         }
  153.         URL objectUrl = null;
  154.         URL codeBase = null;
  155.         URL docBase = null;
  156.  
  157.         // Now get the URL correponding to the resource name.
  158.         if (cls == null) {
  159.         objectUrl = ClassLoader.getSystemResource(resourceName);
  160.         } else {
  161.         objectUrl = cls.getResource(resourceName);
  162.         }
  163.  
  164.         // If we found a URL, we try to locate the docbase by taking
  165.         // of the final path name component, and the code base by taking
  166.            // of the complete resourceName.
  167.         // So if we had a resourceName of "a/b/c.class" and we got an
  168.         // objectURL of "file://bert/classes/a/b/c.class" then we would
  169.         // want to set the codebase to "file://bert/classes/" and the
  170.         // docbase to "file://bert/classes/a/b/"
  171.  
  172.         if (objectUrl != null) {
  173.         String s = objectUrl.toExternalForm();
  174.         if (s.endsWith(resourceName)) {
  175.               int ix = s.length() - resourceName.length();
  176.             codeBase = new URL(s.substring(0,ix));
  177.             docBase = codeBase;
  178.             ix = s.lastIndexOf('/');
  179.             if (ix >= 0) {
  180.                 docBase = new URL(s.substring(0,ix+1));
  181.             }
  182.         }
  183.         }
  184.                 
  185.         // Setup a default context and stub.
  186.         BeansAppletContext context = new BeansAppletContext(applet);
  187.         BeansAppletStub stub = new BeansAppletStub(applet, context, codeBase, docBase);
  188.         applet.setStub(stub);
  189.  
  190.         // If it was deserialized then it was already init-ed.  Otherwise
  191.         // we need to initialize it.
  192.         if (!serialized) {
  193.         // We need to set a reasonable initial size, as many
  194.         // applets are unhappy if they are started without 
  195.         // having been explicitly sized.
  196.         applet.setSize(100,100);
  197.         applet.init();
  198.         }
  199.         stub.active = true;
  200.     }
  201.     return result;
  202.     }
  203.  
  204.  
  205.     /**
  206.      * From a given bean, obtain an object representing a specified
  207.      * type view of that source object. 
  208.      * <p>
  209.      * The result may be the same object or a different object.  If
  210.      * the requested target view isn't available then the given
  211.      * bean is returned.
  212.      * <p>
  213.      * This method is provided in Beans 1.0 as a hook to allow the
  214.      * addition of more flexible bean behaviour in the future.
  215.      *
  216.      * @param obj  Object from which we want to obtain a view.
  217.      * @param targetType  The type of view we'd like to get.
  218.      *
  219.      */
  220.     public static Object getInstanceOf(Object bean, Class targetType) {
  221.         return bean;
  222.     }
  223.  
  224.     /**
  225.      * Check if a bean can be viewed as a given target type.
  226.      * The result will be true if the Beans.getInstanceof method
  227.      * can be used on the given bean to obtain an object that
  228.      * represents the specified targetType type view.
  229.      *
  230.      * @param bean  Bean from which we want to obtain a view.
  231.      * @param targetType  The type of view we'd like to get.
  232.      * @return "true" if the given bean supports the given targetType.
  233.      */
  234.     public static boolean isInstanceOf(Object bean, Class targetType) {
  235.     return Introspector.isSubclass(bean.getClass(), targetType);
  236.     }
  237.  
  238.  
  239.     /**
  240.      * Test if we are in design-mode.
  241.      *
  242.      * @return  True if we are running in an application construction
  243.      *        environment.
  244.      */
  245.     public static boolean isDesignTime() {
  246.     return designTime;
  247.     }
  248.  
  249.     /**
  250.      * @return  True if we are running in an environment where beans
  251.      *       can assume that an interactive GUI is available, so they 
  252.      *       can pop up dialog boxes, etc.  This will normally return
  253.      *       true in a windowing environment, and will normally return
  254.      *       false in a server environment or if an application is
  255.      *       running as part of a batch job.
  256.      */
  257.     public static boolean isGuiAvailable() {
  258.     return guiAvailable;
  259.     }
  260.  
  261.     /**
  262.      * Used to indicate whether of not we are running in an application
  263.      * builder environment.  Note that this method is security checked
  264.      * and is not available to (for example) untrusted applets.
  265.      *
  266.      * @param isDesignTime  True if we're in an application builder tool.
  267.      */
  268.  
  269.     public static void setDesignTime(boolean isDesignTime)
  270.             throws SecurityException {
  271.     designTime = isDesignTime;
  272.     }
  273.  
  274.     /**
  275.      * Used to indicate whether of not we are running in an environment
  276.      * where GUI interaction is available.  Note that this method is 
  277.      * security checked and is not available to (for example) untrusted
  278.      * applets.
  279.      *
  280.      * @param isGuiAvailable  True if GUI interaction is available.
  281.      */
  282.  
  283.     public static void setGuiAvailable(boolean isGuiAvailable)
  284.             throws SecurityException {
  285.     guiAvailable = isGuiAvailable;
  286.     }
  287.  
  288.  
  289.     private static boolean designTime;
  290.     private static boolean guiAvailable = true;
  291. }
  292.  
  293. /**
  294.  * This subclass of ObjectInputStream delegates loading of classes to
  295.  * an existing ClassLoader.
  296.  */
  297.  
  298. class ObjectInputStreamWithLoader extends ObjectInputStream
  299. {
  300.     private ClassLoader loader;
  301.  
  302.     /**
  303.      * Loader must be non-null;
  304.      */
  305.  
  306.     public ObjectInputStreamWithLoader(InputStream in, ClassLoader loader)
  307.         throws IOException, StreamCorruptedException {
  308.  
  309.     super(in);
  310.     if (loader == null) {
  311.             throw new IllegalArgumentException("Illegal null argument to ObjectInputStreamWithLoader");
  312.     }
  313.     this.loader = loader;
  314.     }
  315.  
  316.     /**
  317.      * Use the given ClassLoader rather than using the system class
  318.      */
  319.     protected Class resolveClass(ObjectStreamClass classDesc)
  320.     throws IOException, ClassNotFoundException {
  321.  
  322.     String classname = classDesc.getName();
  323.     return loader.loadClass(classname);
  324.     }
  325. }
  326.  
  327. /**
  328.  * Package private support class.  This provides a default AppletContext
  329.  * for beans which are applets.
  330.  */
  331.  
  332. class BeansAppletContext implements AppletContext {
  333.     Applet target;
  334.     java.util.Hashtable imageCache = new java.util.Hashtable();
  335.  
  336.     BeansAppletContext(Applet target) {
  337.         this.target = target;
  338.     }
  339.  
  340.     public AudioClip getAudioClip(URL url) {
  341.     // We don't currently support audio clips in the Beans.instantiate
  342.     // applet context, unless by some luck there exists a URL content
  343.     // class that can generate an AudioClip from the audio URL.
  344.     try {
  345.         return (AudioClip) url.getContent();
  346.       } catch (Exception ex) {
  347.         return null;
  348.     }
  349.     }
  350.  
  351.     public synchronized Image getImage(URL url) {
  352.     Object o = imageCache.get(url);
  353.     if (o != null) {
  354.         return (Image)o;
  355.     }
  356.     try {
  357.         o = url.getContent();
  358.         if (o == null) {
  359.         return null;
  360.         }
  361.         if (o instanceof Image) {
  362.         imageCache.put(url, o);
  363.         return (Image) o;
  364.         }
  365.         // Otherwise it must be an ImageProducer.
  366.         Image img = target.createImage((java.awt.image.ImageProducer)o);
  367.         imageCache.put(url, img);
  368.         return img;
  369.  
  370.       } catch (Exception ex) {
  371.         return null;
  372.     }
  373.     }
  374.  
  375.     public Applet getApplet(String name) {
  376.     return null;
  377.     }
  378.  
  379.     public java.util.Enumeration getApplets() {
  380.     java.util.Vector applets = new java.util.Vector();
  381.     applets.addElement(target);
  382.     return applets.elements();    
  383.     }
  384.  
  385.     public void showDocument(URL url) {
  386.     // We do nothing.
  387.     }
  388.  
  389.     public void showDocument(URL url, String target) {
  390.     // We do nothing.
  391.     }
  392.  
  393.     public void showStatus(String status) {
  394.     // We do nothing.
  395.     }
  396. }
  397.  
  398. /**
  399.  * Package private support class.  This provides an AppletStub
  400.  * for beans which are applets.
  401.  */
  402. class BeansAppletStub implements AppletStub {
  403.     transient boolean active;
  404.     transient Applet target;
  405.     transient AppletContext context;
  406.     transient URL codeBase;
  407.     transient URL docBase;
  408.  
  409.     BeansAppletStub(Applet target,
  410.         AppletContext context, URL codeBase, 
  411.                 URL docBase) {
  412.         this.target = target;
  413.     this.context = context;
  414.     this.codeBase = codeBase;
  415.     this.docBase = docBase;
  416.     }
  417.  
  418.     public boolean isActive() {
  419.     return active;
  420.     }
  421.     
  422.     public URL getDocumentBase() {
  423.     // use the root directory of the applet's class-loader
  424.     return docBase;
  425.     }
  426.  
  427.     public URL getCodeBase() {
  428.     // use the directory where we found the class or serialized object.
  429.     return codeBase;
  430.     }
  431.  
  432.     public String getParameter(String name) {
  433.     return null;
  434.     }
  435.  
  436.     public AppletContext getAppletContext() {
  437.     return context;
  438.     }
  439.  
  440.     public void appletResize(int width, int height) {
  441.     // we do nothing.
  442.     }
  443. }
  444.