001: /*
002: * Copyright 2003-2006 Sun Microsystems, Inc. All Rights Reserved.
003: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004: *
005: * This code is free software; you can redistribute it and/or modify it
006: * under the terms of the GNU General Public License version 2 only, as
007: * published by the Free Software Foundation. Sun designates this
008: * particular file as subject to the "Classpath" exception as provided
009: * by Sun in the LICENSE file that accompanied this code.
010: *
011: * This code is distributed in the hope that it will be useful, but WITHOUT
012: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
014: * version 2 for more details (a copy is included in the LICENSE file that
015: * accompanied this code).
016: *
017: * You should have received a copy of the GNU General Public License version
018: * 2 along with this work; if not, write to the Free Software Foundation,
019: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020: *
021: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022: * CA 95054 USA or visit www.sun.com if you need additional information or
023: * have any questions.
024: */
025:
026: package com.sun.beans;
027:
028: import com.sun.beans.finder.ClassFinder;
029:
030: import java.beans.*;
031: import java.util.*;
032:
033: import org.xml.sax.*;
034:
035: import static java.util.Locale.ENGLISH;
036:
037: /**
038: * <b>WARNING</b>: This class is an implementation detail and only meant
039: * for use within the core platform. You should NOT depend upon it! This
040: * API may change drastically between dot dot release, and it may even be
041: * removed.
042: *
043: * @see java.beans.XMLEncoder
044: * @see java.io.ObjectInputStream
045: *
046: * @since 1.4
047: *
048: * @version 1.5 11/20/00
049: * @author Philip Milne
050: */
051: public class ObjectHandler extends HandlerBase {
052:
053: public static Class typeNameToClass(String typeName) {
054: typeName = typeName.intern();
055: if (typeName == "boolean")
056: return Boolean.class;
057: if (typeName == "byte")
058: return Byte.class;
059: if (typeName == "char")
060: return Character.class;
061: if (typeName == "short")
062: return Short.class;
063: if (typeName == "int")
064: return Integer.class;
065: if (typeName == "long")
066: return Long.class;
067: if (typeName == "float")
068: return Float.class;
069: if (typeName == "double")
070: return Double.class;
071: if (typeName == "void")
072: return Void.class;
073: return null;
074: }
075:
076: public static Class typeNameToPrimitiveClass(String typeName) {
077: typeName = typeName.intern();
078: if (typeName == "boolean")
079: return boolean.class;
080: if (typeName == "byte")
081: return byte.class;
082: if (typeName == "char")
083: return char.class;
084: if (typeName == "short")
085: return short.class;
086: if (typeName == "int")
087: return int.class;
088: if (typeName == "long")
089: return long.class;
090: if (typeName == "float")
091: return float.class;
092: if (typeName == "double")
093: return double.class;
094: if (typeName == "void")
095: return void.class;
096: return null;
097: }
098:
099: /**
100: * Returns the <code>Class</code> object associated with
101: * the class or interface with the given string name,
102: * using the default class loader.
103: *
104: * @param name fully qualified name of the desired class
105: * @param cl class loader from which the class must be loaded
106: * @return class object representing the desired class
107: *
108: * @exception ClassNotFoundException if the class cannot be located
109: * by the specified class loader
110: *
111: * @deprecated As of JDK version 7, replaced by
112: * {@link ClassFinder#resolveClass(String)}.
113: */
114: @Deprecated
115: public static Class classForName(String name)
116: throws ClassNotFoundException {
117: return ClassFinder.resolveClass(name);
118: }
119:
120: /**
121: * Returns the <code>Class</code> object associated with
122: * the class or interface with the given string name,
123: * using the given class loader.
124: *
125: * @param name fully qualified name of the desired class
126: * @param cl class loader from which the class must be loaded
127: * @return class object representing the desired class
128: *
129: * @exception ClassNotFoundException if the class cannot be located
130: * by the specified class loader
131: *
132: * @deprecated As of JDK version 7, replaced by
133: * {@link ClassFinder#resolveClass(String,ClassLoader)}.
134: */
135: @Deprecated
136: public static Class classForName(String name, ClassLoader cl)
137: throws ClassNotFoundException {
138: return ClassFinder.resolveClass(name, cl);
139: }
140:
141: private Hashtable environment;
142: private Vector expStack;
143: private StringBuffer chars;
144: private XMLDecoder is;
145: private ClassLoader ldr;
146: private int itemsRead = 0;
147: private boolean isString;
148:
149: public ObjectHandler() {
150: environment = new Hashtable();
151: expStack = new Vector();
152: chars = new StringBuffer();
153: }
154:
155: public ObjectHandler(XMLDecoder is) {
156: this ();
157: this .is = is;
158: }
159:
160: /* loader can be null */
161: public ObjectHandler(XMLDecoder is, ClassLoader loader) {
162: this (is);
163: this .ldr = loader;
164: }
165:
166: public void reset() {
167: expStack.clear();
168: chars.setLength(0);
169: MutableExpression e = new MutableExpression();
170: e.setTarget(classForName2("java.lang.Object"));
171: e.setMethodName("null");
172: expStack.add(e);
173: }
174:
175: private Object getValue(Expression exp) {
176: try {
177: return exp.getValue();
178: } catch (Exception e) {
179: if (is != null) {
180: is.getExceptionListener().exceptionThrown(e);
181: }
182: return null;
183: }
184: }
185:
186: private void addArg(Object arg) {
187: lastExp().addArg(arg);
188: }
189:
190: private Object pop(Vector v) {
191: int last = v.size() - 1;
192: Object result = v.get(last);
193: v.remove(last);
194: return result;
195: }
196:
197: private Object eval() {
198: return getValue(lastExp());
199: }
200:
201: private MutableExpression lastExp() {
202: return (MutableExpression) expStack.lastElement();
203: }
204:
205: public Object dequeueResult() {
206: Object[] results = lastExp().getArguments();
207: return results[itemsRead++];
208: }
209:
210: private boolean isPrimitive(String name) {
211: return name != "void" && typeNameToClass(name) != null;
212: }
213:
214: private void simulateException(String message) {
215: Exception e = new Exception(message);
216: e.fillInStackTrace();
217: if (is != null) {
218: is.getExceptionListener().exceptionThrown(e);
219: }
220: }
221:
222: private Class classForName2(String name) {
223: try {
224: return ClassFinder.resolveClass(name, this .ldr);
225: } catch (ClassNotFoundException e) {
226: if (is != null) {
227: is.getExceptionListener().exceptionThrown(e);
228: }
229: }
230: return null;
231: }
232:
233: private HashMap getAttributes(AttributeList attrs) {
234: HashMap attributes = new HashMap();
235: if (attrs != null && attrs.getLength() > 0) {
236: for (int i = 0; i < attrs.getLength(); i++) {
237: attributes.put(attrs.getName(i), attrs.getValue(i));
238: }
239: }
240: return attributes;
241: }
242:
243: public void startElement(String name, AttributeList attrs)
244: throws SAXException {
245: name = name.intern(); // Xerces parser does not supply unique tag names.
246: if (this .isString) {
247: parseCharCode(name, getAttributes(attrs));
248: return;
249: }
250: chars.setLength(0);
251:
252: HashMap attributes = getAttributes(attrs);
253: MutableExpression e = new MutableExpression();
254:
255: // Target
256: String className = (String) attributes.get("class");
257: if (className != null) {
258: e.setTarget(classForName2(className));
259: }
260:
261: // Property
262: Object property = attributes.get("property");
263: String index = (String) attributes.get("index");
264: if (index != null) {
265: property = new Integer(index);
266: e.addArg(property);
267: }
268: e.setProperty(property);
269:
270: // Method
271: String methodName = (String) attributes.get("method");
272: if (methodName == null && property == null) {
273: methodName = "new";
274: }
275: e.setMethodName(methodName);
276:
277: // Tags
278: if (name == "string") {
279: e.setTarget(String.class);
280: e.setMethodName("new");
281: this .isString = true;
282: } else if (isPrimitive(name)) {
283: Class wrapper = typeNameToClass(name);
284: e.setTarget(wrapper);
285: e.setMethodName("new");
286: parseCharCode(name, attributes);
287: } else if (name == "class") {
288: e.setTarget(Class.class);
289: e.setMethodName("forName");
290: } else if (name == "null") {
291: // Create an arbitrary expression that has a value of null - for
292: // consistency.
293: e.setTarget(Object.class);
294: e.setMethodName("getSuperclass");
295: e.setValue(null);
296: } else if (name == "void") {
297: if (e.getTarget() == null) { // this check is for "void class="foo" method= ..."
298: e.setTarget(eval());
299: }
300: } else if (name == "array") {
301: // The class attribute means sub-type for arrays.
302: String subtypeName = (String) attributes.get("class");
303: Class subtype = (subtypeName == null) ? Object.class
304: : classForName2(subtypeName);
305: String length = (String) attributes.get("length");
306: if (length != null) {
307: e.setTarget(java.lang.reflect.Array.class);
308: e.addArg(subtype);
309: e.addArg(new Integer(length));
310: } else {
311: Class arrayClass = java.lang.reflect.Array.newInstance(
312: subtype, 0).getClass();
313: e.setTarget(arrayClass);
314: }
315: } else if (name == "java") {
316: e.setValue(is); // The outermost scope is the stream itself.
317: } else if (name == "object") {
318: } else {
319: simulateException("Unrecognized opening tag: " + name + " "
320: + attrsToString(attrs));
321: return;
322: }
323:
324: // ids
325: String idName = (String) attributes.get("id");
326: if (idName != null) {
327: environment.put(idName, e);
328: }
329:
330: // idrefs
331: String idrefName = (String) attributes.get("idref");
332: if (idrefName != null) {
333: e.setValue(lookup(idrefName));
334: }
335:
336: // fields
337: String fieldName = (String) attributes.get("field");
338: if (fieldName != null) {
339: e.setValue(getFieldValue(e.getTarget(), fieldName));
340: }
341: expStack.add(e);
342: }
343:
344: private Object getFieldValue(Object target, String fieldName) {
345: try {
346: Class type = target.getClass();
347: if (type == Class.class) {
348: type = (Class) target;
349: }
350: java.lang.reflect.Field f = sun.reflect.misc.FieldUtil
351: .getField(type, fieldName);
352: return f.get(target);
353: } catch (Exception e) {
354: if (is != null) {
355: is.getExceptionListener().exceptionThrown(e);
356: }
357: return null;
358: }
359: }
360:
361: private String attrsToString(AttributeList attrs) {
362: StringBuffer b = new StringBuffer();
363: for (int i = 0; i < attrs.getLength(); i++) {
364: b.append(attrs.getName(i) + "=\"" + attrs.getValue(i)
365: + "\" ");
366: }
367: return b.toString();
368: }
369:
370: public void characters(char buf[], int offset, int len)
371: throws SAXException {
372: chars.append(new String(buf, offset, len));
373: }
374:
375: private void parseCharCode(String name, Map map) {
376: if (name == "char") {
377: String value = (String) map.get("code");
378: if (value != null) {
379: int code = Integer.decode(value);
380: for (char ch : Character.toChars(code)) {
381: this .chars.append(ch);
382: }
383: }
384: }
385: }
386:
387: public Object lookup(String s) {
388: Expression e = (Expression) environment.get(s);
389: if (e == null) {
390: simulateException("Unbound variable: " + s);
391: }
392: return getValue(e);
393: }
394:
395: public void register(String id, Object value) {
396: Expression e = new MutableExpression();
397: e.setValue(value);
398: environment.put(id, e);
399: }
400:
401: public void endElement(String name) throws SAXException {
402: name = name.intern(); // Xerces parser does not supply unique tag names.
403: if (name == "string") {
404: this .isString = false;
405: } else if (this .isString) {
406: return;
407: }
408: if (name == "java") {
409: return;
410: }
411: if (isPrimitive(name) || name == "string" || name == "class") {
412: addArg(chars.toString());
413: }
414: if (name == "object" || name == "array" || name == "void"
415: || isPrimitive(name) || name == "string"
416: || name == "class" || name == "null") {
417: Expression e = (Expression) pop(expStack);
418: Object value = getValue(e);
419: if (name != "void") {
420: addArg(value);
421: }
422: } else {
423: simulateException("Unrecognized closing tag: " + name);
424: }
425: }
426: }
427:
428: class MutableExpression extends Expression {
429: private Object target;
430: private String methodName;
431:
432: private Object property;
433: private Vector argV = new Vector();
434:
435: private String capitalize(String propertyName) {
436: if (propertyName.length() == 0) {
437: return propertyName;
438: }
439: return propertyName.substring(0, 1).toUpperCase(ENGLISH)
440: + propertyName.substring(1);
441: }
442:
443: public MutableExpression() {
444: super (null, null, null);
445: }
446:
447: public Object[] getArguments() {
448: return argV.toArray();
449: }
450:
451: public String getMethodName() {
452: if (property == null) {
453: return methodName;
454: }
455: int setterArgs = (property instanceof String) ? 1 : 2;
456: String methodName = (argV.size() == setterArgs) ? "set" : "get";
457: if (property instanceof String) {
458: return methodName + capitalize((String) property);
459: } else {
460: return methodName;
461: }
462: }
463:
464: public void addArg(Object arg) {
465: argV.add(arg);
466: }
467:
468: public void setTarget(Object target) {
469: this .target = target;
470: }
471:
472: public Object getTarget() {
473: return target;
474: }
475:
476: public void setMethodName(String methodName) {
477: this .methodName = methodName;
478: }
479:
480: public void setProperty(Object property) {
481: this .property = property;
482: }
483:
484: public void setValue(Object value) {
485: super .setValue(value);
486: }
487:
488: public Object getValue() throws Exception {
489: return super.getValue();
490: }
491: }
|