/*
 * Copyright (c) 2003, 2006, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

package com.sun.beans;

import com.sun.beans.finder.ClassFinder;

import java.beans.*;
import java.util.*;
import java.io.StringReader;

import org.xml.sax.*;

import static java.util.Locale.ENGLISH;

WARNING: This class is an implementation detail and only meant for use within the core platform. You should NOT depend upon it! This API may change drastically between dot dot release, and it may even be removed.
Author:Philip Milne
See Also:
Since:1.4
/** * <b>WARNING</b>: This class is an implementation detail and only meant * for use within the core platform. You should NOT depend upon it! This * API may change drastically between dot dot release, and it may even be * removed. * * @see java.beans.XMLEncoder * @see java.io.ObjectInputStream * * @since 1.4 * * @author Philip Milne */
public class ObjectHandler extends HandlerBase { public static Class typeNameToClass(String typeName) { typeName = typeName.intern(); if (typeName == "boolean") return Boolean.class; if (typeName == "byte") return Byte.class; if (typeName == "char") return Character.class; if (typeName == "short") return Short.class; if (typeName == "int") return Integer.class; if (typeName == "long") return Long.class; if (typeName == "float") return Float.class; if (typeName == "double") return Double.class; if (typeName == "void") return Void.class; return null; } public static Class typeNameToPrimitiveClass(String typeName) { typeName = typeName.intern(); if (typeName == "boolean") return boolean.class; if (typeName == "byte") return byte.class; if (typeName == "char") return char.class; if (typeName == "short") return short.class; if (typeName == "int") return int.class; if (typeName == "long") return long.class; if (typeName == "float") return float.class; if (typeName == "double") return double.class; if (typeName == "void") return void.class; return null; }
Returns the Class object associated with the class or interface with the given string name, using the default class loader.
Params:
  • name – fully qualified name of the desired class
  • cl – class loader from which the class must be loaded
Throws:
Returns:class object representing the desired class
Deprecated:As of JDK version 7, replaced by ClassFinder.resolveClass(String).
/** * Returns the <code>Class</code> object associated with * the class or interface with the given string name, * using the default class loader. * * @param name fully qualified name of the desired class * @param cl class loader from which the class must be loaded * @return class object representing the desired class * * @exception ClassNotFoundException if the class cannot be located * by the specified class loader * * @deprecated As of JDK version 7, replaced by * {@link ClassFinder#resolveClass(String)}. */
@Deprecated public static Class classForName(String name) throws ClassNotFoundException { return ClassFinder.resolveClass(name); }
Returns the Class object associated with the class or interface with the given string name, using the given class loader.
Params:
  • name – fully qualified name of the desired class
  • cl – class loader from which the class must be loaded
Throws:
Returns:class object representing the desired class
Deprecated:As of JDK version 7, replaced by ClassFinder.resolveClass(String, ClassLoader).
/** * Returns the <code>Class</code> object associated with * the class or interface with the given string name, * using the given class loader. * * @param name fully qualified name of the desired class * @param cl class loader from which the class must be loaded * @return class object representing the desired class * * @exception ClassNotFoundException if the class cannot be located * by the specified class loader * * @deprecated As of JDK version 7, replaced by * {@link ClassFinder#resolveClass(String,ClassLoader)}. */
@Deprecated public static Class classForName(String name, ClassLoader cl) throws ClassNotFoundException { return ClassFinder.resolveClass(name, cl); } private Hashtable environment; private Vector expStack; private StringBuffer chars; private XMLDecoder is; private ClassLoader ldr; private int itemsRead = 0; private boolean isString; public ObjectHandler() { environment = new Hashtable(); expStack = new Vector(); chars = new StringBuffer(); } public ObjectHandler(XMLDecoder is) { this(); this.is = is; } /* loader can be null */ public ObjectHandler(XMLDecoder is, ClassLoader loader) { this(is); this.ldr = loader; } public void reset() { expStack.clear(); chars.setLength(0); MutableExpression e = new MutableExpression(); e.setTarget(classForName2("java.lang.Object")); e.setMethodName("null"); expStack.add(e); }
Disables any external entities.
/** * Disables any external entities. */
public InputSource resolveEntity(String publicId, String systemId) { return new InputSource(new StringReader("")); } private Object getValue(Expression exp) { try { return exp.getValue(); } catch (Exception e) { if (is != null) { is.getExceptionListener().exceptionThrown(e); } return null; } } private void addArg(Object arg) { lastExp().addArg(arg); } private Object pop(Vector v) { int last = v.size()-1; Object result = v.get(last); v.remove(last); return result; } private Object eval() { return getValue(lastExp()); } private MutableExpression lastExp() { return (MutableExpression)expStack.lastElement(); } public Object dequeueResult() { Object[] results = lastExp().getArguments(); return results[itemsRead++]; } private boolean isPrimitive(String name) { return name != "void" && typeNameToClass(name) != null; } private void simulateException(String message) { Exception e = new Exception(message); e.fillInStackTrace(); if (is != null) { is.getExceptionListener().exceptionThrown(e); } } private Class classForName2(String name) { try { return ClassFinder.resolveClass(name, this.ldr); } catch (ClassNotFoundException e) { if (is != null) { is.getExceptionListener().exceptionThrown(e); } } return null; } private HashMap getAttributes(AttributeList attrs) { HashMap attributes = new HashMap(); if (attrs != null && attrs.getLength() > 0) { for(int i = 0; i < attrs.getLength(); i++) { attributes.put(attrs.getName(i), attrs.getValue(i)); } } return attributes; } public void startElement(String name, AttributeList attrs) throws SAXException { name = name.intern(); // Xerces parser does not supply unique tag names. if (this.isString) { parseCharCode(name, getAttributes(attrs)); return; } chars.setLength(0); HashMap attributes = getAttributes(attrs); MutableExpression e = new MutableExpression(); // Target String className = (String)attributes.get("class"); if (className != null) { e.setTarget(classForName2(className)); } // Property Object property = attributes.get("property"); String index = (String)attributes.get("index"); if (index != null) { property = new Integer(index); e.addArg(property); } e.setProperty(property); // Method String methodName = (String)attributes.get("method"); if (methodName == null && property == null) { methodName = "new"; } e.setMethodName(methodName); // Tags if (name == "string") { e.setTarget(String.class); e.setMethodName("new"); this.isString = true; } else if (isPrimitive(name)){ Class wrapper = typeNameToClass(name); e.setTarget(wrapper); e.setMethodName("new"); parseCharCode(name, attributes); } else if (name == "class") { e.setTarget(Class.class); e.setMethodName("forName"); } else if (name == "null") { // Create an arbitrary expression that has a value of null - for // consistency. e.setTarget(Object.class); e.setMethodName("getSuperclass"); e.setValue(null); } else if (name == "void") { if (e.getTarget() == null) { // this check is for "void class="foo" method= ..." e.setTarget(eval()); } } else if (name == "array") { // The class attribute means sub-type for arrays. String subtypeName = (String)attributes.get("class"); Class subtype = (subtypeName == null) ? Object.class : classForName2(subtypeName); String length = (String)attributes.get("length"); if (length != null) { e.setTarget(java.lang.reflect.Array.class); e.addArg(subtype); e.addArg(new Integer(length)); } else { Class arrayClass = java.lang.reflect.Array.newInstance(subtype, 0).getClass(); e.setTarget(arrayClass); } } else if (name == "java") { e.setValue(is); // The outermost scope is the stream itself. } else if (name == "object") { } else { simulateException("Unrecognized opening tag: " + name + " " + attrsToString(attrs)); return; } // ids String idName = (String)attributes.get("id"); if (idName != null) { environment.put(idName, e); } // idrefs String idrefName = (String)attributes.get("idref"); if (idrefName != null) { e.setValue(lookup(idrefName)); } // fields String fieldName = (String)attributes.get("field"); if (fieldName != null) { e.setValue(getFieldValue(e.getTarget(), fieldName)); } expStack.add(e); } private Object getFieldValue(Object target, String fieldName) { try { Class type = target.getClass(); if (type == Class.class) { type = (Class)target; } java.lang.reflect.Field f = sun.reflect.misc.FieldUtil.getField(type, fieldName); return f.get(target); } catch (Exception e) { if (is != null) { is.getExceptionListener().exceptionThrown(e); } return null; } } private String attrsToString(AttributeList attrs) { StringBuffer b = new StringBuffer(); for (int i = 0; i < attrs.getLength (); i++) { b.append(attrs.getName(i)+"=\""+attrs.getValue(i)+"\" "); } return b.toString(); } public void characters(char buf [], int offset, int len) throws SAXException { chars.append(new String(buf, offset, len)); } private void parseCharCode(String name, Map map) { if (name == "char") { String value = (String) map.get("code"); if (value != null) { this.chars.append(parseIntAsChar(value)); } } } private static char parseIntAsChar(String data) { try { int i = data.startsWith("#") ? Integer.parseInt(data.substring(1), 16) : Integer.parseInt(data); // be convinced, that valid character code is read char ch = (char) i; if (ch == i) return ch; throw new IllegalArgumentException("Wrong character code: '" + data + "'"); } catch (NumberFormatException exception) { throw new IllegalArgumentException("Wrong character code: '" + data + "'", exception); } } public Object lookup(String s) { Expression e = (Expression)environment.get(s); if (e == null) { simulateException("Unbound variable: " + s); } return getValue(e); } public void register(String id, Object value) { Expression e = new MutableExpression(); e.setValue(value); environment.put(id, e); } public void endElement(String name) throws SAXException { name = name.intern(); // Xerces parser does not supply unique tag names. if (name == "string") { this.isString = false; } else if (this.isString) { return; } if (name == "java") { return; } if (isPrimitive(name) || name == "string" || name == "class") { addArg(chars.toString()); } if (name == "object" || name == "array" || name == "void" || isPrimitive(name) || name == "string" || name == "class" || name == "null") { Expression e = (Expression)pop(expStack); Object value = getValue(e); if (name != "void") { addArg(value); } } else { simulateException("Unrecognized closing tag: " + name); } } } class MutableExpression extends Expression { private Object target; private String methodName; private Object property; private Vector argV = new Vector(); private String capitalize(String propertyName) { if (propertyName.length() == 0) { return propertyName; } return propertyName.substring(0, 1).toUpperCase(ENGLISH) + propertyName.substring(1); } public MutableExpression() { super(null, null, null); } public Object[] getArguments() { return argV.toArray(); } public String getMethodName() { if (property == null) { return methodName; } int setterArgs = (property instanceof String) ? 1 : 2; String methodName = (argV.size() == setterArgs) ? "set" : "get"; if (property instanceof String) { return methodName + capitalize((String)property); } else { return methodName; } } public void addArg(Object arg) { argV.add(arg); } public void setTarget(Object target) { this.target = target; } public Object getTarget() { return target; } public void setMethodName(String methodName) { this.methodName = methodName; } public void setProperty(Object property) { this.property = property; } public void setValue(Object value) { super.setValue(value); } public Object getValue() throws Exception { return super.getValue(); } }