Separatelly compiling Beans and Applet modules. Using 'code injection' to allow Beans class to perform its Applet related functionality if Applet module is around.
2 * Copyright 1996-2009 Sun Microsystems, Inc. All Rights Reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
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.
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).
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.
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
28 import com.sun.beans.finder.ClassFinder;
30 import java.awt.GraphicsEnvironment;
32 import java.beans.beancontext.BeanContext;
34 import java.io.IOException;
35 import java.io.InputStream;
36 import java.io.ObjectInputStream;
37 import java.io.ObjectStreamClass;
38 import java.io.StreamCorruptedException;
41 import java.security.AccessController;
42 import java.security.PrivilegedAction;
44 import java.util.Iterator;
45 import java.util.ServiceLoader;
47 import sun.awt.AppContext;
48 import sun.beans.AppletProxy;
51 * This class provides some general purpose beans control methods.
55 private static final Object DESIGN_TIME = new Object();
56 private static final Object GUI_AVAILABLE = new Object();
60 * Instantiate a JavaBean.
63 * @param cls the class-loader from which we should create
64 * the bean. If this is null, then the system
65 * class-loader is used.
66 * @param beanName the name of the bean within the class-loader.
67 * For example "sun.beanbox.foobah"
69 * @exception ClassNotFoundException if the class of a serialized
70 * object could not be found.
71 * @exception IOException if an I/O error occurs.
74 public static Object instantiate(ClassLoader cls, String beanName) throws IOException, ClassNotFoundException {
75 return Beans.instantiate(cls, beanName, null, null);
80 * Instantiate a JavaBean.
83 * @param cls the class-loader from which we should create
84 * the bean. If this is null, then the system
85 * class-loader is used.
86 * @param beanName the name of the bean within the class-loader.
87 * For example "sun.beanbox.foobah"
88 * @param beanContext The BeanContext in which to nest the new bean
90 * @exception ClassNotFoundException if the class of a serialized
91 * object could not be found.
92 * @exception IOException if an I/O error occurs.
95 public static Object instantiate(ClassLoader cls, String beanName, BeanContext beanContext) throws IOException, ClassNotFoundException {
96 return Beans.instantiate(cls, beanName, beanContext, null);
100 * Instantiate a bean.
102 * The bean is created based on a name relative to a class-loader.
103 * This name should be a dot-separated name such as "a.b.c".
105 * In Beans 1.0 the given name can indicate either a serialized object
106 * or a class. Other mechanisms may be added in the future. In
107 * beans 1.0 we first try to treat the beanName as a serialized object
108 * name then as a class name.
110 * When using the beanName as a serialized object name we convert the
111 * given beanName to a resource pathname and add a trailing ".ser" suffix.
112 * We then try to load a serialized object from that resource.
114 * For example, given a beanName of "x.y", Beans.instantiate would first
115 * try to read a serialized object from the resource "x/y.ser" and if
116 * that failed it would try to load the class "x.y" and create an
117 * instance of that class.
119 * If the bean is a subtype of java.applet.Applet, then it is given
120 * some special initialization. First, it is supplied with a default
121 * AppletStub and AppletContext. Second, if it was instantiated from
122 * a classname the applet's "init" method is called. (If the bean was
123 * deserialized this step is skipped.)
125 * Note that for beans which are applets, it is the caller's responsiblity
126 * to call "start" on the applet. For correct behaviour, this should be done
127 * after the applet has been added into a visible AWT container.
129 * Note that applets created via beans.instantiate run in a slightly
130 * different environment than applets running inside browsers. In
131 * particular, bean applets have no access to "parameters", so they may
132 * wish to provide property get/set methods to set parameter values. We
133 * advise bean-applet developers to test their bean-applets against both
134 * the JDK appletviewer (for a reference browser environment) and the
135 * BDK BeanBox (for a reference bean container).
137 * @param cls the class-loader from which we should create
138 * the bean. If this is null, then the system
139 * class-loader is used.
140 * @param beanName the name of the bean within the class-loader.
141 * For example "sun.beanbox.foobah"
142 * @param beanContext The BeanContext in which to nest the new bean
143 * @param initializer The AppletInitializer for the new bean
145 * @exception ClassNotFoundException if the class of a serialized
146 * object could not be found.
147 * @exception IOException if an I/O error occurs.
150 public static Object instantiate(ClassLoader cls, String beanName, BeanContext beanContext,
151 /** TBD: Oops , this is bad. The AppletInitializer is used from
152 * public API. I have not noticed that sooner. Opps.
153 AppletInitializer initializer
154 * meanwhile turning into object, but this cannot be final solution:
157 ) throws IOException, ClassNotFoundException {
160 ObjectInputStream oins = null;
161 Object result = null;
162 boolean serialized = false;
163 IOException serex = null;
165 // If the given classloader is null, we check if an
166 // system classloader is available and (if so)
168 // Note that calls on the system class loader will
169 // look in the bootstrap class loader first.
172 cls = ClassLoader.getSystemClassLoader();
173 } catch (SecurityException ex) {
174 // We're not allowed to access the system class loader.
179 // Try to find a serialized object with this name
180 final String serName = beanName.replace('.','/').concat(".ser");
181 final ClassLoader loader = cls;
182 ins = (InputStream)AccessController.doPrivileged
183 (new PrivilegedAction() {
184 public Object run() {
186 return ClassLoader.getSystemResourceAsStream(serName);
188 return loader.getResourceAsStream(serName);
194 oins = new ObjectInputStream(ins);
196 oins = new ObjectInputStreamWithLoader(ins, cls);
198 result = oins.readObject();
201 } catch (IOException ex) {
203 // Drop through and try opening the class. But remember
204 // the exception in case we can't find the class either.
206 } catch (ClassNotFoundException ex) {
212 if (result == null) {
213 // No serialized object, try just instantiating the class
217 cl = ClassFinder.findClass(beanName, cls);
218 } catch (ClassNotFoundException ex) {
219 // There is no appropriate class. If we earlier tried to
220 // deserialize an object and got an IO exception, throw that,
221 // otherwise rethrow the ClassNotFoundException.
229 * Try to instantiate the class.
233 result = cl.newInstance();
234 } catch (Exception ex) {
235 // We have to remap the exception to one in our signature.
236 // But we pass extra information in the detail message.
237 throw new ClassNotFoundException("" + cl + " : " + ex, ex);
241 if (result != null) {
243 // Ok, if the result is an applet initialize it.
244 Iterator<AppletProxy> it = ServiceLoader.load(AppletProxy.class).iterator();
245 AppletProxy ap = it.hasNext() ? it.next() : null;
246 if (ap != null || !ap.initialize(
247 result, initializer, serialized, beanName, beanContext, cls
249 if (beanContext != null) beanContext.add(result);
258 * From a given bean, obtain an object representing a specified
259 * type view of that source object.
261 * The result may be the same object or a different object. If
262 * the requested target view isn't available then the given
265 * This method is provided in Beans 1.0 as a hook to allow the
266 * addition of more flexible bean behaviour in the future.
268 * @param bean Object from which we want to obtain a view.
269 * @param targetType The type of view we'd like to get.
272 public static Object getInstanceOf(Object bean, Class<?> targetType) {
277 * Check if a bean can be viewed as a given target type.
278 * The result will be true if the Beans.getInstanceof method
279 * can be used on the given bean to obtain an object that
280 * represents the specified targetType type view.
282 * @param bean Bean from which we want to obtain a view.
283 * @param targetType The type of view we'd like to get.
284 * @return "true" if the given bean supports the given targetType.
287 public static boolean isInstanceOf(Object bean, Class<?> targetType) {
288 return Introspector.isSubclass(bean.getClass(), targetType);
293 * Test if we are in design-mode.
295 * @return True if we are running in an application construction
300 public static boolean isDesignTime() {
301 Object value = AppContext.getAppContext().get(DESIGN_TIME);
302 return (value instanceof Boolean) && (Boolean) value;
306 * Determines whether beans can assume a GUI is available.
308 * @return True if we are running in an environment where beans
309 * can assume that an interactive GUI is available, so they
310 * can pop up dialog boxes, etc. This will normally return
311 * true in a windowing environment, and will normally return
312 * false in a server environment or if an application is
313 * running as part of a batch job.
318 public static boolean isGuiAvailable() {
319 Object value = AppContext.getAppContext().get(GUI_AVAILABLE);
320 return (value instanceof Boolean) ? (Boolean) value : !GraphicsEnvironment.isHeadless();
324 * Used to indicate whether of not we are running in an application
325 * builder environment.
327 * <p>Note that this method is security checked
328 * and is not available to (for example) untrusted applets.
329 * More specifically, if there is a security manager,
330 * its <code>checkPropertiesAccess</code>
331 * method is called. This could result in a SecurityException.
333 * @param isDesignTime True if we're in an application builder tool.
334 * @exception SecurityException if a security manager exists and its
335 * <code>checkPropertiesAccess</code> method doesn't allow setting
336 * of system properties.
337 * @see SecurityManager#checkPropertiesAccess
340 public static void setDesignTime(boolean isDesignTime)
341 throws SecurityException {
342 SecurityManager sm = System.getSecurityManager();
344 sm.checkPropertiesAccess();
346 AppContext.getAppContext().put(DESIGN_TIME, Boolean.valueOf(isDesignTime));
350 * Used to indicate whether of not we are running in an environment
351 * where GUI interaction is available.
353 * <p>Note that this method is security checked
354 * and is not available to (for example) untrusted applets.
355 * More specifically, if there is a security manager,
356 * its <code>checkPropertiesAccess</code>
357 * method is called. This could result in a SecurityException.
359 * @param isGuiAvailable True if GUI interaction is available.
360 * @exception SecurityException if a security manager exists and its
361 * <code>checkPropertiesAccess</code> method doesn't allow setting
362 * of system properties.
363 * @see SecurityManager#checkPropertiesAccess
366 public static void setGuiAvailable(boolean isGuiAvailable)
367 throws SecurityException {
368 SecurityManager sm = System.getSecurityManager();
370 sm.checkPropertiesAccess();
372 AppContext.getAppContext().put(GUI_AVAILABLE, Boolean.valueOf(isGuiAvailable));
377 * This subclass of ObjectInputStream delegates loading of classes to
378 * an existing ClassLoader.
381 class ObjectInputStreamWithLoader extends ObjectInputStream
383 private ClassLoader loader;
386 * Loader must be non-null;
389 public ObjectInputStreamWithLoader(InputStream in, ClassLoader loader)
390 throws IOException, StreamCorruptedException {
393 if (loader == null) {
394 throw new IllegalArgumentException("Illegal null argument to ObjectInputStreamWithLoader");
396 this.loader = loader;
400 * Use the given ClassLoader rather than using the system class
402 protected Class resolveClass(ObjectStreamClass classDesc)
403 throws IOException, ClassNotFoundException {
405 String cname = classDesc.getName();
406 return ClassFinder.resolveClass(cname, this.loader);