KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > javax > swing > UIDefaults


1 /*
2  * @(#)UIDefaults.java 1.58 04/05/05
3  *
4  * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
5  * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
6  */

7
8 package javax.swing;
9
10
11 import javax.swing.plaf.ComponentUI JavaDoc;
12 import javax.swing.border.*;
13 import javax.swing.event.SwingPropertyChangeSupport JavaDoc;
14
15 import java.lang.reflect.*;
16 import java.util.HashMap JavaDoc;
17 import java.util.Map JavaDoc;
18 import java.util.Enumeration JavaDoc;
19 import java.util.Hashtable JavaDoc;
20 import java.util.ResourceBundle JavaDoc;
21 import java.util.Locale JavaDoc;
22 import java.util.Vector JavaDoc;
23 import java.util.MissingResourceException JavaDoc;
24 import java.awt.Font JavaDoc;
25 import java.awt.Color JavaDoc;
26 import java.awt.Insets JavaDoc;
27 import java.awt.Dimension JavaDoc;
28 import java.lang.reflect.Method JavaDoc;
29 import java.beans.PropertyChangeListener JavaDoc;
30 import java.beans.PropertyChangeEvent JavaDoc;
31 import java.security.AccessController JavaDoc;
32 import java.security.AccessControlContext JavaDoc;
33 import java.security.PrivilegedAction JavaDoc;
34
35 import sun.reflect.misc.MethodUtil;
36
37 /**
38  * A table of defaults for Swing components. Applications can set/get
39  * default values via the <code>UIManager</code>.
40  * <p>
41  * <strong>Warning:</strong>
42  * Serialized objects of this class will not be compatible with
43  * future Swing releases. The current serialization support is
44  * appropriate for short term storage or RMI between applications running
45  * the same version of Swing. As of 1.4, support for long term storage
46  * of all JavaBeans<sup><font size="-2">TM</font></sup>
47  * has been added to the <code>java.beans</code> package.
48  * Please see {@link java.beans.XMLEncoder}.
49  *
50  * @see UIManager
51  * @version 1.58 05/05/04
52  * @author Hans Muller
53  */

54 public class UIDefaults extends Hashtable JavaDoc<Object JavaDoc,Object JavaDoc>
55 {
56     private static final Object JavaDoc PENDING = new String JavaDoc("Pending");
57
58     private SwingPropertyChangeSupport JavaDoc changeSupport;
59
60     private Vector JavaDoc resourceBundles;
61
62     private Locale JavaDoc defaultLocale = Locale.getDefault();
63
64     /**
65      * Maps from a Locale to a cached Map of the ResourceBundle. This is done
66      * so as to avoid an exception being thrown when a value is asked for.
67      * Access to this should be done while holding a lock on the
68      * UIDefaults, eg synchronized(this).
69      */

70     private Map JavaDoc resourceCache;
71
72     /**
73      * Create an empty defaults table.
74      */

75     public UIDefaults() {
76         super(700, .75f);
77         resourceCache = new HashMap JavaDoc();
78     }
79
80
81     /**
82      * Create a defaults table initialized with the specified
83      * key/value pairs. For example:
84      * <pre>
85         Object[] uiDefaults = {
86              "Font", new Font("Dialog", Font.BOLD, 12),
87             "Color", Color.red,
88              "five", new Integer(5)
89         }
90         UIDefaults myDefaults = new UIDefaults(uiDefaults);
91      * </pre>
92      * @param keyValueList an array of objects containing the key/value
93      * pairs
94      */

95     public UIDefaults(Object JavaDoc[] keyValueList) {
96         super(keyValueList.length / 2);
97         for(int i = 0; i < keyValueList.length; i += 2) {
98             super.put(keyValueList[i], keyValueList[i + 1]);
99         }
100     }
101
102
103     /**
104      * Returns the value for key. If the value is a
105      * <code>UIDefaults.LazyValue</code> then the real
106      * value is computed with <code>LazyValue.createValue()</code>,
107      * the table entry is replaced, and the real value is returned.
108      * If the value is an <code>UIDefaults.ActiveValue</code>
109      * the table entry is not replaced - the value is computed
110      * with <code>ActiveValue.createValue()</code> for each
111      * <code>get()</code> call.
112      *
113      * If the key is not found in the table then it is searched for in the list
114      * of resource bundles maintained by this object. The resource bundles are
115      * searched most recently added first using the locale returned by
116      * <code>getDefaultLocale</code>. <code>LazyValues</code> and
117      * <code>ActiveValues</code> are not supported in the resource bundles.
118
119      *
120      * @param key the desired key
121      * @return the value for <code>key</code>
122      * @see LazyValue
123      * @see ActiveValue
124      * @see java.util.Hashtable#get
125      * @see #getDefaultLocale
126      * @see #addResourceBundle
127      * @since 1.4
128      */

129     public Object JavaDoc get(Object JavaDoc key) {
130         Object JavaDoc value = getFromHashtable( key );
131         return (value != null) ? value : getFromResourceBundle(key, null);
132     }
133
134     /**
135      * Looks up up the given key in our Hashtable and resolves LazyValues
136      * or ActiveValues.
137      */

138     private Object JavaDoc getFromHashtable(Object JavaDoc key) {
139         /* Quickly handle the common case, without grabbing
140          * a lock.
141          */

142         Object JavaDoc value = super.get(key);
143         if ((value != PENDING) &&
144             !(value instanceof ActiveValue) &&
145             !(value instanceof LazyValue)) {
146             return value;
147         }
148
149         /* If the LazyValue for key is being constructed by another
150          * thread then wait and then return the new value, otherwise drop
151          * the lock and construct the ActiveValue or the LazyValue.
152          * We use the special value PENDING to mark LazyValues that
153          * are being constructed.
154          */

155         synchronized(this) {
156             value = super.get(key);
157             if (value == PENDING) {
158                 do {
159                     try {
160                         this.wait();
161                     }
162                     catch (InterruptedException JavaDoc e) {
163                     }
164                     value = super.get(key);
165                 }
166                 while(value == PENDING);
167                 return value;
168             }
169             else if (value instanceof LazyValue) {
170                 super.put(key, PENDING);
171             }
172             else if (!(value instanceof ActiveValue)) {
173                 return value;
174             }
175         }
176
177         /* At this point we know that the value of key was
178          * a LazyValue or an ActiveValue.
179          */

180         if (value instanceof LazyValue) {
181             try {
182                 /* If an exception is thrown we'll just put the LazyValue
183                  * back in the table.
184                  */

185                 value = ((LazyValue)value).createValue(this);
186             }
187             finally {
188                 synchronized(this) {
189                     if (value == null) {
190                         super.remove(key);
191                     }
192                     else {
193                         super.put(key, value);
194                     }
195                     this.notifyAll();
196                 }
197             }
198         }
199         else {
200             value = ((ActiveValue)value).createValue(this);
201         }
202
203         return value;
204     }
205
206
207     /**
208      * Returns the value for key associated with the given locale.
209      * If the value is a <code>UIDefaults.LazyValue</code> then the real
210      * value is computed with <code>LazyValue.createValue()</code>,
211      * the table entry is replaced, and the real value is returned.
212      * If the value is an <code>UIDefaults.ActiveValue</code>
213      * the table entry is not replaced - the value is computed
214      * with <code>ActiveValue.createValue()</code> for each
215      * <code>get()</code> call.
216      *
217      * If the key is not found in the table then it is searched for in the list
218      * of resource bundles maintained by this object. The resource bundles are
219      * searched most recently added first using the given locale.
220      * <code>LazyValues</code> and <code>ActiveValues</code> are not supported
221      * in the resource bundles.
222      *
223      * @param key the desired key
224      * @param l the desired <code>locale</code>
225      * @return the value for <code>key</code>
226      * @see LazyValue
227      * @see ActiveValue
228      * @see java.util.Hashtable#get
229      * @see #addResourceBundle
230      * @since 1.4
231      */

232     public Object JavaDoc get(Object JavaDoc key, Locale JavaDoc l) {
233         Object JavaDoc value = getFromHashtable( key );
234         return (value != null) ? value : getFromResourceBundle(key, l);
235     }
236
237     /**
238      * Looks up given key in our resource bundles.
239      */

240     private Object JavaDoc getFromResourceBundle(Object JavaDoc key, Locale JavaDoc l) {
241
242         if( resourceBundles == null ||
243             resourceBundles.isEmpty() ||
244             !(key instanceof String JavaDoc) ) {
245             return null;
246         }
247
248         // A null locale means use the default locale.
249
if( l == null ) {
250             if( defaultLocale == null )
251                 return null;
252             else
253                 l = (Locale JavaDoc)defaultLocale;
254         }
255
256         synchronized(this) {
257             return getResourceCache(l).get((String JavaDoc)key);
258         }
259     }
260
261     /**
262      * Returns a Map of the known resources for the given locale.
263      */

264     private Map JavaDoc getResourceCache(Locale JavaDoc l) {
265         Map JavaDoc values = (Map JavaDoc)resourceCache.get(l);
266
267         if (values == null) {
268             values = new HashMap JavaDoc();
269             for (int i=resourceBundles.size()-1; i >= 0; i--) {
270                 String JavaDoc bundleName = (String JavaDoc)resourceBundles.get(i);
271                 try {
272                     ResourceBundle JavaDoc b = ResourceBundle.getBundle(bundleName, l);
273                     Enumeration JavaDoc keys = b.getKeys();
274
275                     while (keys.hasMoreElements()) {
276                         String JavaDoc key = (String JavaDoc)keys.nextElement();
277
278                         if (values.get(key) == null) {
279                             Object JavaDoc value = b.getObject(key);
280
281                             values.put(key, value);
282                         }
283                     }
284                 } catch( MissingResourceException JavaDoc mre ) {
285                     // Keep looking
286
}
287             }
288             resourceCache.put(l, values);
289         }
290         return values;
291     }
292
293     /**
294      * Sets the value of <code>key</code> to <code>value</code> for all locales.
295      * If <code>key</code> is a string and the new value isn't
296      * equal to the old one, fire a <code>PropertyChangeEvent</code>.
297      * If value is <code>null</code>, the key is removed from the table.
298      *
299      * @param key the unique <code>Object</code> who's value will be used
300      * to retrieve the data value associated with it
301      * @param value the new <code>Object</code> to store as data under
302      * that key
303      * @return the previous <code>Object</code> value, or <code>null</code>
304      * @see #putDefaults
305      * @see java.util.Hashtable#put
306      */

307     public Object JavaDoc put(Object JavaDoc key, Object JavaDoc value) {
308         Object JavaDoc oldValue = (value == null) ? super.remove(key) : super.put(key, value);
309         if (key instanceof String JavaDoc) {
310             firePropertyChange((String JavaDoc)key, oldValue, value);
311         }
312         return oldValue;
313     }
314
315
316     /**
317      * Puts all of the key/value pairs in the database and
318      * unconditionally generates one <code>PropertyChangeEvent</code>.
319      * The events oldValue and newValue will be <code>null</code> and its
320      * <code>propertyName</code> will be "UIDefaults". The key/value pairs are
321      * added for all locales.
322      *
323      * @param keyValueList an array of key/value pairs
324      * @see #put
325      * @see java.util.Hashtable#put
326      */

327     public void putDefaults(Object JavaDoc[] keyValueList) {
328         for(int i = 0, max = keyValueList.length; i < max; i += 2) {
329             Object JavaDoc value = keyValueList[i + 1];
330             if (value == null) {
331                 super.remove(keyValueList[i]);
332             }
333             else {
334                 super.put(keyValueList[i], value);
335             }
336         }
337         firePropertyChange("UIDefaults", null, null);
338     }
339
340
341     /**
342      * If the value of <code>key</code> is a <code>Font</code> return it,
343      * otherwise return <code>null</code>.
344      * @param key the desired key
345      * @return if the value for <code>key</code> is a <code>Font</code>,
346      * return the <code>Font</code> object; otherwise return
347      * <code>null</code>
348      */

349     public Font JavaDoc getFont(Object JavaDoc key) {
350         Object JavaDoc value = get(key);
351         return (value instanceof Font JavaDoc) ? (Font JavaDoc)value : null;
352     }
353
354
355     /**
356      * If the value of <code>key</code> for the given <code>Locale</code>
357      * is a <code>Font</code> return it, otherwise return <code>null</code>.
358      * @param key the desired key
359      * @param l the desired locale
360      * @return if the value for <code>key</code> and <code>Locale</code>
361      * is a <code>Font</code>,
362      * return the <code>Font</code> object; otherwise return
363      * <code>null</code>
364      * @since 1.4
365      */

366     public Font JavaDoc getFont(Object JavaDoc key, Locale JavaDoc l) {
367         Object JavaDoc value = get(key,l);
368         return (value instanceof Font JavaDoc) ? (Font JavaDoc)value : null;
369     }
370
371     /**
372      * If the value of <code>key</code> is a <code>Color</code> return it,
373      * otherwise return <code>null</code>.
374      * @param key the desired key
375      * @return if the value for <code>key</code> is a <code>Color</code>,
376      * return the <code>Color</code> object; otherwise return
377      * <code>null</code>
378      */

379     public Color JavaDoc getColor(Object JavaDoc key) {
380         Object JavaDoc value = get(key);
381         return (value instanceof Color JavaDoc) ? (Color JavaDoc)value : null;
382     }
383
384
385     /**
386      * If the value of <code>key</code> for the given <code>Locale</code>
387      * is a <code>Color</code> return it, otherwise return <code>null</code>.
388      * @param key the desired key
389      * @param l the desired locale
390      * @return if the value for <code>key</code> and <code>Locale</code>
391      * is a <code>Color</code>,
392      * return the <code>Color</code> object; otherwise return
393      * <code>null</code>
394      * @since 1.4
395      */

396     public Color JavaDoc getColor(Object JavaDoc key, Locale JavaDoc l) {
397         Object JavaDoc value = get(key,l);
398         return (value instanceof Color JavaDoc) ? (Color JavaDoc)value : null;
399     }
400
401
402     /**
403      * If the value of <code>key</code> is an <code>Icon</code> return it,
404      * otherwise return <code>null</code>.
405      * @param key the desired key
406      * @return if the value for <code>key</code> is an <code>Icon</code>,
407      * return the <code>Icon</code> object; otherwise return
408      * <code>null</code>
409      */

410     public Icon JavaDoc getIcon(Object JavaDoc key) {
411         Object JavaDoc value = get(key);
412         return (value instanceof Icon JavaDoc) ? (Icon JavaDoc)value : null;
413     }
414
415
416     /**
417      * If the value of <code>key</code> for the given <code>Locale</code>
418      * is an <code>Icon</code> return it, otherwise return <code>null</code>.
419      * @param key the desired key
420      * @param l the desired locale
421      * @return if the value for <code>key</code> and <code>Locale</code>
422      * is an <code>Icon</code>,
423      * return the <code>Icon</code> object; otherwise return
424      * <code>null</code>
425      * @since 1.4
426      */

427     public Icon JavaDoc getIcon(Object JavaDoc key, Locale JavaDoc l) {
428         Object JavaDoc value = get(key,l);
429         return (value instanceof Icon JavaDoc) ? (Icon JavaDoc)value : null;
430     }
431
432
433     /**
434      * If the value of <code>key</code> is a <code>Border</code> return it,
435      * otherwise return <code>null</code>.
436      * @param key the desired key
437      * @return if the value for <code>key</code> is a <code>Border</code>,
438      * return the <code>Border</code> object; otherwise return
439      * <code>null</code>
440      */

441     public Border getBorder(Object JavaDoc key) {
442         Object JavaDoc value = get(key);
443         return (value instanceof Border) ? (Border)value : null;
444     }
445
446
447     /**
448      * If the value of <code>key</code> for the given <code>Locale</code>
449      * is a <code>Border</code> return it, otherwise return <code>null</code>.
450      * @param key the desired key
451      * @param l the desired locale
452      * @return if the value for <code>key</code> and <code>Locale</code>
453      * is a <code>Border</code>,
454      * return the <code>Border</code> object; otherwise return
455      * <code>null</code>
456      * @since 1.4
457      */

458     public Border getBorder(Object JavaDoc key, Locale JavaDoc l) {
459         Object JavaDoc value = get(key,l);
460         return (value instanceof Border) ? (Border)value : null;
461     }
462
463
464     /**
465      * If the value of <code>key</code> is a <code>String</code> return it,
466      * otherwise return <code>null</code>.
467      * @param key the desired key
468      * @return if the value for <code>key</code> is a <code>String</code>,
469      * return the <code>String</code> object; otherwise return
470      * <code>null</code>
471      */

472     public String JavaDoc getString(Object JavaDoc key) {
473         Object JavaDoc value = get(key);
474         return (value instanceof String JavaDoc) ? (String JavaDoc)value : null;
475     }
476
477     /**
478      * If the value of <code>key</code> for the given <code>Locale</code>
479      * is a <code>String</code> return it, otherwise return <code>null</code>.
480      * @param key the desired key
481      * @param l the desired <code>Locale</code>
482      * @return if the value for <code>key</code> for the given
483      * <code>Locale</code> is a <code>String</code>,
484      * return the <code>String</code> object; otherwise return
485      * <code>null</code>
486      * @since 1.4
487      */

488     public String JavaDoc getString(Object JavaDoc key, Locale JavaDoc l) {
489         Object JavaDoc value = get(key,l);
490         return (value instanceof String JavaDoc) ? (String JavaDoc)value : null;
491     }
492
493     /**
494      * If the value of <code>key</code> is an <code>Integer</code> return its
495      * integer value, otherwise return 0.
496      * @param key the desired key
497      * @return if the value for <code>key</code> is an <code>Integer</code>,
498      * return its value, otherwise return 0
499      */

500     public int getInt(Object JavaDoc key) {
501         Object JavaDoc value = get(key);
502         return (value instanceof Integer JavaDoc) ? ((Integer JavaDoc)value).intValue() : 0;
503     }
504
505
506     /**
507      * If the value of <code>key</code> for the given <code>Locale</code>
508      * is an <code>Integer</code> return its integer value, otherwise return 0.
509      * @param key the desired key
510      * @param l the desired locale
511      * @return if the value for <code>key</code> and <code>Locale</code>
512      * is an <code>Integer</code>,
513      * return its value, otherwise return 0
514      * @since 1.4
515      */

516     public int getInt(Object JavaDoc key, Locale JavaDoc l) {
517         Object JavaDoc value = get(key,l);
518         return (value instanceof Integer JavaDoc) ? ((Integer JavaDoc)value).intValue() : 0;
519     }
520
521
522     /**
523      * If the value of <code>key</code> is boolean, return the
524      * boolean value, otherwise return false.
525      *
526      * @param key an <code>Object</code> specifying the key for the desired boolean value
527      * @return if the value of <code>key</code> is boolean, return the
528      * boolean value, otherwise return false.
529      * @since 1.4
530      */

531     public boolean getBoolean(Object JavaDoc key) {
532         Object JavaDoc value = get(key);
533         return (value instanceof Boolean JavaDoc) ? ((Boolean JavaDoc)value).booleanValue() : false;
534     }
535
536
537     /**
538      * If the value of <code>key</code> for the given <code>Locale</code>
539      * is boolean, return the boolean value, otherwise return false.
540      *
541      * @param key an <code>Object</code> specifying the key for the desired boolean value
542      * @param l the desired locale
543      * @return if the value for <code>key</code> and <code>Locale</code>
544      * is boolean, return the
545      * boolean value, otherwise return false.
546      * @since 1.4
547      */

548     public boolean getBoolean(Object JavaDoc key, Locale JavaDoc l) {
549         Object JavaDoc value = get(key,l);
550         return (value instanceof Boolean JavaDoc) ? ((Boolean JavaDoc)value).booleanValue() : false;
551     }
552
553
554     /**
555      * If the value of <code>key</code> is an <code>Insets</code> return it,
556      * otherwise return <code>null</code>.
557      * @param key the desired key
558      * @return if the value for <code>key</code> is an <code>Insets</code>,
559      * return the <code>Insets</code> object; otherwise return
560      * <code>null</code>
561      */

562     public Insets JavaDoc getInsets(Object JavaDoc key) {
563         Object JavaDoc value = get(key);
564         return (value instanceof Insets JavaDoc) ? (Insets JavaDoc)value : null;
565     }
566
567
568     /**
569      * If the value of <code>key</code> for the given <code>Locale</code>
570      * is an <code>Insets</code> return it, otherwise return <code>null</code>.
571      * @param key the desired key
572      * @param l the desired locale
573      * @return if the value for <code>key</code> and <code>Locale</code>
574      * is an <code>Insets</code>,
575      * return the <code>Insets</code> object; otherwise return
576      * <code>null</code>
577      * @since 1.4
578      */

579     public Insets JavaDoc getInsets(Object JavaDoc key, Locale JavaDoc l) {
580         Object JavaDoc value = get(key,l);
581         return (value instanceof Insets JavaDoc) ? (Insets JavaDoc)value : null;
582     }
583
584
585     /**
586      * If the value of <code>key</code> is a <code>Dimension</code> return it,
587      * otherwise return <code>null</code>.
588      * @param key the desired key
589      * @return if the value for <code>key</code> is a <code>Dimension</code>,
590      * return the <code>Dimension</code> object; otherwise return
591      * <code>null</code>
592      */

593     public Dimension JavaDoc getDimension(Object JavaDoc key) {
594         Object JavaDoc value = get(key);
595         return (value instanceof Dimension JavaDoc) ? (Dimension JavaDoc)value : null;
596     }
597
598
599     /**
600      * If the value of <code>key</code> for the given <code>Locale</code>
601      * is a <code>Dimension</code> return it, otherwise return <code>null</code>.
602      * @param key the desired key
603      * @param l the desired locale
604      * @return if the value for <code>key</code> and <code>Locale</code>
605      * is a <code>Dimension</code>,
606      * return the <code>Dimension</code> object; otherwise return
607      * <code>null</code>
608      * @since 1.4
609      */

610     public Dimension JavaDoc getDimension(Object JavaDoc key, Locale JavaDoc l) {
611         Object JavaDoc value = get(key,l);
612         return (value instanceof Dimension JavaDoc) ? (Dimension JavaDoc)value : null;
613     }
614
615
616     /**
617      * The value of <code>get(uidClassID)</code> must be the
618      * <code>String</code> name of a
619      * class that implements the corresponding <code>ComponentUI</code>
620      * class. If the class hasn't been loaded before, this method looks
621      * up the class with <code>uiClassLoader.loadClass()</code> if a non
622      * <code>null</code>
623      * class loader is provided, <code>classForName()</code> otherwise.
624      * <p>
625      * If a mapping for <code>uiClassID</code> exists or if the specified
626      * class can't be found, return <code>null</code>.
627      * <p>
628      * This method is used by <code>getUI</code>, it's usually
629      * not necessary to call it directly.
630      *
631      * @param uiClassID a string containing the class ID
632      * @param uiClassLoader the object which will load the class
633      * @return the value of <code>Class.forName(get(uidClassID))</code>
634      * @see #getUI
635      */

636     public Class JavaDoc<? extends ComponentUI JavaDoc>
637     getUIClass(String JavaDoc uiClassID, ClassLoader JavaDoc uiClassLoader)
638     {
639         try {
640             String JavaDoc className = (String JavaDoc)get(uiClassID);
641             if (className != null) {
642                 Class JavaDoc cls = (Class JavaDoc)get(className);
643                 if (cls == null) {
644                     if (uiClassLoader == null) {
645                         cls = SwingUtilities.loadSystemClass(className);
646                     }
647                     else {
648                         cls = uiClassLoader.loadClass(className);
649                     }
650                     if (cls != null) {
651                         // Save lookup for future use, as forName is slow.
652
put(className, cls);
653                     }
654                 }
655                 return cls;
656             }
657         }
658     catch (ClassNotFoundException JavaDoc e) {
659             return null;
660         }
661     catch (ClassCastException JavaDoc e) {
662             return null;
663         }
664         return null;
665     }
666
667
668     /**
669      * Returns the L&F class that renders this component.
670      *
671      * @param uiClassID a string containing the class ID
672      * @return the Class object returned by
673      * <code>getUIClass(uiClassID, null)</code>
674      */

675     public Class JavaDoc<? extends ComponentUI JavaDoc> getUIClass(String JavaDoc uiClassID) {
676     return getUIClass(uiClassID, null);
677     }
678
679
680     /**
681      * If <code>getUI()</code> fails for any reason,
682      * it calls this method before returning <code>null</code>.
683      * Subclasses may choose to do more or less here.
684      *
685      * @param msg message string to print
686      * @see #getUI
687      */

688     protected void getUIError(String JavaDoc msg) {
689         System.err.println("UIDefaults.getUI() failed: " + msg);
690         try {
691             throw new Error JavaDoc();
692         }
693         catch (Throwable JavaDoc e) {
694             e.printStackTrace();
695         }
696     }
697
698     /**
699      * Creates an <code>ComponentUI</code> implementation for the
700      * specified component. In other words create the look
701      * and feel specific delegate object for <code>target</code>.
702      * This is done in two steps:
703      * <ul>
704      * <li> Look up the name of the <code>ComponentUI</code> implementation
705      * class under the value returned by <code>target.getUIClassID()</code>.
706      * <li> Use the implementation classes static <code>createUI()</code>
707      * method to construct a look and feel delegate.
708      * </ul>
709      * @param target the <code>JComponent</code> which needs a UI
710      * @return the <code>ComponentUI</code> object
711      */

712     public ComponentUI JavaDoc getUI(JComponent JavaDoc target) {
713
714         Object JavaDoc cl = get("ClassLoader");
715     ClassLoader JavaDoc uiClassLoader =
716         (cl != null) ? (ClassLoader JavaDoc)cl : target.getClass().getClassLoader();
717         Class JavaDoc uiClass = getUIClass(target.getUIClassID(), uiClassLoader);
718         Object JavaDoc uiObject = null;
719
720         if (uiClass == null) {
721             getUIError("no ComponentUI class for: " + target);
722         }
723         else {
724             try {
725         Method JavaDoc m = (Method JavaDoc)get(uiClass);
726         if (m == null) {
727             Class JavaDoc acClass = javax.swing.JComponent JavaDoc.class;
728             m = uiClass.getMethod("createUI", new Class JavaDoc[]{acClass});
729             put(uiClass, m);
730         }
731         uiObject = MethodUtil.invoke(m, null, new Object JavaDoc[]{target});
732             }
733             catch (NoSuchMethodException JavaDoc e) {
734                 getUIError("static createUI() method not found in " + uiClass);
735             }
736             catch (Exception JavaDoc e) {
737                 getUIError("createUI() failed for " + target + " " + e);
738             }
739         }
740
741         return (ComponentUI JavaDoc)uiObject;
742     }
743
744     /**
745      * Adds a <code>PropertyChangeListener</code> to the listener list.
746      * The listener is registered for all properties.
747      * <p>
748      * A <code>PropertyChangeEvent</code> will get fired whenever a default
749      * is changed.
750      *
751      * @param listener the <code>PropertyChangeListener</code> to be added
752      * @see java.beans.PropertyChangeSupport
753      */

754     public synchronized void addPropertyChangeListener(PropertyChangeListener JavaDoc listener) {
755         if (changeSupport == null) {
756             changeSupport = new SwingPropertyChangeSupport JavaDoc(this);
757         }
758         changeSupport.addPropertyChangeListener(listener);
759     }
760
761
762     /**
763      * Removes a <code>PropertyChangeListener</code> from the listener list.
764      * This removes a <code>PropertyChangeListener</code> that was registered
765      * for all properties.
766      *
767      * @param listener the <code>PropertyChangeListener</code> to be removed
768      * @see java.beans.PropertyChangeSupport
769      */

770     public synchronized void removePropertyChangeListener(PropertyChangeListener JavaDoc listener) {
771         if (changeSupport != null) {
772             changeSupport.removePropertyChangeListener(listener);
773         }
774     }
775
776
777     /**
778      * Returns an array of all the <code>PropertyChangeListener</code>s added
779      * to this UIDefaults with addPropertyChangeListener().
780      *
781      * @return all of the <code>PropertyChangeListener</code>s added or an empty
782      * array if no listeners have been added
783      * @since 1.4
784      */

785     public synchronized PropertyChangeListener JavaDoc[] getPropertyChangeListeners() {
786         if (changeSupport == null) {
787             return new PropertyChangeListener JavaDoc[0];
788         }
789         return changeSupport.getPropertyChangeListeners();
790     }
791
792
793     /**
794      * Support for reporting bound property changes. If oldValue and
795      * newValue are not equal and the <code>PropertyChangeEvent</code>x
796      * listener list isn't empty, then fire a
797      * <code>PropertyChange</code> event to each listener.
798      *
799      * @param propertyName the programmatic name of the property