001: package jaxx.runtime;
002:
003: import java.awt.*;
004: import java.io.*;
005: import java.lang.ref.*;
006: import java.lang.reflect.*;
007: import java.util.*;
008: import java.util.List;
009: import java.util.zip.*;
010: import javax.swing.*;
011:
012: public class Util {
013: // Maps root objects to lists of event listeners
014: private static Map/*<Object, List<EventListenerDescriptor>>*/eventListeners = new WeakHashMap/*<Object, List<EventListenerDescriptor>>*/();
015: private static Map/*<Object, List<DataBindingUpdateListener>>*/dataBindingUpdateListeners = new WeakHashMap/*<Object, List<EventListenerDescriptor>>*/();
016:
017: private static class EventListenerDescriptor {
018: Class listenerClass;
019: String listenerMethodName;
020: String methodName;
021: Object eventListener;
022: }
023:
024: /** Decodes the serialized representation of a JAXXObjectDescriptor. The string must be a byte-to-character mapping
025: * of the binary serialization data for a JAXXObjectDescriptor. See the comments in JAXXCompiler.createJAXXObjectDescriptorField
026: * for the rationale behind this (admittedly ugly) approach.
027: */
028: public static JAXXObjectDescriptor decodeJAXXObjectDescriptor(
029: String descriptor) {
030: try {
031: byte[] data = new byte[descriptor.length()];
032: descriptor.getBytes(0, descriptor.length(), data, 0); // copy low-order bytes into the array. The high-order bytes should all be zero.
033: ObjectInputStream in = new ObjectInputStream(
034: new ByteArrayInputStream(data));
035: return (JAXXObjectDescriptor) in.readObject();
036: } catch (IOException e) {
037: throw new RuntimeException(
038: "Internal error: can't-happen error", e);
039: } catch (ClassNotFoundException e) {
040: throw new RuntimeException(
041: "Internal error: can't-happen error", e);
042: }
043: }
044:
045: public static JAXXObjectDescriptor decodeCompressedJAXXObjectDescriptor(
046: String descriptor) {
047: try {
048: byte[] data = new byte[descriptor.length()];
049: descriptor.getBytes(0, descriptor.length(), data, 0); // copy low-order bytes into the array. The high-order bytes should all be zero.
050: ObjectInputStream in = new ObjectInputStream(
051: new GZIPInputStream(new ByteArrayInputStream(data)));
052: return (JAXXObjectDescriptor) in.readObject();
053: } catch (IOException e) {
054: throw new RuntimeException(
055: "Internal error: can't-happen error", e);
056: } catch (ClassNotFoundException e) {
057: throw new RuntimeException(
058: "Internal error: can't-happen error", e);
059: }
060: }
061:
062: public static Object getEventListener(Class listenerClass,
063: final String listenerMethodName,
064: final Object methodContainer, final String methodName) {
065: WeakReference ref = (WeakReference) eventListeners
066: .get(methodContainer);
067: List/*<EventListenerDescriptor>*/descriptors = ref != null ? (List) ref
068: .get()
069: : null;
070: if (descriptors == null) {
071: descriptors = new ArrayList/*<EventListenerDescriptor>*/();
072: eventListeners.put(methodContainer, new WeakReference(
073: descriptors));
074: } else {
075: Iterator/*<EventListenerDescriptor>*/iter = descriptors
076: .iterator();
077: while (iter.hasNext()) {
078: EventListenerDescriptor descriptor = (EventListenerDescriptor) iter
079: .next();
080: if (listenerClass == descriptor.listenerClass
081: && (listenerMethodName == null ? descriptor.listenerMethodName == null
082: : listenerMethodName
083: .equals(descriptor.listenerMethodName))
084: && methodName.equals(descriptor.methodName))
085: return descriptor.eventListener;
086: }
087: }
088:
089: // else we need to create a new listener
090: final EventListenerDescriptor descriptor = new EventListenerDescriptor();
091: descriptor.listenerClass = listenerClass;
092: descriptor.listenerMethodName = listenerMethodName;
093: descriptor.methodName = methodName;
094: try {
095: final List/*<Method>*/listenerMethods = Arrays
096: .asList(listenerClass.getMethods());
097: Method listenerMethod = null;
098: if (listenerMethodName != null) {
099: for (int i = 0; i < listenerMethods.size(); i++) {
100: if (((Method) listenerMethods.get(i)).getName()
101: .equals(listenerMethodName)) {
102: listenerMethod = (Method) listenerMethods
103: .get(i);
104: break;
105: }
106: }
107: }
108: if (listenerMethodName != null && listenerMethod == null)
109: throw new IllegalArgumentException("no method named "
110: + listenerMethodName + " found in class "
111: + listenerClass.getName());
112: Class[] parameterTypes = ((Method) listenerMethods.get(0))
113: .getParameterTypes();
114: Class methodContainerClass = methodContainer.getClass();
115: final Method targetMethod = methodContainerClass.getMethod(
116: methodName, parameterTypes);
117: descriptor.eventListener = Proxy.newProxyInstance(
118: listenerClass.getClassLoader(),
119: new Class[] { listenerClass },
120: new InvocationHandler() {
121: public Object invoke(Object proxy,
122: Method method, Object[] args) {
123: String methodName = method.getName();
124: if ((listenerMethodName == null && listenerMethods
125: .contains(method))
126: || methodName
127: .equals(listenerMethodName)) {
128: try {
129: return targetMethod.invoke(
130: methodContainer, args);
131: } catch (IllegalAccessException e) {
132: throw new RuntimeException(e);
133: } catch (InvocationTargetException e) {
134: throw new RuntimeException(e);
135: }
136: } else if (methodName.equals("toString"))
137: return toString();
138: else if (methodName.equals("equals"))
139: return Boolean
140: .valueOf(descriptor.eventListener == args[0]);
141: else if (methodName.equals("hashCode"))
142: return new Integer(hashCode());
143: else
144: return null;
145: }
146: });
147: descriptors.add(descriptor);
148: return descriptor.eventListener;
149: } catch (NoSuchMethodException e) {
150: throw new RuntimeException(e);
151: }
152: }
153:
154: public static Object getEventListener(Class listenerClass,
155: final Object methodContainer, final String methodName) {
156: return getEventListener(listenerClass, null, methodContainer,
157: methodName);
158: }
159:
160: public static DataBindingUpdateListener getDataBindingUpdateListener(
161: JAXXObject object, String bindingName) {
162: WeakReference/*<List<DataBindingUpdateListener>*/ref = ((WeakReference) dataBindingUpdateListeners
163: .get(object));
164: List/*<DataBindingUpdateListener>*/listeners = ref != null ? (List) ref
165: .get()
166: : null;
167: if (listeners == null) {
168: listeners = new ArrayList/*<EventListenerDescriptor>*/();
169: dataBindingUpdateListeners.put(object, new WeakReference(
170: listeners));
171: } else {
172: Iterator/*<DataBindingUpdateListener>*/iter = listeners
173: .iterator();
174: while (iter.hasNext()) {
175: DataBindingUpdateListener listener = (DataBindingUpdateListener) iter
176: .next();
177: if (bindingName.equals(listener.getBindingName()))
178: return listener;
179: }
180: }
181: DataBindingUpdateListener listener = new DataBindingUpdateListener(
182: object, bindingName);
183: listeners.add(listener);
184: return listener;
185: }
186:
187: public static void setComponentWidth(Component component, int width) {
188: component.setSize(width, component.getHeight());
189: if (component instanceof JComponent) {
190: JComponent jcomponent = (JComponent) component;
191: jcomponent.setPreferredSize(new Dimension(width, jcomponent
192: .getPreferredSize().height));
193: jcomponent.setMinimumSize(new Dimension(width, jcomponent
194: .getPreferredSize().height));
195: if (jcomponent.isDisplayable())
196: jcomponent.revalidate();
197: }
198: }
199:
200: public static void setComponentHeight(Component component,
201: int height) {
202: component.setSize(component.getWidth(), height);
203: if (component instanceof JComponent) {
204: JComponent jcomponent = (JComponent) component;
205: jcomponent.setPreferredSize(new Dimension(jcomponent
206: .getPreferredSize().width, height));
207: jcomponent.setMinimumSize(new Dimension(jcomponent
208: .getPreferredSize().width, height));
209: if (jcomponent.isDisplayable())
210: jcomponent.revalidate();
211: }
212: }
213:
214: public static boolean assignment(boolean value, String name,
215: JAXXObject src) {
216: src.firePropertyChange(name.trim(), null, "dummy value");
217: return value;
218: }
219:
220: public static byte assignment(byte value, String name,
221: JAXXObject src) {
222: src.firePropertyChange(name.trim(), null, "dummy value");
223: return value;
224: }
225:
226: public static short assignment(short value, String name,
227: JAXXObject src) {
228: src.firePropertyChange(name.trim(), null, "dummy value");
229: return value;
230: }
231:
232: public static int assignment(int value, String name, JAXXObject src) {
233: src.firePropertyChange(name.trim(), null, "dummy value");
234: return value;
235: }
236:
237: public static long assignment(long value, String name,
238: JAXXObject src) {
239: src.firePropertyChange(name.trim(), null, "dummy value");
240: return value;
241: }
242:
243: public static float assignment(float value, String name,
244: JAXXObject src) {
245: src.firePropertyChange(name.trim(), null, "dummy value");
246: return value;
247: }
248:
249: public static double assignment(double value, String name,
250: JAXXObject src) {
251: src.firePropertyChange(name.trim(), null, "dummy value");
252: return value;
253: }
254:
255: public static char assignment(char value, String name,
256: JAXXObject src) {
257: src.firePropertyChange(name.trim(), null, "dummy value");
258: return value;
259: }
260:
261: public static java.lang.Object assignment(java.lang.Object value,
262: String name, JAXXObject src) {
263: src.firePropertyChange(name.trim(), null, "dummy value");
264: return value;
265: }
266: }
|