001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017:
018: package java.beans;
019:
020: import java.applet.Applet;
021: import java.applet.AppletContext;
022: import java.applet.AppletStub;
023: import java.applet.AudioClip;
024: import java.awt.Image;
025: import java.beans.beancontext.BeanContext;
026: import java.io.IOException;
027: import java.io.InputStream;
028: import java.io.ObjectInputStream;
029: import java.net.MalformedURLException;
030: import java.net.URL;
031: import java.security.AccessController;
032: import java.security.PrivilegedAction;
033: import java.util.Enumeration;
034: import java.util.Iterator;
035: import java.util.Vector;
036:
037: import org.apache.harmony.beans.internal.nls.Messages;
038:
039: /**
040: * This class <code>Beans</code> provides some methods for manipulting bean
041: * controls.
042: *
043: */
044:
045: public class Beans {
046:
047: private static boolean designTime = false;
048:
049: private static boolean guiAvailable = true;
050:
051: /**
052: * Constructs a Beans instance.
053: */
054: public Beans() {
055: // expected
056: }
057:
058: /**
059: * Obtains an instance of a JavaBean specified the bean name using the
060: * specified class loader.
061: * <p>
062: * If the specified class loader is null, the system class loader is used.
063: * </p>
064: *
065: * @param loader
066: * the specified class loader. It can be null.
067: * @param name
068: * the name of the JavaBean
069: * @return an isntance of the bean.
070: * @throws IOException
071: * @throws ClassNotFoundException
072: */
073: public static Object instantiate(ClassLoader loader, String name)
074: throws IOException, ClassNotFoundException {
075: return instantiate(loader, name, null, null);
076: }
077:
078: /**
079: * Obtains an instance of a JavaBean specified the bean name using the
080: * specified class loader, and adds the instance into the specified bean
081: * context.
082: *
083: * <p>
084: * If the specified class loader is null, the system class loader is used.
085: * </p>
086: *
087: * @param cls
088: * the specified class loader. It can be null.
089: * @param beanName
090: * the name of the JavaBean
091: * @param beanContext
092: * the beancontext in which the bean instance will be added.
093: * @return an instance of the specified JavaBean.
094: * @throws IOException
095: * @throws ClassNotFoundException
096: */
097: public static Object instantiate(ClassLoader cls, String beanName,
098: BeanContext beanContext) throws IOException,
099: ClassNotFoundException {
100: return instantiate(cls, beanName, beanContext, null);
101:
102: }
103:
104: /**
105: * Obtains an instance of a JavaBean specified by the bean name using the
106: * specified class loader, and adds the instance into the specified bean
107: * context.
108: * <p>
109: * The parameter name must be a qualified name relative to the specified
110: * class loader. For example, "java.awt.Button" and "x.y.z".
111: * </p>
112: * <p>
113: * If the specified class loader is null, the system class loader is used.
114: * </p>
115: * <p>
116: * Firstly, The class <code>Beans</code> regards the bean name as a
117: * serialized object name. The class <code>Beans</code> convert bean name
118: * into pathname, append a suffix ".ser" to the pathname. then try to load
119: * the resource using the specified class loader. If <code>Beans</code>
120: * fails to load the resource, <code>Beans</code> will regard the
121: * <code>name</code> as a class name and construct a new instance of the
122: * bean class.
123: * </p>
124: * <p>
125: * For example, if the name is specified as "x.y.z", The class
126: * <code>Beans</code> will try to load the serialized object from the
127: * resource "x/y/z.ser"; If <code>Beans</code> fails to load the resource
128: * "x/y/z.ser", it will create a new instance of "x.y.z".
129: * </p>
130: * <p>
131: * If the bean is an instance of java.applet.Applet, <code>Beans</code>
132: * will do some special initialization for this applet bean. First,
133: * <code>Beans</code> will set the default AppletStub and AppletContext
134: * for the applet bean (If the specified <code>AppletInitializer</code> is
135: * not null, <code>Beans</code> will call the
136: * <code>AppletInitializer.initialize</code> to set the default AppletStub
137: * and AppletContext for the applet bean). Second, <code>Beans</code> will
138: * call the <code>init</code> method of the applet. (If the applet bean is
139: * loaded as a serialized object, the <code>init</code> method will not be
140: * called.)
141: * </p>
142: *
143: * @param cls
144: * the specified class loader. It can be null.
145: * @param beanName
146: * the name of the JavaBean
147: * @param context
148: * the beancontext in which the bean instance will be added.
149: * @param initializer
150: * the AppletInitializer for applet bean instance.
151: * @return Obtains an instance of the JavaBean.
152: * @throws IOException
153: * @throws ClassNotFoundException
154: */
155: @SuppressWarnings("unchecked")
156: public static Object instantiate(ClassLoader cls, String beanName,
157: BeanContext context, AppletInitializer initializer)
158: throws IOException, ClassNotFoundException {
159: Object result = null;
160:
161: boolean deserialized = true;
162:
163: ClassLoader loader = null;
164:
165: // First try to load it from a serialization file.
166: String beanResourceName = getBeanResourceName(beanName);
167:
168: InputStream is = (cls == null) ? ClassLoader
169: .getSystemResourceAsStream(beanResourceName) : cls
170: .getResourceAsStream(beanResourceName);
171:
172: IOException serializationException = null;
173: if (is != null) {
174: try {
175: ObjectInputStream ois = (cls == null) ? new ObjectInputStream(
176: is)
177: : new CustomizedObjectInputStream(is, cls);
178: result = ois.readObject();
179: } catch (IOException exception) {
180: //Not loadable - remember this as we may throw it later.
181: serializationException = exception;
182: }
183: }
184:
185: //If that did not work, try to instantiate it from the given classloader.
186: if (result == null) {
187: deserialized = false;
188: try {
189: loader = cls == null ? ClassLoader
190: .getSystemClassLoader() : cls;
191: Class<?> c = Class.forName(beanName, true, loader);
192: result = c.newInstance();
193: } catch (Exception e) {
194: if (serializationException != null) {
195: throw serializationException;
196: }
197: throw new ClassNotFoundException(e.getClass() + ": " //$NON-NLS-1$
198: + e.getMessage());
199: }
200: }
201:
202: if (result != null) {
203: // Applet specific initialization
204: if (result instanceof Applet) {
205: appletLoaded((Applet) result, loader, beanName,
206: context, initializer, deserialized);
207: }
208: if (null != context) {
209: context.add(result);
210: }
211: }
212: return result;
213: }
214:
215: /**
216: * Obtain an alternative type view of the given bean. The view type is
217: * specified by the parameter <code>type</code>.
218: * <p>
219: * If the type view cannot be obtained, the original bean object is
220: * returned.
221: * </p>
222: *
223: * @param bean
224: * the original bean object.
225: * @param targetType
226: * the specified view type.
227: * @return a type view of the given bean.
228: */
229: @SuppressWarnings("unused")
230: public static Object getInstanceOf(Object bean, Class<?> targetType) {
231: return bean;
232: }
233:
234: /**
235: * Determine if the the specified bean object can be viewed as the specified
236: * type.
237: *
238: * @param bean
239: * the specified bean object.
240: * @param targetType
241: * the specifed view type.
242: * @return true if the specified bean object can be viewed as the specified
243: * type; otherwise, return false;
244: */
245: public static boolean isInstanceOf(Object bean, Class<?> targetType) {
246: if (bean == null) {
247: throw new NullPointerException(Messages
248: .getString("beans.1D")); //$NON-NLS-1$
249: }
250:
251: return targetType == null ? false : targetType.isInstance(bean);
252: }
253:
254: /**
255: * Set whether or not a GUI is available in the bean's current environment.
256: *
257: * @param isGuiAvailable
258: * should be <code>true</code> to signify that a GUI is
259: * available, <code>false</code> otherwise.
260: * @throws SecurityException
261: * if the caller does not have the required permission to access
262: * or modify system properties.
263: */
264: public static synchronized void setGuiAvailable(
265: boolean isGuiAvailable) throws SecurityException {
266: checkPropertiesAccess();
267: guiAvailable = isGuiAvailable;
268: }
269:
270: /**
271: * Used to indicate whether of not it's in an application construction
272: * environment.
273: *
274: * @param isDesignTime
275: * true to indicate that it's in application construction
276: * environment.
277: * @throws SecurityException
278: */
279: public static void setDesignTime(boolean isDesignTime)
280: throws SecurityException {
281: checkPropertiesAccess();
282: synchronized (Beans.class) {
283: designTime = isDesignTime;
284: }
285: }
286:
287: /**
288: * Returns a boolean indication of whether or not a GUI is available for
289: * beans.
290: *
291: * @return <code>true</code> if a GUI is available, otherwise
292: * <code>false</code>.
293: */
294: public static synchronized boolean isGuiAvailable() {
295: return guiAvailable;
296: }
297:
298: /**
299: * Determine if it's in design-mode.
300: *
301: * @return true if it's in an application construction environment.
302: */
303: public static synchronized boolean isDesignTime() {
304: return designTime;
305: }
306:
307: private static void checkPropertiesAccess()
308: throws SecurityException {
309: SecurityManager sm = System.getSecurityManager();
310:
311: if (sm != null) {
312: sm.checkPropertiesAccess();
313: }
314: }
315:
316: private static String getBeanResourceName(String beanName) {
317: return beanName.replace('.', '/') + ".ser"; //$NON-NLS-1$
318: }
319:
320: private static void appletLoaded(Applet applet, ClassLoader loader,
321: String name, BeanContext context,
322: AppletInitializer initializer, boolean deserialized)
323: throws ClassNotFoundException {
324:
325: // If there is an initializer
326: if (initializer != null) {
327: initializer.initialize(applet, context);
328: } else {
329: setStub(applet, loader, deserialized, name);
330: }
331:
332: if (!deserialized) {
333: applet.init();
334: }
335:
336: if (initializer != null) {
337: initializer.activate(applet);
338: }
339: }
340:
341: private static void setStub(Applet applet,
342: final ClassLoader loader, boolean serialized,
343: String beanName) throws ClassNotFoundException {
344: // Get path to the resource representing the applet.
345: String pathName = beanName.replace('.', '/');
346: final String resourceName = serialized ? pathName
347: .concat(".ser") : pathName.concat(".class"); //$NON-NLS-1$ //$NON-NLS-2$
348: URL objectUrl = AccessController
349: .doPrivileged(new PrivilegedAction<URL>() {
350: public URL run() {
351: if (loader == null)
352: return ClassLoader
353: .getSystemResource(resourceName);
354: return loader.getResource(resourceName);
355: }
356: });
357:
358: // If we can't get to the applet itself, the codebase and doc base are
359: // left as null.
360: if (objectUrl == null) {
361: applet.setStub(getAppletStub(getStubAppletContext(applet),
362: null, null));
363: return;
364: }
365:
366: // Try to decompose the resource URL to get to the doc/code URL
367: String urlString = objectUrl.toExternalForm();
368:
369: // This is the URL of the directory that contains the applet.
370: int codeURLlength = urlString.length() - resourceName.length();
371: URL codeBase = safeURL(urlString.substring(0, codeURLlength));
372:
373: // URL of the document containing the applet.
374: int docURLlength = urlString.lastIndexOf('/');
375: URL docBase = safeURL(urlString.substring(0, docURLlength + 1));
376:
377: applet.setStub(getAppletStub(getStubAppletContext(applet),
378: codeBase, docBase));
379: }
380:
381: private static AppletStub getAppletStub(
382: final AppletContext context, final URL codeBase,
383: final URL docBase) {
384:
385: return new AppletStub() {
386: public boolean isActive() {
387: return true;
388: }
389:
390: public URL getDocumentBase() {
391: return docBase;
392: }
393:
394: public URL getCodeBase() {
395: return codeBase;
396: }
397:
398: public String getParameter(String name) {
399: // Applet beans have no params.
400: return null;
401: }
402:
403: public AppletContext getAppletContext() {
404: return context;
405: }
406:
407: public void appletResize(int width, int height) {
408: // Do nothing.
409: }
410: };
411: }
412:
413: private static AppletContext getStubAppletContext(
414: final Applet target) {
415: return new AppletContext() {
416: public AudioClip getAudioClip(URL url) {
417: return null;
418: }
419:
420: public synchronized Image getImage(URL url) {
421: return null;
422: }
423:
424: public Applet getApplet(String name) {
425: return null;
426: }
427:
428: public Enumeration<Applet> getApplets() {
429: Vector<Applet> applets = new Vector<Applet>();
430: applets.addElement(target);
431: return applets.elements();
432: }
433:
434: public void showDocument(URL url) {
435: // Do nothing.
436: }
437:
438: public void showDocument(URL url, String aTarget) {
439: // Do nothing.
440: }
441:
442: public void showStatus(String status) {
443: // Do nothing.
444: }
445:
446: public void setStream(String key, InputStream stream)
447: throws IOException {
448: // Do nothing.
449: }
450:
451: public InputStream getStream(String key) {
452: return null;
453: }
454:
455: public Iterator<String> getStreamKeys() {
456: return null;
457: }
458: };
459: }
460:
461: // Maps malformed URL exception to ClassNotFoundException
462: private static URL safeURL(String urlString)
463: throws ClassNotFoundException {
464: try {
465: return new URL(urlString);
466: } catch (MalformedURLException exception) {
467: throw new ClassNotFoundException(exception.getMessage());
468: }
469: }
470:
471: }
|