KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > java > beans > Beans


1 /*
2  * @(#)Beans.java 1.63 04/06/28
3  *
4  * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
5  * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
6  */

7
8 package java.beans;
9
10 import java.applet.*;
11
12 import java.awt.*;
13
14 import java.beans.AppletInitializer JavaDoc;
15
16 import java.beans.beancontext.BeanContext JavaDoc;
17
18 import java.io.*;
19
20 import java.lang.reflect.Constructor JavaDoc;
21
22 import java.net.URL JavaDoc;
23 import java.lang.reflect.Array JavaDoc;
24
25 /**
26  * This class provides some general purpose beans control methods.
27  */

28
29 public class Beans {
30
31     /**
32      * <p>
33      * Instantiate a JavaBean.
34      * </p>
35      *
36      * @param cls the class-loader from which we should create
37      * the bean. If this is null, then the system
38      * class-loader is used.
39      * @param beanName the name of the bean within the class-loader.
40      * For example "sun.beanbox.foobah"
41      *
42      * @exception java.lang.ClassNotFoundException if the class of a serialized
43      * object could not be found.
44      * @exception java.io.IOException if an I/O error occurs.
45      */

46
47     public static Object JavaDoc instantiate(ClassLoader JavaDoc cls, String JavaDoc beanName) throws java.io.IOException JavaDoc, ClassNotFoundException JavaDoc {
48     return Beans.instantiate(cls, beanName, null, null);
49     }
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      * @param beanContext The BeanContext in which to nest the new bean
62      *
63      * @exception java.lang.ClassNotFoundException if the class of a serialized
64      * object could not be found.
65      * @exception java.io.IOException if an I/O error occurs.
66      */

67
68     public static Object JavaDoc instantiate(ClassLoader JavaDoc cls, String JavaDoc beanName, BeanContext JavaDoc beanContext) throws java.io.IOException JavaDoc, ClassNotFoundException JavaDoc {
69     return Beans.instantiate(cls, beanName, beanContext, null);
70     }
71
72     /**
73      * Instantiate a bean.
74      * <p>
75      * The bean is created based on a name relative to a class-loader.
76      * This name should be a dot-separated name such as "a.b.c".
77      * <p>
78      * In Beans 1.0 the given name can indicate either a serialized object
79      * or a class. Other mechanisms may be added in the future. In
80      * beans 1.0 we first try to treat the beanName as a serialized object
81      * name then as a class name.
82      * <p>
83      * When using the beanName as a serialized object name we convert the
84      * given beanName to a resource pathname and add a trailing ".ser" suffix.
85      * We then try to load a serialized object from that resource.
86      * <p>
87      * For example, given a beanName of "x.y", Beans.instantiate would first
88      * try to read a serialized object from the resource "x/y.ser" and if
89      * that failed it would try to load the class "x.y" and create an
90      * instance of that class.
91      * <p>
92      * If the bean is a subtype of java.applet.Applet, then it is given
93      * some special initialization. First, it is supplied with a default
94      * AppletStub and AppletContext. Second, if it was instantiated from
95      * a classname the applet's "init" method is called. (If the bean was
96      * deserialized this step is skipped.)
97      * <p>
98      * Note that for beans which are applets, it is the caller's responsiblity
99      * to call "start" on the applet. For correct behaviour, this should be done
100      * after the applet has been added into a visible AWT container.
101      * <p>
102      * Note that applets created via beans.instantiate run in a slightly
103      * different environment than applets running inside browsers. In
104      * particular, bean applets have no access to "parameters", so they may
105      * wish to provide property get/set methods to set parameter values. We
106      * advise bean-applet developers to test their bean-applets against both
107      * the JDK appletviewer (for a reference browser environment) and the
108      * BDK BeanBox (for a reference bean container).
109      *
110      * @param cls the class-loader from which we should create
111      * the bean. If this is null, then the system
112      * class-loader is used.
113      * @param beanName the name of the bean within the class-loader.
114      * For example "sun.beanbox.foobah"
115      * @param beanContext The BeanContext in which to nest the new bean
116      * @param initializer The AppletInitializer for the new bean
117      *
118      * @exception java.lang.ClassNotFoundException if the class of a serialized
119      * object could not be found.
120      * @exception java.io.IOException if an I/O error occurs.
121      */

122
123     public static Object JavaDoc instantiate(ClassLoader JavaDoc cls, String JavaDoc beanName, BeanContext JavaDoc beanContext, AppletInitializer JavaDoc initializer)
124             throws java.io.IOException JavaDoc, ClassNotFoundException JavaDoc {
125
126     java.io.InputStream JavaDoc ins;
127     java.io.ObjectInputStream JavaDoc oins = null;
128     Object JavaDoc result = null;
129     boolean serialized = false;
130     java.io.IOException JavaDoc serex = null;
131
132     // If the given classloader is null, we check if an
133
// system classloader is available and (if so)
134
// use that instead.
135
// Note that calls on the system class loader will
136
// look in the bootstrap class loader first.
137
if (cls == null) {
138         try {
139             cls = ClassLoader.getSystemClassLoader();
140             } catch (SecurityException JavaDoc ex) {
141             // We're not allowed to access the system class loader.
142
// Drop through.
143
}
144     }
145
146     // Try to find a serialized object with this name
147
final String JavaDoc serName = beanName.replace('.','/').concat(".ser");
148     final ClassLoader JavaDoc loader = cls;
149     ins = (InputStream)java.security.AccessController.doPrivileged
150         (new java.security.PrivilegedAction JavaDoc() {
151         public Object JavaDoc run() {
152             if (loader == null)
153             return ClassLoader.getSystemResourceAsStream(serName);
154             else
155             return loader.getResourceAsStream(serName);
156         }
157     });
158     if (ins != null) {
159         try {
160             if (cls == null) {
161             oins = new ObjectInputStream(ins);
162             } else {
163             oins = new ObjectInputStreamWithLoader(ins, cls);
164             }
165             result = oins.readObject();
166         serialized = true;
167             oins.close();
168         } catch (java.io.IOException JavaDoc ex) {
169         ins.close();
170         // Drop through and try opening the class. But remember
171
// the exception in case we can't find the class either.
172
serex = ex;
173         } catch (ClassNotFoundException JavaDoc ex) {
174         ins.close();
175         throw ex;
176         }
177     }
178
179     if (result == null) {
180         // No serialized object, try just instantiating the class
181
Class JavaDoc cl;
182
183         try {
184             if (cls == null) {
185                 cl = Class.forName(beanName);
186             } else {
187                 cl = cls.loadClass(beanName);
188             }
189         } catch (ClassNotFoundException JavaDoc ex) {
190         // There is no appropriate class. If we earlier tried to
191
// deserialize an object and got an IO exception, throw that,
192
// otherwise rethrow the ClassNotFoundException.
193
if (serex != null) {
194             throw serex;
195         }
196         throw ex;
197         }
198
199         /*
200          * Try to instantiate the class.
201          */

202
203         try {
204             result = cl.newInstance();
205         } catch (Exception JavaDoc ex) {
206         // We have to remap the exception to one in our signature.
207
// But we pass extra information in the detail message.
208
throw new ClassNotFoundException JavaDoc("" + cl + " : " + ex, ex);
209         }
210     }
211
212     if (result != null) {
213
214         // Ok, if the result is an applet initialize it.
215

216         AppletStub stub = null;
217
218         if (result instanceof Applet) {
219             Applet applet = (Applet) result;
220         boolean needDummies = initializer == null;
221
222         if (needDummies) {
223
224                 // Figure our the codebase and docbase URLs. We do this
225
// by locating the URL for a known resource, and then
226
// massaging the URL.
227

228                 // First find the "resource name" corresponding to the bean
229
// itself. So a serialzied bean "a.b.c" would imply a
230
// resource name of "a/b/c.ser" and a classname of "x.y"
231
// would imply a resource name of "x/y.class".
232

233                 final String JavaDoc resourceName;
234
235                 if (serialized) {
236                 // Serialized bean
237
resourceName = beanName.replace('.','/').concat(".ser");
238                 } else {
239                 // Regular class
240
resourceName = beanName.replace('.','/').concat(".class");
241                 }
242
243                 URL JavaDoc objectUrl = null;
244                 URL JavaDoc codeBase = null;
245                 URL JavaDoc docBase = null;
246
247                 // Now get the URL correponding to the resource name.
248

249             final ClassLoader JavaDoc cloader = cls;
250             objectUrl = (URL JavaDoc)
251             java.security.AccessController.doPrivileged
252             (new java.security.PrivilegedAction JavaDoc() {
253                 public Object JavaDoc run() {
254                 if (cloader == null)
255                     return ClassLoader.getSystemResource
256                                 (resourceName);
257                 else
258                     return cloader.getResource(resourceName);
259                 }
260             });
261
262                 // If we found a URL, we try to locate the docbase by taking
263
// of the final path name component, and the code base by taking
264
// of the complete resourceName.
265
// So if we had a resourceName of "a/b/c.class" and we got an
266
// objectURL of "file://bert/classes/a/b/c.class" then we would
267
// want to set the codebase to "file://bert/classes/" and the
268
// docbase to "file://bert/classes/a/b/"
269

270                 if (objectUrl != null) {
271                 String JavaDoc s = objectUrl.toExternalForm();
272
273                 if (s.endsWith(resourceName)) {
274                     int ix = s.length() - resourceName.length();
275                     codeBase = new URL JavaDoc(s.substring(0,ix));
276                     docBase = codeBase;
277
278                     ix = s.lastIndexOf('/');
279
280                     if (ix >= 0) {
281                         docBase = new URL JavaDoc(s.substring(0,ix+1));
282                     }
283                 }
284                 }
285
286                 // Setup a default context and stub.
287
BeansAppletContext context = new BeansAppletContext(applet);
288
289                 stub = (AppletStub)new BeansAppletStub(applet, context, codeBase, docBase);
290                 applet.setStub(stub);
291         } else {
292             initializer.initialize(applet, beanContext);
293         }
294
295             // now, if there is a BeanContext, add the bean, if applicable.
296

297             if (beanContext != null) {
298                 beanContext.add(result);
299             }
300
301         // If it was deserialized then it was already init-ed.
302
// Otherwise we need to initialize it.
303

304         if (!serialized) {
305             // We need to set a reasonable initial size, as many
306
// applets are unhappy if they are started without
307
// having been explicitly sized.
308
applet.setSize(100,100);
309             applet.init();
310         }
311
312         if (needDummies) {
313           ((BeansAppletStub)stub).active = true;
314         } else initializer.activate(applet);
315
316         } else if (beanContext != null) beanContext.add(result);
317     }
318
319     return result;
320     }
321
322
323     /**
324      * From a given bean, obtain an object representing a specified
325      * type view of that source object.
326      * <p>
327      * The result may be the same object or a different object. If
328      * the requested target view isn't available then the given
329      * bean is returned.
330      * <p>
331      * This method is provided in Beans 1.0 as a hook to allow the
332      * addition of more flexible bean behaviour in the future.
333      *
334      * @param bean Object from which we want to obtain a view.
335      * @param targetType The type of view we'd like to get.
336      *
337      */

338     public static Object JavaDoc getInstanceOf(Object JavaDoc bean, Class JavaDoc<?> targetType) {
339         return bean;
340     }
341
342     /**
343      * Check if a bean can be viewed as a given target type.
344      * The result will be true if the Beans.getInstanceof method
345      * can be used on the given bean to obtain an object that
346      * represents the specified targetType type view.
347      *
348      * @param bean Bean from which we want to obtain a view.
349      * @param targetType The type of view we'd like to get.
350      * @return "true" if the given bean supports the given targetType.
351      *
352      */

353     public static boolean isInstanceOf(Object JavaDoc bean, Class JavaDoc<?> targetType) {
354     return Introspector.isSubclass(bean.getClass(), targetType);
355     }
356
357
358     /**
359      * Test if we are in design-mode.
360      *
361      * @return True if we are running in an application construction
362      * environment.
363      *
364      * @see java.beans.DesignMode
365      */

366     public static boolean isDesignTime() {
367     return designTime;
368     }
369
370     /**
371      * Determines whether beans can assume a GUI is available.
372      *
373      * @return True if we are running in an environment where beans
374      * can assume that an interactive GUI is available, so they
375      * can pop up dialog boxes, etc. This will normally return
376      * true in a windowing environment, and will normally return
377      * false in a server environment or if an application is
378      * running as part of a batch job.
379      *
380      * @see java.beans.Visibility
381      *
382      */

383     public static boolean isGuiAvailable() {
384     return guiAvailable;
385     }
386
387     /**
388      * Used to indicate whether of not we are running in an application
389      * builder environment.
390      *
391      * <p>Note that this method is security checked
392      * and is not available to (for example) untrusted applets.
393      * More specifically, if there is a security manager,
394      * its <code>checkPropertiesAccess</code>
395      * method is called. This could result in a SecurityException.
396      *
397      * @param isDesignTime True if we're in an application builder tool.
398      * @exception SecurityException if a security manager exists and its
399      * <code>checkPropertiesAccess</code> method doesn't allow setting
400      * of system properties.
401      * @see SecurityManager#checkPropertiesAccess
402      */

403
404     public static void setDesignTime(boolean isDesignTime)
405             throws SecurityException JavaDoc {
406     SecurityManager JavaDoc sm = System.getSecurityManager();
407     if (sm != null) {
408         sm.checkPropertiesAccess();
409     }
410     designTime = isDesignTime;
411     }
412
413     /**
414      * Used to indicate whether of not we are running in an environment
415      * where GUI interaction is available.
416      *
417      * <p>Note that this method is security checked
418      * and is not available to (for example) untrusted applets.
419      * More specifically, if there is a security manager,
420      * its <code>checkPropertiesAccess</code>
421      * method is called. This could result in a SecurityException.
422      *
423      * @param isGuiAvailable True if GUI interaction is available.
424      * @exception SecurityException if a security manager exists and its
425      * <code>checkPropertiesAccess</code> method doesn't allow setting
426      * of system properties.
427      * @see SecurityManager#checkPropertiesAccess
428      */

429
430     public static void setGuiAvailable(boolean isGuiAvailable)
431             throws SecurityException JavaDoc {
432     SecurityManager JavaDoc sm = System.getSecurityManager();
433     if (sm != null) {
434         sm.checkPropertiesAccess();
435     }
436     guiAvailable = isGuiAvailable;
437     }
438
439
440     private static boolean designTime;
441     private static boolean guiAvailable;
442     static {
443         guiAvailable = !GraphicsEnvironment.isHeadless();
444     }
445 }
446
447 /**
448  * This subclass of ObjectInputStream delegates loading of classes to
449  * an existing ClassLoader.
450  */

451
452 class ObjectInputStreamWithLoader extends ObjectInputStream
453 {
454     private ClassLoader JavaDoc loader;
455
456     /**
457      * Loader must be non-null;
458      */

459
460     public ObjectInputStreamWithLoader(InputStream in, ClassLoader JavaDoc loader)
461         throws IOException, StreamCorruptedException {
462
463     super(in);
464     if (loader == null) {
465             throw new IllegalArgumentException JavaDoc("Illegal null argument to ObjectInputStreamWithLoader");
466     }
467     this.loader = loader;
468     }
469
470     /**
471      * Make a primitive array class
472      */

473
474     private Class JavaDoc primitiveType(char type) {
475     switch (type) {
476     case 'B': return byte.class;
477         case 'C': return char.class;
478     case 'D': return double.class;
479     case 'F': return float.class;
480     case 'I': return int.class;
481     case 'J': return long.class;
482     case 'S': return short.class;
483     case 'Z': return boolean.class;
484     default: return null;
485     }
486     }
487
488     /**
489      * Use the given ClassLoader rather than using the system class
490      */

491     protected Class JavaDoc resolveClass(ObjectStreamClass classDesc)
492     throws IOException, ClassNotFoundException JavaDoc {
493
494     String JavaDoc cname = classDesc.getName();
495     if (cname.startsWith("[")) {
496         // An array
497
Class JavaDoc component; // component class
498
int dcount; // dimension
499
for (dcount=1; cname.charAt(dcount)=='['; dcount++) ;
500         if (cname.charAt(dcount) == 'L') {
501         component = loader.loadClass(cname.substring(dcount+1,
502                                  cname.length()-1));
503         } else {
504         if (cname.length() != dcount+1) {
505             throw new ClassNotFoundException JavaDoc(cname);// malformed
506
}
507         component = primitiveType(cname.charAt(dcount));
508         }
509         int dim[] = new int[dcount];
510         for (int i=0; i<dcount; i++) {
511         dim[i]=0;
512         }
513         return Array.newInstance(component, dim).getClass();
514     } else {
515         return loader.loadClass(cname);
516     }
517     }
518 }
519
520 /**
521  * Package private support class. This provides a default AppletContext
522  * for beans which are applets.
523  */

524
525 class BeansAppletContext implements AppletContext {
526     Applet target;
527     java.util.Hashtable JavaDoc imageCache = new java.util.Hashtable JavaDoc();
528
529     BeansAppletContext(Applet target) {
530         this.target = target;
531     }
532
533     public AudioClip getAudioClip(URL JavaDoc url) {
534     // We don't currently support audio clips in the Beans.instantiate
535
// applet context, unless by some luck there exists a URL content
536
// class that can generate an AudioClip from the audio URL.
537
try {
538         return (AudioClip) url.getContent();
539     } catch (Exception JavaDoc ex) {
540         return null;
541     }
542     }
543
544     public synchronized Image getImage(URL JavaDoc url) {
545     Object JavaDoc o = imageCache.get(url);
546     if (o != null) {
547         return (Image)o;
548     }
549     try {
550         o = url.getContent();
551         if (o == null) {
552         return null;
553         }
554         if (o instanceof Image) {
555         imageCache.put(url, o);
556         return (Image) o;
557         }
558         // Otherwise it must be an ImageProducer.
559
Image img = target.createImage((java.awt.image.ImageProducer JavaDoc)o);
560         imageCache.put(url, img);
561         return img;
562
563     } catch (Exception JavaDoc ex) {
564         return null;
565     }
566     }
567
568     public Applet getApplet(String JavaDoc name) {
569     return null;
570     }
571
572     public java.util.Enumeration JavaDoc getApplets() {
573     java.util.Vector JavaDoc applets = new java.util.Vector JavaDoc();
574     applets.addElement(target);
575     return applets.elements();
576     }
577
578     public void showDocument(URL JavaDoc url) {
579     // We do nothing.
580
}
581
582     public void showDocument(URL JavaDoc url, String JavaDoc target) {
583     // We do nothing.
584
}
585
586     public void showStatus(String JavaDoc status) {
587     // We do nothing.
588
}
589
590     public void setStream(String JavaDoc key, InputStream stream)throws IOException{
591     // We do nothing.
592
}
593
594     public InputStream getStream(String JavaDoc key){
595     // We do nothing.
596
return null;
597     }
598
599     public java.util.Iterator JavaDoc getStreamKeys(){
600     // We do nothing.
601
return null;
602     }
603 }
604
605 /**
606  * Package private support class. This provides an AppletStub
607  * for beans which are applets.
608  */

609 class BeansAppletStub implements AppletStub {
610     transient boolean active;
611     transient Applet target;
612     transient AppletContext context;
613     transient URL JavaDoc codeBase;
614     transient URL JavaDoc docBase;
615
616     BeansAppletStub(Applet target,
617         AppletContext context, URL JavaDoc codeBase,
618                 URL JavaDoc docBase) {
619         this.target = target;
620     this.context = context;
621     this.codeBase = codeBase;
622     this.docBase = docBase;
623     }
624
625     public boolean isActive() {
626     return active;
627     }
628
629     public URL JavaDoc getDocumentBase() {
630     // use the root directory of the applet's class-loader
631
return docBase;
632     }
633
634     public URL JavaDoc getCodeBase() {
635     // use the directory where we found the class or serialized object.
636
return codeBase;
637     }
638
639     public String JavaDoc getParameter(String JavaDoc name) {
640     return null;
641     }
642
643     public AppletContext getAppletContext() {
644     return context;
645     }
646
647     public void appletResize(int width, int height) {
648     // we do nothing.
649
}
650 }
651
Popular Tags