Save This Page
Home » openjdk-7 » java » beans » [javadoc | source]
    1   /*
    2    * Copyright 1996-2006 Sun Microsystems, Inc.  All Rights Reserved.
    3    * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    4    *
    5    * This code is free software; you can redistribute it and/or modify it
    6    * under the terms of the GNU General Public License version 2 only, as
    7    * published by the Free Software Foundation.  Sun designates this
    8    * particular file as subject to the "Classpath" exception as provided
    9    * by Sun in the LICENSE file that accompanied this code.
   10    *
   11    * This code is distributed in the hope that it will be useful, but WITHOUT
   12    * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   13    * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   14    * version 2 for more details (a copy is included in the LICENSE file that
   15    * accompanied this code).
   16    *
   17    * You should have received a copy of the GNU General Public License version
   18    * 2 along with this work; if not, write to the Free Software Foundation,
   19    * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   20    *
   21    * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
   22    * CA 95054 USA or visit www.sun.com if you need additional information or
   23    * have any questions.
   24    */
   25   
   26   package java.beans;
   27   
   28   import com.sun.beans.finder.ClassFinder;
   29   
   30   import java.applet;
   31   
   32   import java.awt;
   33   
   34   import java.beans.AppletInitializer;
   35   
   36   import java.beans.beancontext.BeanContext;
   37   
   38   import java.io;
   39   
   40   import java.lang.reflect.Constructor;
   41   
   42   import java.net.URL;
   43   import java.lang.reflect.Array;
   44   
   45   /**
   46    * This class provides some general purpose beans control methods.
   47    */
   48   
   49   public class Beans {
   50   
   51       /**
   52        * <p>
   53        * Instantiate a JavaBean.
   54        * </p>
   55        *
   56        * @param     cls         the class-loader from which we should create
   57        *                        the bean.  If this is null, then the system
   58        *                        class-loader is used.
   59        * @param     beanName    the name of the bean within the class-loader.
   60        *                        For example "sun.beanbox.foobah"
   61        *
   62        * @exception java.lang.ClassNotFoundException if the class of a serialized
   63        *              object could not be found.
   64        * @exception java.io.IOException if an I/O error occurs.
   65        */
   66   
   67       public static Object instantiate(ClassLoader cls, String beanName) throws java.io.IOException, ClassNotFoundException {
   68           return Beans.instantiate(cls, beanName, null, null);
   69       }
   70   
   71       /**
   72        * <p>
   73        * Instantiate a JavaBean.
   74        * </p>
   75        *
   76        * @param     cls         the class-loader from which we should create
   77        *                        the bean.  If this is null, then the system
   78        *                        class-loader is used.
   79        * @param     beanName    the name of the bean within the class-loader.
   80        *                        For example "sun.beanbox.foobah"
   81        * @param     beanContext The BeanContext in which to nest the new bean
   82        *
   83        * @exception java.lang.ClassNotFoundException if the class of a serialized
   84        *              object could not be found.
   85        * @exception java.io.IOException if an I/O error occurs.
   86        */
   87   
   88       public static Object instantiate(ClassLoader cls, String beanName, BeanContext beanContext) throws java.io.IOException, ClassNotFoundException {
   89           return Beans.instantiate(cls, beanName, beanContext, null);
   90       }
   91   
   92       /**
   93        * Instantiate a bean.
   94        * <p>
   95        * The bean is created based on a name relative to a class-loader.
   96        * This name should be a dot-separated name such as "a.b.c".
   97        * <p>
   98        * In Beans 1.0 the given name can indicate either a serialized object
   99        * or a class.  Other mechanisms may be added in the future.  In
  100        * beans 1.0 we first try to treat the beanName as a serialized object
  101        * name then as a class name.
  102        * <p>
  103        * When using the beanName as a serialized object name we convert the
  104        * given beanName to a resource pathname and add a trailing ".ser" suffix.
  105        * We then try to load a serialized object from that resource.
  106        * <p>
  107        * For example, given a beanName of "x.y", Beans.instantiate would first
  108        * try to read a serialized object from the resource "x/y.ser" and if
  109        * that failed it would try to load the class "x.y" and create an
  110        * instance of that class.
  111        * <p>
  112        * If the bean is a subtype of java.applet.Applet, then it is given
  113        * some special initialization.  First, it is supplied with a default
  114        * AppletStub and AppletContext.  Second, if it was instantiated from
  115        * a classname the applet's "init" method is called.  (If the bean was
  116        * deserialized this step is skipped.)
  117        * <p>
  118        * Note that for beans which are applets, it is the caller's responsiblity
  119        * to call "start" on the applet.  For correct behaviour, this should be done
  120        * after the applet has been added into a visible AWT container.
  121        * <p>
  122        * Note that applets created via beans.instantiate run in a slightly
  123        * different environment than applets running inside browsers.  In
  124        * particular, bean applets have no access to "parameters", so they may
  125        * wish to provide property get/set methods to set parameter values.  We
  126        * advise bean-applet developers to test their bean-applets against both
  127        * the JDK appletviewer (for a reference browser environment) and the
  128        * BDK BeanBox (for a reference bean container).
  129        *
  130        * @param     cls         the class-loader from which we should create
  131        *                        the bean.  If this is null, then the system
  132        *                        class-loader is used.
  133        * @param     beanName    the name of the bean within the class-loader.
  134        *                        For example "sun.beanbox.foobah"
  135        * @param     beanContext The BeanContext in which to nest the new bean
  136        * @param     initializer The AppletInitializer for the new bean
  137        *
  138        * @exception java.lang.ClassNotFoundException if the class of a serialized
  139        *              object could not be found.
  140        * @exception java.io.IOException if an I/O error occurs.
  141        */
  142   
  143       public static Object instantiate(ClassLoader cls, String beanName, BeanContext beanContext, AppletInitializer initializer)
  144                           throws java.io.IOException, ClassNotFoundException {
  145   
  146           java.io.InputStream ins;
  147           java.io.ObjectInputStream oins = null;
  148           Object result = null;
  149           boolean serialized = false;
  150           java.io.IOException serex = null;
  151   
  152           // If the given classloader is null, we check if an
  153           // system classloader is available and (if so)
  154           // use that instead.
  155           // Note that calls on the system class loader will
  156           // look in the bootstrap class loader first.
  157           if (cls == null) {
  158               try {
  159                   cls = ClassLoader.getSystemClassLoader();
  160               } catch (SecurityException ex) {
  161                   // We're not allowed to access the system class loader.
  162                   // Drop through.
  163               }
  164           }
  165   
  166           // Try to find a serialized object with this name
  167           final String serName = beanName.replace('.','/').concat(".ser");
  168           final ClassLoader loader = cls;
  169           ins = (InputStream)java.security.AccessController.doPrivileged
  170               (new java.security.PrivilegedAction() {
  171                   public Object run() {
  172                       if (loader == null)
  173                           return ClassLoader.getSystemResourceAsStream(serName);
  174                       else
  175                           return loader.getResourceAsStream(serName);
  176                   }
  177           });
  178           if (ins != null) {
  179               try {
  180                   if (cls == null) {
  181                       oins = new ObjectInputStream(ins);
  182                   } else {
  183                       oins = new ObjectInputStreamWithLoader(ins, cls);
  184                   }
  185                   result = oins.readObject();
  186                   serialized = true;
  187                   oins.close();
  188               } catch (java.io.IOException ex) {
  189                   ins.close();
  190                   // Drop through and try opening the class.  But remember
  191                   // the exception in case we can't find the class either.
  192                   serex = ex;
  193               } catch (ClassNotFoundException ex) {
  194                   ins.close();
  195                   throw ex;
  196               }
  197           }
  198   
  199           if (result == null) {
  200               // No serialized object, try just instantiating the class
  201               Class cl;
  202   
  203               try {
  204                   cl = ClassFinder.findClass(beanName, cls);
  205               } catch (ClassNotFoundException ex) {
  206                   // There is no appropriate class.  If we earlier tried to
  207                   // deserialize an object and got an IO exception, throw that,
  208                   // otherwise rethrow the ClassNotFoundException.
  209                   if (serex != null) {
  210                       throw serex;
  211                   }
  212                   throw ex;
  213               }
  214   
  215               /*
  216                * Try to instantiate the class.
  217                */
  218   
  219               try {
  220                   result = cl.newInstance();
  221               } catch (Exception ex) {
  222                   // We have to remap the exception to one in our signature.
  223                   // But we pass extra information in the detail message.
  224                   throw new ClassNotFoundException("" + cl + " : " + ex, ex);
  225               }
  226           }
  227   
  228           if (result != null) {
  229   
  230               // Ok, if the result is an applet initialize it.
  231   
  232               AppletStub stub = null;
  233   
  234               if (result instanceof Applet) {
  235                   Applet  applet      = (Applet) result;
  236                   boolean needDummies = initializer == null;
  237   
  238                   if (needDummies) {
  239   
  240                       // Figure our the codebase and docbase URLs.  We do this
  241                       // by locating the URL for a known resource, and then
  242                       // massaging the URL.
  243   
  244                       // First find the "resource name" corresponding to the bean
  245                       // itself.  So a serialzied bean "a.b.c" would imply a
  246                       // resource name of "a/b/c.ser" and a classname of "x.y"
  247                       // would imply a resource name of "x/y.class".
  248   
  249                       final String resourceName;
  250   
  251                       if (serialized) {
  252                           // Serialized bean
  253                           resourceName = beanName.replace('.','/').concat(".ser");
  254                       } else {
  255                           // Regular class
  256                           resourceName = beanName.replace('.','/').concat(".class");
  257                       }
  258   
  259                       URL objectUrl = null;
  260                       URL codeBase  = null;
  261                       URL docBase   = null;
  262   
  263                       // Now get the URL correponding to the resource name.
  264   
  265                       final ClassLoader cloader = cls;
  266                       objectUrl = (URL)
  267                           java.security.AccessController.doPrivileged
  268                           (new java.security.PrivilegedAction() {
  269                               public Object run() {
  270                                   if (cloader == null)
  271                                       return ClassLoader.getSystemResource
  272                                                                   (resourceName);
  273                                   else
  274                                       return cloader.getResource(resourceName);
  275                               }
  276                       });
  277   
  278                       // If we found a URL, we try to locate the docbase by taking
  279                       // of the final path name component, and the code base by taking
  280                       // of the complete resourceName.
  281                       // So if we had a resourceName of "a/b/c.class" and we got an
  282                       // objectURL of "file://bert/classes/a/b/c.class" then we would
  283                       // want to set the codebase to "file://bert/classes/" and the
  284                       // docbase to "file://bert/classes/a/b/"
  285   
  286                       if (objectUrl != null) {
  287                           String s = objectUrl.toExternalForm();
  288   
  289                           if (s.endsWith(resourceName)) {
  290                               int ix   = s.length() - resourceName.length();
  291                               codeBase = new URL(s.substring(0,ix));
  292                               docBase  = codeBase;
  293   
  294                               ix = s.lastIndexOf('/');
  295   
  296                               if (ix >= 0) {
  297                                   docBase = new URL(s.substring(0,ix+1));
  298                               }
  299                           }
  300                       }
  301   
  302                       // Setup a default context and stub.
  303                       BeansAppletContext context = new BeansAppletContext(applet);
  304   
  305                       stub = (AppletStub)new BeansAppletStub(applet, context, codeBase, docBase);
  306                       applet.setStub(stub);
  307                   } else {
  308                       initializer.initialize(applet, beanContext);
  309                   }
  310   
  311                   // now, if there is a BeanContext, add the bean, if applicable.
  312   
  313                   if (beanContext != null) {
  314                       beanContext.add(result);
  315                   }
  316   
  317                   // If it was deserialized then it was already init-ed.
  318                   // Otherwise we need to initialize it.
  319   
  320                   if (!serialized) {
  321                       // We need to set a reasonable initial size, as many
  322                       // applets are unhappy if they are started without
  323                       // having been explicitly sized.
  324                       applet.setSize(100,100);
  325                       applet.init();
  326                   }
  327   
  328                   if (needDummies) {
  329                     ((BeansAppletStub)stub).active = true;
  330                   } else initializer.activate(applet);
  331   
  332               } else if (beanContext != null) beanContext.add(result);
  333           }
  334   
  335           return result;
  336       }
  337   
  338   
  339       /**
  340        * From a given bean, obtain an object representing a specified
  341        * type view of that source object.
  342        * <p>
  343        * The result may be the same object or a different object.  If
  344        * the requested target view isn't available then the given
  345        * bean is returned.
  346        * <p>
  347        * This method is provided in Beans 1.0 as a hook to allow the
  348        * addition of more flexible bean behaviour in the future.
  349        *
  350        * @param bean        Object from which we want to obtain a view.
  351        * @param targetType  The type of view we'd like to get.
  352        *
  353        */
  354       public static Object getInstanceOf(Object bean, Class<?> targetType) {
  355           return bean;
  356       }
  357   
  358       /**
  359        * Check if a bean can be viewed as a given target type.
  360        * The result will be true if the Beans.getInstanceof method
  361        * can be used on the given bean to obtain an object that
  362        * represents the specified targetType type view.
  363        *
  364        * @param bean  Bean from which we want to obtain a view.
  365        * @param targetType  The type of view we'd like to get.
  366        * @return "true" if the given bean supports the given targetType.
  367        *
  368        */
  369       public static boolean isInstanceOf(Object bean, Class<?> targetType) {
  370           return Introspector.isSubclass(bean.getClass(), targetType);
  371       }
  372   
  373   
  374       /**
  375        * Test if we are in design-mode.
  376        *
  377        * @return  True if we are running in an application construction
  378        *          environment.
  379        *
  380        * @see java.beans.DesignMode
  381        */
  382       public static boolean isDesignTime() {
  383           return designTime;
  384       }
  385   
  386       /**
  387        * Determines whether beans can assume a GUI is available.
  388        *
  389        * @return  True if we are running in an environment where beans
  390        *     can assume that an interactive GUI is available, so they
  391        *     can pop up dialog boxes, etc.  This will normally return
  392        *     true in a windowing environment, and will normally return
  393        *     false in a server environment or if an application is
  394        *     running as part of a batch job.
  395        *
  396        * @see java.beans.Visibility
  397        *
  398        */
  399       public static boolean isGuiAvailable() {
  400           return guiAvailable;
  401       }
  402   
  403       /**
  404        * Used to indicate whether of not we are running in an application
  405        * builder environment.
  406        *
  407        * <p>Note that this method is security checked
  408        * and is not available to (for example) untrusted applets.
  409        * More specifically, if there is a security manager,
  410        * its <code>checkPropertiesAccess</code>
  411        * method is called. This could result in a SecurityException.
  412        *
  413        * @param isDesignTime  True if we're in an application builder tool.
  414        * @exception  SecurityException  if a security manager exists and its
  415        *             <code>checkPropertiesAccess</code> method doesn't allow setting
  416        *              of system properties.
  417        * @see SecurityManager#checkPropertiesAccess
  418        */
  419   
  420       public static void setDesignTime(boolean isDesignTime)
  421                           throws SecurityException {
  422           SecurityManager sm = System.getSecurityManager();
  423           if (sm != null) {
  424               sm.checkPropertiesAccess();
  425           }
  426           designTime = isDesignTime;
  427       }
  428   
  429       /**
  430        * Used to indicate whether of not we are running in an environment
  431        * where GUI interaction is available.
  432        *
  433        * <p>Note that this method is security checked
  434        * and is not available to (for example) untrusted applets.
  435        * More specifically, if there is a security manager,
  436        * its <code>checkPropertiesAccess</code>
  437        * method is called. This could result in a SecurityException.
  438        *
  439        * @param isGuiAvailable  True if GUI interaction is available.
  440        * @exception  SecurityException  if a security manager exists and its
  441        *             <code>checkPropertiesAccess</code> method doesn't allow setting
  442        *              of system properties.
  443        * @see SecurityManager#checkPropertiesAccess
  444        */
  445   
  446       public static void setGuiAvailable(boolean isGuiAvailable)
  447                           throws SecurityException {
  448           SecurityManager sm = System.getSecurityManager();
  449           if (sm != null) {
  450               sm.checkPropertiesAccess();
  451           }
  452           guiAvailable = isGuiAvailable;
  453       }
  454   
  455   
  456       private static boolean designTime;
  457       private static boolean guiAvailable;
  458       static {
  459           guiAvailable = !GraphicsEnvironment.isHeadless();
  460       }
  461   }
  462   
  463   /**
  464    * This subclass of ObjectInputStream delegates loading of classes to
  465    * an existing ClassLoader.
  466    */
  467   
  468   class ObjectInputStreamWithLoader extends ObjectInputStream
  469   {
  470       private ClassLoader loader;
  471   
  472       /**
  473        * Loader must be non-null;
  474        */
  475   
  476       public ObjectInputStreamWithLoader(InputStream in, ClassLoader loader)
  477               throws IOException, StreamCorruptedException {
  478   
  479           super(in);
  480           if (loader == null) {
  481               throw new IllegalArgumentException("Illegal null argument to ObjectInputStreamWithLoader");
  482           }
  483           this.loader = loader;
  484       }
  485   
  486       /**
  487        * Use the given ClassLoader rather than using the system class
  488        */
  489       protected Class resolveClass(ObjectStreamClass classDesc)
  490           throws IOException, ClassNotFoundException {
  491   
  492           String cname = classDesc.getName();
  493           return ClassFinder.resolveClass(cname, this.loader);
  494       }
  495   }
  496   
  497   /**
  498    * Package private support class.  This provides a default AppletContext
  499    * for beans which are applets.
  500    */
  501   
  502   class BeansAppletContext implements AppletContext {
  503       Applet target;
  504       java.util.Hashtable imageCache = new java.util.Hashtable();
  505   
  506       BeansAppletContext(Applet target) {
  507           this.target = target;
  508       }
  509   
  510       public AudioClip getAudioClip(URL url) {
  511           // We don't currently support audio clips in the Beans.instantiate
  512           // applet context, unless by some luck there exists a URL content
  513           // class that can generate an AudioClip from the audio URL.
  514           try {
  515               return (AudioClip) url.getContent();
  516           } catch (Exception ex) {
  517               return null;
  518           }
  519       }
  520   
  521       public synchronized Image getImage(URL url) {
  522           Object o = imageCache.get(url);
  523           if (o != null) {
  524               return (Image)o;
  525           }
  526           try {
  527               o = url.getContent();
  528               if (o == null) {
  529                   return null;
  530               }
  531               if (o instanceof Image) {
  532                   imageCache.put(url, o);
  533                   return (Image) o;
  534               }
  535               // Otherwise it must be an ImageProducer.
  536               Image img = target.createImage((java.awt.image.ImageProducer)o);
  537               imageCache.put(url, img);
  538               return img;
  539   
  540           } catch (Exception ex) {
  541               return null;
  542           }
  543       }
  544   
  545       public Applet getApplet(String name) {
  546           return null;
  547       }
  548   
  549       public java.util.Enumeration getApplets() {
  550           java.util.Vector applets = new java.util.Vector();
  551           applets.addElement(target);
  552           return applets.elements();
  553       }
  554   
  555       public void showDocument(URL url) {
  556           // We do nothing.
  557       }
  558   
  559       public void showDocument(URL url, String target) {
  560           // We do nothing.
  561       }
  562   
  563       public void showStatus(String status) {
  564           // We do nothing.
  565       }
  566   
  567       public void setStream(String key, InputStream stream)throws IOException{
  568           // We do nothing.
  569       }
  570   
  571       public InputStream getStream(String key){
  572           // We do nothing.
  573           return null;
  574       }
  575   
  576       public java.util.Iterator getStreamKeys(){
  577           // We do nothing.
  578           return null;
  579       }
  580   }
  581   
  582   /**
  583    * Package private support class.  This provides an AppletStub
  584    * for beans which are applets.
  585    */
  586   class BeansAppletStub implements AppletStub {
  587       transient boolean active;
  588       transient Applet target;
  589       transient AppletContext context;
  590       transient URL codeBase;
  591       transient URL docBase;
  592   
  593       BeansAppletStub(Applet target,
  594                   AppletContext context, URL codeBase,
  595                                   URL docBase) {
  596           this.target = target;
  597           this.context = context;
  598           this.codeBase = codeBase;
  599           this.docBase = docBase;
  600       }
  601   
  602       public boolean isActive() {
  603           return active;
  604       }
  605   
  606       public URL getDocumentBase() {
  607           // use the root directory of the applet's class-loader
  608           return docBase;
  609       }
  610   
  611       public URL getCodeBase() {
  612           // use the directory where we found the class or serialized object.
  613           return codeBase;
  614       }
  615   
  616       public String getParameter(String name) {
  617           return null;
  618       }
  619   
  620       public AppletContext getAppletContext() {
  621           return context;
  622       }
  623   
  624       public void appletResize(int width, int height) {
  625           // we do nothing.
  626       }
  627   }

Save This Page
Home » openjdk-7 » java » beans » [javadoc | source]