Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/classes/java/beans/Beans.java
38829 views
/*1* Copyright (c) 1996, 2015, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425package java.beans;2627import com.sun.beans.finder.ClassFinder;2829import java.applet.Applet;30import java.applet.AppletContext;31import java.applet.AppletStub;32import java.applet.AudioClip;3334import java.awt.Image;3536import java.beans.beancontext.BeanContext;3738import java.io.IOException;39import java.io.InputStream;40import java.io.ObjectInputStream;41import java.io.ObjectStreamClass;42import java.io.StreamCorruptedException;4344import java.lang.reflect.Modifier;4546import java.net.URL;4748import java.util.Enumeration;49import java.util.Hashtable;50import java.util.Iterator;51import java.util.Vector;5253/**54* This class provides some general purpose beans control methods.55*/5657public class Beans {5859/**60* <p>61* Instantiate a JavaBean.62* </p>63* @return a JavaBean64* @param cls the class-loader from which we should create65* the bean. If this is null, then the system66* class-loader is used.67* @param beanName the name of the bean within the class-loader.68* For example "sun.beanbox.foobah"69*70* @exception ClassNotFoundException if the class of a serialized71* object could not be found.72* @exception IOException if an I/O error occurs.73*/7475public static Object instantiate(ClassLoader cls, String beanName) throws IOException, ClassNotFoundException {76return Beans.instantiate(cls, beanName, null, null);77}7879/**80* <p>81* Instantiate a JavaBean.82* </p>83* @return a JavaBean84*85* @param cls the class-loader from which we should create86* the bean. If this is null, then the system87* class-loader is used.88* @param beanName the name of the bean within the class-loader.89* For example "sun.beanbox.foobah"90* @param beanContext The BeanContext in which to nest the new bean91*92* @exception ClassNotFoundException if the class of a serialized93* object could not be found.94* @exception IOException if an I/O error occurs.95*/9697public static Object instantiate(ClassLoader cls, String beanName, BeanContext beanContext) throws IOException, ClassNotFoundException {98return Beans.instantiate(cls, beanName, beanContext, null);99}100101/**102* Instantiate a bean.103* <p>104* The bean is created based on a name relative to a class-loader.105* This name should be a dot-separated name such as "a.b.c".106* <p>107* In Beans 1.0 the given name can indicate either a serialized object108* or a class. Other mechanisms may be added in the future. In109* beans 1.0 we first try to treat the beanName as a serialized object110* name then as a class name.111* <p>112* When using the beanName as a serialized object name we convert the113* given beanName to a resource pathname and add a trailing ".ser" suffix.114* We then try to load a serialized object from that resource.115* <p>116* For example, given a beanName of "x.y", Beans.instantiate would first117* try to read a serialized object from the resource "x/y.ser" and if118* that failed it would try to load the class "x.y" and create an119* instance of that class.120* <p>121* If the bean is a subtype of java.applet.Applet, then it is given122* some special initialization. First, it is supplied with a default123* AppletStub and AppletContext. Second, if it was instantiated from124* a classname the applet's "init" method is called. (If the bean was125* deserialized this step is skipped.)126* <p>127* Note that for beans which are applets, it is the caller's responsiblity128* to call "start" on the applet. For correct behaviour, this should be done129* after the applet has been added into a visible AWT container.130* <p>131* Note that applets created via beans.instantiate run in a slightly132* different environment than applets running inside browsers. In133* particular, bean applets have no access to "parameters", so they may134* wish to provide property get/set methods to set parameter values. We135* advise bean-applet developers to test their bean-applets against both136* the JDK appletviewer (for a reference browser environment) and the137* BDK BeanBox (for a reference bean container).138*139* @return a JavaBean140* @param cls the class-loader from which we should create141* the bean. If this is null, then the system142* class-loader is used.143* @param beanName the name of the bean within the class-loader.144* For example "sun.beanbox.foobah"145* @param beanContext The BeanContext in which to nest the new bean146* @param initializer The AppletInitializer for the new bean147*148* @exception ClassNotFoundException if the class of a serialized149* object could not be found.150* @exception IOException if an I/O error occurs.151*/152153public static Object instantiate(ClassLoader cls, String beanName, BeanContext beanContext, AppletInitializer initializer)154throws IOException, ClassNotFoundException {155156InputStream ins;157ObjectInputStream oins = null;158Object result = null;159boolean serialized = false;160IOException serex = null;161162// If the given classloader is null, we check if an163// system classloader is available and (if so)164// use that instead.165// Note that calls on the system class loader will166// look in the bootstrap class loader first.167if (cls == null) {168try {169cls = ClassLoader.getSystemClassLoader();170} catch (SecurityException ex) {171// We're not allowed to access the system class loader.172// Drop through.173}174}175176// Try to find a serialized object with this name177final String serName = beanName.replace('.','/').concat(".ser");178if (cls == null)179ins = ClassLoader.getSystemResourceAsStream(serName);180else181ins = cls.getResourceAsStream(serName);182if (ins != null) {183try {184if (cls == null) {185oins = new ObjectInputStream(ins);186} else {187oins = new ObjectInputStreamWithLoader(ins, cls);188}189result = oins.readObject();190serialized = true;191oins.close();192} catch (IOException ex) {193ins.close();194// Drop through and try opening the class. But remember195// the exception in case we can't find the class either.196serex = ex;197} catch (ClassNotFoundException ex) {198ins.close();199throw ex;200}201}202203if (result == null) {204// No serialized object, try just instantiating the class205Class<?> cl;206207try {208cl = ClassFinder.findClass(beanName, cls);209} catch (ClassNotFoundException ex) {210// There is no appropriate class. If we earlier tried to211// deserialize an object and got an IO exception, throw that,212// otherwise rethrow the ClassNotFoundException.213if (serex != null) {214throw serex;215}216throw ex;217}218219if (!Modifier.isPublic(cl.getModifiers())) {220throw new ClassNotFoundException("" + cl + " : no public access");221}222223/*224* Try to instantiate the class.225*/226227try {228result = cl.newInstance();229} catch (Exception ex) {230// We have to remap the exception to one in our signature.231// But we pass extra information in the detail message.232throw new ClassNotFoundException("" + cl + " : " + ex, ex);233}234}235236if (result != null) {237238// Ok, if the result is an applet initialize it.239240AppletStub stub = null;241242if (result instanceof Applet) {243Applet applet = (Applet) result;244boolean needDummies = initializer == null;245246if (needDummies) {247248// Figure our the codebase and docbase URLs. We do this249// by locating the URL for a known resource, and then250// massaging the URL.251252// First find the "resource name" corresponding to the bean253// itself. So a serialzied bean "a.b.c" would imply a254// resource name of "a/b/c.ser" and a classname of "x.y"255// would imply a resource name of "x/y.class".256257final String resourceName;258259if (serialized) {260// Serialized bean261resourceName = beanName.replace('.','/').concat(".ser");262} else {263// Regular class264resourceName = beanName.replace('.','/').concat(".class");265}266267URL objectUrl = null;268URL codeBase = null;269URL docBase = null;270271// Now get the URL correponding to the resource name.272if (cls == null) {273objectUrl = ClassLoader.getSystemResource(resourceName);274} else275objectUrl = cls.getResource(resourceName);276277// If we found a URL, we try to locate the docbase by taking278// of the final path name component, and the code base by taking279// of the complete resourceName.280// So if we had a resourceName of "a/b/c.class" and we got an281// objectURL of "file://bert/classes/a/b/c.class" then we would282// want to set the codebase to "file://bert/classes/" and the283// docbase to "file://bert/classes/a/b/"284285if (objectUrl != null) {286String s = objectUrl.toExternalForm();287288if (s.endsWith(resourceName)) {289int ix = s.length() - resourceName.length();290codeBase = new URL(s.substring(0,ix));291docBase = codeBase;292293ix = s.lastIndexOf('/');294295if (ix >= 0) {296docBase = new URL(s.substring(0,ix+1));297}298}299}300301// Setup a default context and stub.302BeansAppletContext context = new BeansAppletContext(applet);303304stub = (AppletStub)new BeansAppletStub(applet, context, codeBase, docBase);305applet.setStub(stub);306} else {307initializer.initialize(applet, beanContext);308}309310// now, if there is a BeanContext, add the bean, if applicable.311312if (beanContext != null) {313unsafeBeanContextAdd(beanContext, result);314}315316// If it was deserialized then it was already init-ed.317// Otherwise we need to initialize it.318319if (!serialized) {320// We need to set a reasonable initial size, as many321// applets are unhappy if they are started without322// having been explicitly sized.323applet.setSize(100,100);324applet.init();325}326327if (needDummies) {328((BeansAppletStub)stub).active = true;329} else initializer.activate(applet);330331} else if (beanContext != null) unsafeBeanContextAdd(beanContext, result);332}333334return result;335}336337@SuppressWarnings("unchecked")338private static void unsafeBeanContextAdd(BeanContext beanContext, Object res) {339beanContext.add(res);340}341342/**343* From a given bean, obtain an object representing a specified344* type view of that source object.345* <p>346* The result may be the same object or a different object. If347* the requested target view isn't available then the given348* bean is returned.349* <p>350* This method is provided in Beans 1.0 as a hook to allow the351* addition of more flexible bean behaviour in the future.352*353* @return an object representing a specified type view of the354* source object355* @param bean Object from which we want to obtain a view.356* @param targetType The type of view we'd like to get.357*358*/359public static Object getInstanceOf(Object bean, Class<?> targetType) {360return bean;361}362363/**364* Check if a bean can be viewed as a given target type.365* The result will be true if the Beans.getInstanceof method366* can be used on the given bean to obtain an object that367* represents the specified targetType type view.368*369* @param bean Bean from which we want to obtain a view.370* @param targetType The type of view we'd like to get.371* @return "true" if the given bean supports the given targetType.372*373*/374public static boolean isInstanceOf(Object bean, Class<?> targetType) {375return Introspector.isSubclass(bean.getClass(), targetType);376}377378/**379* Test if we are in design-mode.380*381* @return True if we are running in an application construction382* environment.383*384* @see DesignMode385*/386public static boolean isDesignTime() {387return ThreadGroupContext.getContext().isDesignTime();388}389390/**391* Determines whether beans can assume a GUI is available.392*393* @return True if we are running in an environment where beans394* can assume that an interactive GUI is available, so they395* can pop up dialog boxes, etc. This will normally return396* true in a windowing environment, and will normally return397* false in a server environment or if an application is398* running as part of a batch job.399*400* @see Visibility401*402*/403public static boolean isGuiAvailable() {404return ThreadGroupContext.getContext().isGuiAvailable();405}406407/**408* Used to indicate whether of not we are running in an application409* builder environment.410*411* <p>Note that this method is security checked412* and is not available to (for example) untrusted applets.413* More specifically, if there is a security manager,414* its <code>checkPropertiesAccess</code>415* method is called. This could result in a SecurityException.416*417* @param isDesignTime True if we're in an application builder tool.418* @exception SecurityException if a security manager exists and its419* <code>checkPropertiesAccess</code> method doesn't allow setting420* of system properties.421* @see SecurityManager#checkPropertiesAccess422*/423424public static void setDesignTime(boolean isDesignTime)425throws SecurityException {426SecurityManager sm = System.getSecurityManager();427if (sm != null) {428sm.checkPropertiesAccess();429}430ThreadGroupContext.getContext().setDesignTime(isDesignTime);431}432433/**434* Used to indicate whether of not we are running in an environment435* where GUI interaction is available.436*437* <p>Note that this method is security checked438* and is not available to (for example) untrusted applets.439* More specifically, if there is a security manager,440* its <code>checkPropertiesAccess</code>441* method is called. This could result in a SecurityException.442*443* @param isGuiAvailable True if GUI interaction is available.444* @exception SecurityException if a security manager exists and its445* <code>checkPropertiesAccess</code> method doesn't allow setting446* of system properties.447* @see SecurityManager#checkPropertiesAccess448*/449450public static void setGuiAvailable(boolean isGuiAvailable)451throws SecurityException {452SecurityManager sm = System.getSecurityManager();453if (sm != null) {454sm.checkPropertiesAccess();455}456ThreadGroupContext.getContext().setGuiAvailable(isGuiAvailable);457}458}459460/**461* This subclass of ObjectInputStream delegates loading of classes to462* an existing ClassLoader.463*/464465class ObjectInputStreamWithLoader extends ObjectInputStream466{467private ClassLoader loader;468469/**470* Loader must be non-null;471*/472473public ObjectInputStreamWithLoader(InputStream in, ClassLoader loader)474throws IOException, StreamCorruptedException {475476super(in);477if (loader == null) {478throw new IllegalArgumentException("Illegal null argument to ObjectInputStreamWithLoader");479}480this.loader = loader;481}482483/**484* Use the given ClassLoader rather than using the system class485*/486@SuppressWarnings("rawtypes")487protected Class resolveClass(ObjectStreamClass classDesc)488throws IOException, ClassNotFoundException {489490String cname = classDesc.getName();491return ClassFinder.resolveClass(cname, this.loader);492}493}494495/**496* Package private support class. This provides a default AppletContext497* for beans which are applets.498*/499500class BeansAppletContext implements AppletContext {501Applet target;502Hashtable<URL,Object> imageCache = new Hashtable<>();503504BeansAppletContext(Applet target) {505this.target = target;506}507508public AudioClip getAudioClip(URL url) {509// We don't currently support audio clips in the Beans.instantiate510// applet context, unless by some luck there exists a URL content511// class that can generate an AudioClip from the audio URL.512try {513return (AudioClip) url.getContent();514} catch (Exception ex) {515return null;516}517}518519public synchronized Image getImage(URL url) {520Object o = imageCache.get(url);521if (o != null) {522return (Image)o;523}524try {525o = url.getContent();526if (o == null) {527return null;528}529if (o instanceof Image) {530imageCache.put(url, o);531return (Image) o;532}533// Otherwise it must be an ImageProducer.534Image img = target.createImage((java.awt.image.ImageProducer)o);535imageCache.put(url, img);536return img;537538} catch (Exception ex) {539return null;540}541}542543public Applet getApplet(String name) {544return null;545}546547public Enumeration<Applet> getApplets() {548Vector<Applet> applets = new Vector<>();549applets.addElement(target);550return applets.elements();551}552553public void showDocument(URL url) {554// We do nothing.555}556557public void showDocument(URL url, String target) {558// We do nothing.559}560561public void showStatus(String status) {562// We do nothing.563}564565public void setStream(String key, InputStream stream)throws IOException{566// We do nothing.567}568569public InputStream getStream(String key){570// We do nothing.571return null;572}573574public Iterator<String> getStreamKeys(){575// We do nothing.576return null;577}578}579580/**581* Package private support class. This provides an AppletStub582* for beans which are applets.583*/584class BeansAppletStub implements AppletStub {585transient boolean active;586transient Applet target;587transient AppletContext context;588transient URL codeBase;589transient URL docBase;590591BeansAppletStub(Applet target,592AppletContext context, URL codeBase,593URL docBase) {594this.target = target;595this.context = context;596this.codeBase = codeBase;597this.docBase = docBase;598}599600public boolean isActive() {601return active;602}603604public URL getDocumentBase() {605// use the root directory of the applet's class-loader606return docBase;607}608609public URL getCodeBase() {610// use the directory where we found the class or serialized object.611return codeBase;612}613614public String getParameter(String name) {615return null;616}617618public AppletContext getAppletContext() {619return context;620}621622public void appletResize(int width, int height) {623// we do nothing.624}625}626627628