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: /**
019: * @author Sergey Burlak
020: * @version $Revision$
021: */package javax.swing;
022:
023: import java.awt.Color;
024: import java.awt.Dimension;
025: import java.awt.Font;
026: import java.awt.Insets;
027: import java.beans.PropertyChangeListener;
028: import java.io.PrintWriter;
029: import java.io.StringWriter;
030: import java.lang.reflect.Method;
031: import java.security.AccessController;
032: import java.security.PrivilegedAction;
033: import java.util.ArrayList;
034: import java.util.Hashtable;
035: import java.util.List;
036: import java.util.Locale;
037: import java.util.MissingResourceException;
038: import java.util.ResourceBundle;
039:
040: import javax.swing.border.Border;
041: import javax.swing.event.SwingPropertyChangeSupport;
042: import javax.swing.plaf.ComponentUI;
043: import javax.swing.plaf.UIResource;
044:
045: import org.apache.harmony.x.swing.internal.nls.Messages;
046:
047: public class UIDefaults extends Hashtable<Object, Object> {
048:
049: public static interface ActiveValue {
050: Object createValue(UIDefaults uiDefaults);
051: }
052:
053: public static interface LazyValue {
054: Object createValue(UIDefaults uiDefaults);
055: }
056:
057: public static class LazyInputMap implements LazyValue {
058: private Object[] objects;
059:
060: public LazyInputMap(final Object[] objects) {
061: if (objects != null) {
062: this .objects = new Object[objects.length];
063: System.arraycopy(objects, 0, this .objects, 0,
064: objects.length);
065: }
066: }
067:
068: public Object createValue(final UIDefaults uiDefaults) {
069: return LookAndFeel.makeInputMap(objects);
070: }
071:
072: }
073:
074: public static class ProxyLazyValue implements LazyValue {
075: private String className;
076: private String methodName;
077: private Object[] params;
078:
079: private Object value;
080:
081: public ProxyLazyValue(final String className) {
082: this (className, null, null);
083: }
084:
085: public ProxyLazyValue(final String className,
086: final Object[] params) {
087: this (className, null, params);
088: }
089:
090: public ProxyLazyValue(final String className,
091: final String methodName) {
092: this (className, methodName, null);
093: }
094:
095: public ProxyLazyValue(final String className,
096: final String methodName, final Object[] params) {
097: this .className = className;
098: this .methodName = methodName;
099: if (params != null) {
100: this .params = new Object[params.length];
101: System.arraycopy(params, 0, this .params, 0,
102: params.length);
103: }
104: }
105:
106: public Object createValue(final UIDefaults uiDefaults) {
107: AccessController.doPrivileged(new PrivilegedAction() {
108: public Object run() {
109: value = null;
110: try {
111: Class classObj = Class.forName(className, true,
112: Thread.currentThread()
113: .getContextClassLoader());
114: if (params == null) {
115: value = (methodName == null) ? classObj
116: .newInstance() : classObj
117: .getMethod(methodName,
118: (Class[]) null).invoke(
119: null, (Object[]) null);
120: } else {
121: Class[] mParams = new Class[params.length];
122: for (int i = 0; i < mParams.length; i++) {
123: mParams[i] = extractClass(params[i]);
124: }
125:
126: value = (methodName == null) ? classObj
127: .getConstructor(mParams)
128: .newInstance(params) : classObj
129: .getMethod(methodName, mParams)
130: .invoke(null, params);
131: }
132: } catch (Exception ignored) {
133: }
134:
135: return value;
136: }
137: });
138:
139: return value;
140: }
141:
142: /**
143: * Extract class from the object
144: * @param Object obj
145: * @return Class result
146: */
147: private Class extractClass(final Object obj) {
148: if (obj instanceof Integer) {
149: return Integer.TYPE;
150: }
151: if (obj instanceof Boolean) {
152: return Boolean.TYPE;
153: }
154: if (obj instanceof Float) {
155: return Float.TYPE;
156: }
157: if (obj instanceof Character) {
158: return Character.TYPE;
159: }
160: if (obj instanceof Short) {
161: return Short.TYPE;
162: }
163: if (obj instanceof Long) {
164: return Long.TYPE;
165: }
166: if (obj instanceof Double) {
167: return Double.TYPE;
168: }
169: if (obj instanceof Byte) {
170: return Byte.TYPE;
171: }
172: if (obj instanceof Void) {
173: return Void.TYPE;
174: }
175: if (obj instanceof UIResource) {
176: return obj.getClass().getSuperclass();
177: }
178:
179: return obj.getClass();
180: }
181: }
182:
183: private static final String CREATE_UI_METHOD_NAME = "createUI";
184: private Locale defaultLocale = Locale.getDefault();
185: private SwingPropertyChangeSupport propertyChangeSupport = new SwingPropertyChangeSupport(
186: this );
187: private List resourceBundles = new ArrayList();
188:
189: public UIDefaults() {
190: }
191:
192: public UIDefaults(final Object[] array) {
193: putDefaults(array);
194: }
195:
196: public void removePropertyChangeListener(
197: final PropertyChangeListener l) {
198: propertyChangeSupport.removePropertyChangeListener(l);
199: }
200:
201: public void addPropertyChangeListener(final PropertyChangeListener l) {
202: propertyChangeSupport.addPropertyChangeListener(l);
203: }
204:
205: public PropertyChangeListener[] getPropertyChangeListeners() {
206: return propertyChangeSupport.getPropertyChangeListeners();
207: }
208:
209: public void removeResourceBundle(final String name) {
210: resourceBundles.remove(ResourceBundle.getBundle(name,
211: getDefaultLocale()));
212: }
213:
214: public void addResourceBundle(final String name) {
215: ResourceBundle bundle = ResourceBundle.getBundle(name,
216: getDefaultLocale());
217: if (bundle != null) {
218: resourceBundles.add(bundle);
219: }
220: }
221:
222: public Object get(final Object key) {
223: return get(key, getDefaultLocale());
224: }
225:
226: public Object get(final Object key, final Locale locale) {
227: Object result = super .get(key);
228: if (result == null) {
229: result = getFromResourceBundles(key, locale);
230: return result;
231: }
232:
233: if (result instanceof LazyValue) {
234: Object value = ((LazyValue) result).createValue(this );
235: if (key != null && value != null) {
236: super .put(key, value);
237: }
238: result = value;
239: }
240: if (result instanceof ActiveValue) {
241: result = ((ActiveValue) result).createValue(this );
242: }
243:
244: return result;
245: }
246:
247: public boolean getBoolean(final Object obj) {
248: return getBoolean(obj, getDefaultLocale());
249: }
250:
251: public boolean getBoolean(final Object obj, final Locale locale) {
252: Object result = get(obj, locale);
253: return (result instanceof Boolean) ? ((Boolean) result)
254: .booleanValue() : false;
255: }
256:
257: public Border getBorder(final Object obj) {
258: return getBorder(obj, getDefaultLocale());
259: }
260:
261: public Border getBorder(final Object obj, final Locale locale) {
262: Object result = get(obj, locale);
263: return (result instanceof Border) ? (Border) result : null;
264: }
265:
266: public Color getColor(final Object obj) {
267: return getColor(obj, getDefaultLocale());
268: }
269:
270: public Color getColor(final Object obj, final Locale locale) {
271: Object result = get(obj, locale);
272: return (result instanceof Color) ? (Color) result : null;
273: }
274:
275: public Locale getDefaultLocale() {
276: return defaultLocale;
277: }
278:
279: public Dimension getDimension(final Object obj) {
280: return getDimension(obj, getDefaultLocale());
281: }
282:
283: public Dimension getDimension(final Object obj, final Locale locale) {
284: Object result = get(obj, locale);
285: return (result instanceof Dimension) ? (Dimension) result
286: : null;
287: }
288:
289: public Font getFont(final Object obj) {
290: return getFont(obj, getDefaultLocale());
291: }
292:
293: public Font getFont(final Object obj, final Locale locale) {
294: Object result = get(obj, locale);
295: return (result instanceof Font) ? (Font) result : null;
296: }
297:
298: public Icon getIcon(final Object obj) {
299: return getIcon(obj, getDefaultLocale());
300: }
301:
302: public Icon getIcon(final Object obj, final Locale locale) {
303: Object result = get(obj, locale);
304: return (result instanceof Icon) ? (Icon) result : null;
305: }
306:
307: public Insets getInsets(final Object obj) {
308: return getInsets(obj, getDefaultLocale());
309: }
310:
311: public Insets getInsets(final Object obj, final Locale locale) {
312: Object result = get(obj, locale);
313: return (result instanceof Insets) ? (Insets) result : null;
314: }
315:
316: public int getInt(final Object obj) {
317: return getInt(obj, getDefaultLocale());
318: }
319:
320: public int getInt(final Object obj, final Locale locale) {
321: Object result = get(obj, locale);
322: return (result instanceof Integer) ? ((Integer) result)
323: .intValue() : 0;
324: }
325:
326: public String getString(final Object obj) {
327: return getString(obj, getDefaultLocale());
328: }
329:
330: public String getString(final Object obj, final Locale locale) {
331: Object result = get(obj, locale);
332: return (result instanceof String) ? (String) result : null;
333: }
334:
335: public ComponentUI getUI(final JComponent comp) {
336: try {
337: String classID = comp.getUIClassID();
338: String fullClassName = (String) get(classID);
339: if (fullClassName == null) {
340: getUIError(Messages.getString("swing.err.0D", classID)); //$NON-NLS-1$
341: return null;
342: }
343: Class uiClass = (Class) get(fullClassName);
344: Method method = null;
345: if (uiClass == null) {
346: uiClass = getUIClass(classID, comp.getClass()
347: .getClassLoader());
348: method = getCreateUIMethodPriveledged(uiClass);
349:
350: put(fullClassName, uiClass);
351: put(uiClass, method);
352: } else {
353: method = (Method) get(uiClass);
354: }
355: return (ComponentUI) method.invoke(null,
356: new Object[] { comp });
357: } catch (final Exception e) {
358: StringWriter writer = new StringWriter();
359: e.printStackTrace(new PrintWriter(writer));
360: getUIError(writer.toString());
361: return null;
362: }
363: }
364:
365: private Method getCreateUIMethodPriveledged(final Class uiClass) {
366: return (Method) AccessController
367: .doPrivileged(new PrivilegedAction() {
368: public Object run() {
369: try {
370: return uiClass.getMethod(
371: CREATE_UI_METHOD_NAME,
372: new Class[] { JComponent.class });
373: } catch (Exception e) {
374: return null;
375: }
376: }
377: });
378: }
379:
380: public Class<? extends javax.swing.plaf.ComponentUI> getUIClass(
381: final String name) {
382: return getUIClass(name, null);
383: }
384:
385: public Class<? extends javax.swing.plaf.ComponentUI> getUIClass(
386: final String name, final ClassLoader classLoader) {
387: try {
388: if (classLoader == null) {
389: return (Class<? extends javax.swing.plaf.ComponentUI>) Class
390: .forName((String) get(name), true, Thread
391: .currentThread()
392: .getContextClassLoader());
393: } else {
394: return (Class<? extends javax.swing.plaf.ComponentUI>) classLoader
395: .loadClass((String) get(name));
396: }
397: } catch (final ClassNotFoundException e) {
398: StringWriter writer = new StringWriter();
399: e.printStackTrace(new PrintWriter(writer));
400: getUIError(writer.toString());
401: }
402:
403: return null;
404: }
405:
406: public Object put(final Object key, final Object value) {
407: Object previousValue = super .get(key);
408: if (value == null) {
409: super .remove(key);
410: firePropertyChange(key.toString(), previousValue, value);
411: } else if (!value.equals(previousValue)) {
412: super .put(key, value);
413: firePropertyChange(key.toString(), previousValue, value);
414: }
415:
416: return previousValue;
417: }
418:
419: public void putDefaults(final Object[] array) {
420: for (int i = 0; i < array.length; i += 2) {
421: if (array[i + 1] != null) {
422: super .put(array[i], array[i + 1]);
423: }
424: }
425:
426: firePropertyChange("UIDefaults", null, null);
427: }
428:
429: public void setDefaultLocale(final Locale locale) {
430: this .defaultLocale = locale;
431: }
432:
433: protected void firePropertyChange(final String propertyName,
434: final Object oldValue, final Object newValue) {
435: propertyChangeSupport.firePropertyChange(propertyName,
436: oldValue, newValue);
437: }
438:
439: protected void getUIError(final String message) {
440: System.err.println(Messages.getString("swing.err.06", message)); //$NON-NLS-1$
441: }
442:
443: private Object getFromResourceBundles(final Object key,
444: final Locale locale) {
445: if (key == null || !(key instanceof String)) {
446: return null;
447: }
448:
449: String keyAsString = (String) key;
450: if (getDefaultLocale().equals(locale)) {
451: for (int i = resourceBundles.size() - 1; i >= 0; i--) {
452: ResourceBundle bundle = (ResourceBundle) resourceBundles
453: .get(i);
454: try {
455: return bundle.getObject(keyAsString);
456: } catch (final MissingResourceException mre) {
457: }
458: }
459: } else {
460: for (int i = resourceBundles.size() - 1; i >= 0; i--) {
461: ResourceBundle bundle = (ResourceBundle) resourceBundles
462: .get(i);
463: try {
464: return ResourceBundle.getBundle(
465: bundle.getClass().getName(), locale)
466: .getObject(keyAsString);
467: } catch (final MissingResourceException mre) {
468: }
469: }
470: }
471:
472: return null;
473: }
474: }
|