jdk/src/share/classes/com/sun/beans/ObjectHandler.java
changeset 1853 63c1129add13
parent 1810 54dffad0bf06
parent 1852 958801d67667
child 1854 3a1f36b2dd3b
equal deleted inserted replaced
1810:54dffad0bf06 1853:63c1129add13
     1 /*
       
     2  * Copyright 2003-2006 Sun Microsystems, Inc.  All Rights Reserved.
       
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
       
     4  *
       
     5  * This code is free software; you can redistribute it and/or modify it
       
     6  * under the terms of the GNU General Public License version 2 only, as
       
     7  * published by the Free Software Foundation.  Sun designates this
       
     8  * particular file as subject to the "Classpath" exception as provided
       
     9  * by Sun in the LICENSE file that accompanied this code.
       
    10  *
       
    11  * This code is distributed in the hope that it will be useful, but WITHOUT
       
    12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
       
    13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
       
    14  * version 2 for more details (a copy is included in the LICENSE file that
       
    15  * accompanied this code).
       
    16  *
       
    17  * You should have received a copy of the GNU General Public License version
       
    18  * 2 along with this work; if not, write to the Free Software Foundation,
       
    19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
       
    20  *
       
    21  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
       
    22  * CA 95054 USA or visit www.sun.com if you need additional information or
       
    23  * have any questions.
       
    24  */
       
    25 
       
    26 package com.sun.beans;
       
    27 
       
    28 import com.sun.beans.finder.ClassFinder;
       
    29 
       
    30 import java.beans.*;
       
    31 import java.util.*;
       
    32 
       
    33 import org.xml.sax.*;
       
    34 
       
    35 import static java.util.Locale.ENGLISH;
       
    36 
       
    37 /**
       
    38  * <b>WARNING</b>: This class is an implementation detail and only meant
       
    39  * for use within the core platform. You should NOT depend upon it! This
       
    40  * API may change drastically between dot dot release, and it may even be
       
    41  * removed.
       
    42  *
       
    43  * @see java.beans.XMLEncoder
       
    44  * @see java.io.ObjectInputStream
       
    45  *
       
    46  * @since 1.4
       
    47  *
       
    48  * @author Philip Milne
       
    49  */
       
    50 public class ObjectHandler extends HandlerBase {
       
    51 
       
    52     public static Class typeNameToClass(String typeName) {
       
    53         typeName = typeName.intern();
       
    54         if (typeName == "boolean") return Boolean.class;
       
    55         if (typeName == "byte") return Byte.class;
       
    56         if (typeName == "char") return Character.class;
       
    57         if (typeName == "short") return Short.class;
       
    58         if (typeName == "int") return Integer.class;
       
    59         if (typeName == "long") return Long.class;
       
    60         if (typeName == "float") return Float.class;
       
    61         if (typeName == "double") return Double.class;
       
    62         if (typeName == "void") return Void.class;
       
    63         return null;
       
    64     }
       
    65 
       
    66     public static Class typeNameToPrimitiveClass(String typeName) {
       
    67         typeName = typeName.intern();
       
    68         if (typeName == "boolean") return boolean.class;
       
    69         if (typeName == "byte") return byte.class;
       
    70         if (typeName == "char") return char.class;
       
    71         if (typeName == "short") return short.class;
       
    72         if (typeName == "int") return int.class;
       
    73         if (typeName == "long") return long.class;
       
    74         if (typeName == "float") return float.class;
       
    75         if (typeName == "double") return double.class;
       
    76         if (typeName == "void") return void.class;
       
    77         return null;
       
    78     }
       
    79 
       
    80     /**
       
    81      * Returns the <code>Class</code> object associated with
       
    82      * the class or interface with the given string name,
       
    83      * using the default class loader.
       
    84      *
       
    85      * @param name  fully qualified name of the desired class
       
    86      * @param cl    class loader from which the class must be loaded
       
    87      * @return class object representing the desired class
       
    88      *
       
    89      * @exception ClassNotFoundException  if the class cannot be located
       
    90      *                                    by the specified class loader
       
    91      *
       
    92      * @deprecated As of JDK version 7, replaced by
       
    93      *             {@link ClassFinder#resolveClass(String)}.
       
    94      */
       
    95     @Deprecated
       
    96     public static Class classForName(String name) throws ClassNotFoundException {
       
    97         return ClassFinder.resolveClass(name);
       
    98     }
       
    99 
       
   100     /**
       
   101      * Returns the <code>Class</code> object associated with
       
   102      * the class or interface with the given string name,
       
   103      * using the given class loader.
       
   104      *
       
   105      * @param name  fully qualified name of the desired class
       
   106      * @param cl    class loader from which the class must be loaded
       
   107      * @return class object representing the desired class
       
   108      *
       
   109      * @exception ClassNotFoundException  if the class cannot be located
       
   110      *                                    by the specified class loader
       
   111      *
       
   112      * @deprecated As of JDK version 7, replaced by
       
   113      *             {@link ClassFinder#resolveClass(String,ClassLoader)}.
       
   114      */
       
   115     @Deprecated
       
   116     public static Class classForName(String name, ClassLoader cl)
       
   117         throws ClassNotFoundException {
       
   118         return ClassFinder.resolveClass(name, cl);
       
   119     }
       
   120 
       
   121     private Hashtable environment;
       
   122     private Vector expStack;
       
   123     private StringBuffer chars;
       
   124     private XMLDecoder is;
       
   125     private ClassLoader ldr;
       
   126     private int itemsRead = 0;
       
   127     private boolean isString;
       
   128 
       
   129     public ObjectHandler() {
       
   130         environment = new Hashtable();
       
   131         expStack = new Vector();
       
   132         chars = new StringBuffer();
       
   133     }
       
   134 
       
   135     public ObjectHandler(XMLDecoder is) {
       
   136         this();
       
   137         this.is = is;
       
   138     }
       
   139 
       
   140     /* loader can be null */
       
   141     public ObjectHandler(XMLDecoder is, ClassLoader loader) {
       
   142         this(is);
       
   143         this.ldr = loader;
       
   144     }
       
   145 
       
   146 
       
   147     public void reset() {
       
   148         expStack.clear();
       
   149         chars.setLength(0);
       
   150         MutableExpression e = new MutableExpression();
       
   151         e.setTarget(classForName2("java.lang.Object"));
       
   152         e.setMethodName("null");
       
   153         expStack.add(e);
       
   154     }
       
   155 
       
   156     private Object getValue(Expression exp) {
       
   157         try {
       
   158             return exp.getValue();
       
   159         }
       
   160         catch (Exception e) {
       
   161             if (is != null) {
       
   162                 is.getExceptionListener().exceptionThrown(e);
       
   163             }
       
   164             return null;
       
   165         }
       
   166     }
       
   167 
       
   168     private void addArg(Object arg) {
       
   169         lastExp().addArg(arg);
       
   170     }
       
   171 
       
   172     private Object pop(Vector v) {
       
   173         int last = v.size()-1;
       
   174         Object result = v.get(last);
       
   175         v.remove(last);
       
   176         return result;
       
   177     }
       
   178 
       
   179     private Object eval() {
       
   180         return getValue(lastExp());
       
   181     }
       
   182 
       
   183     private MutableExpression lastExp() {
       
   184         return (MutableExpression)expStack.lastElement();
       
   185     }
       
   186 
       
   187     public Object dequeueResult() {
       
   188         Object[] results = lastExp().getArguments();
       
   189         return results[itemsRead++];
       
   190     }
       
   191 
       
   192     private boolean isPrimitive(String name) {
       
   193         return name != "void" && typeNameToClass(name) != null;
       
   194     }
       
   195 
       
   196     private void simulateException(String message) {
       
   197         Exception e = new Exception(message);
       
   198         e.fillInStackTrace();
       
   199         if (is != null) {
       
   200             is.getExceptionListener().exceptionThrown(e);
       
   201         }
       
   202     }
       
   203 
       
   204     private Class classForName2(String name) {
       
   205         try {
       
   206             return ClassFinder.resolveClass(name, this.ldr);
       
   207         }
       
   208         catch (ClassNotFoundException e) {
       
   209             if (is != null) {
       
   210                 is.getExceptionListener().exceptionThrown(e);
       
   211             }
       
   212         }
       
   213         return null;
       
   214     }
       
   215 
       
   216     private HashMap getAttributes(AttributeList attrs) {
       
   217         HashMap attributes = new HashMap();
       
   218         if (attrs != null && attrs.getLength() > 0) {
       
   219             for(int i = 0; i < attrs.getLength(); i++) {
       
   220                 attributes.put(attrs.getName(i), attrs.getValue(i));
       
   221             }
       
   222         }
       
   223         return attributes;
       
   224     }
       
   225 
       
   226     public void startElement(String name, AttributeList attrs) throws SAXException {
       
   227         name = name.intern(); // Xerces parser does not supply unique tag names.
       
   228         if (this.isString) {
       
   229             parseCharCode(name, getAttributes(attrs));
       
   230             return;
       
   231         }
       
   232         chars.setLength(0);
       
   233 
       
   234         HashMap attributes = getAttributes(attrs);
       
   235         MutableExpression e = new MutableExpression();
       
   236 
       
   237         // Target
       
   238         String className = (String)attributes.get("class");
       
   239         if (className != null) {
       
   240             e.setTarget(classForName2(className));
       
   241         }
       
   242 
       
   243         // Property
       
   244         Object property = attributes.get("property");
       
   245         String index = (String)attributes.get("index");
       
   246         if (index != null) {
       
   247             property = new Integer(index);
       
   248             e.addArg(property);
       
   249         }
       
   250         e.setProperty(property);
       
   251 
       
   252         // Method
       
   253         String methodName = (String)attributes.get("method");
       
   254         if (methodName == null && property == null) {
       
   255             methodName = "new";
       
   256         }
       
   257         e.setMethodName(methodName);
       
   258 
       
   259         // Tags
       
   260         if (name == "string") {
       
   261             e.setTarget(String.class);
       
   262             e.setMethodName("new");
       
   263             this.isString = true;
       
   264         }
       
   265         else if (isPrimitive(name)){
       
   266             Class wrapper = typeNameToClass(name);
       
   267             e.setTarget(wrapper);
       
   268             e.setMethodName("new");
       
   269             parseCharCode(name, attributes);
       
   270         }
       
   271         else if (name == "class") {
       
   272             e.setTarget(Class.class);
       
   273             e.setMethodName("forName");
       
   274         }
       
   275         else if (name == "null") {
       
   276             // Create an arbitrary expression that has a value of null - for
       
   277             // consistency.
       
   278             e.setTarget(Object.class);
       
   279             e.setMethodName("getSuperclass");
       
   280             e.setValue(null);
       
   281         }
       
   282         else if (name == "void") {
       
   283             if (e.getTarget() == null) { // this check is for "void class="foo" method= ..."
       
   284                 e.setTarget(eval());
       
   285             }
       
   286         }
       
   287         else if (name == "array") {
       
   288             // The class attribute means sub-type for arrays.
       
   289             String subtypeName = (String)attributes.get("class");
       
   290             Class subtype = (subtypeName == null) ? Object.class : classForName2(subtypeName);
       
   291             String length = (String)attributes.get("length");
       
   292             if (length != null) {
       
   293                 e.setTarget(java.lang.reflect.Array.class);
       
   294                 e.addArg(subtype);
       
   295                 e.addArg(new Integer(length));
       
   296             }
       
   297             else {
       
   298                 Class arrayClass = java.lang.reflect.Array.newInstance(subtype, 0).getClass();
       
   299                 e.setTarget(arrayClass);
       
   300             }
       
   301         }
       
   302         else if (name == "java") {
       
   303             e.setValue(is); // The outermost scope is the stream itself.
       
   304         }
       
   305         else if (name == "object") {
       
   306         }
       
   307         else {
       
   308             simulateException("Unrecognized opening tag: " + name + " " + attrsToString(attrs));
       
   309             return;
       
   310         }
       
   311 
       
   312         // ids
       
   313         String idName = (String)attributes.get("id");
       
   314         if (idName != null) {
       
   315             environment.put(idName, e);
       
   316         }
       
   317 
       
   318         // idrefs
       
   319         String idrefName = (String)attributes.get("idref");
       
   320         if (idrefName != null) {
       
   321             e.setValue(lookup(idrefName));
       
   322         }
       
   323 
       
   324         // fields
       
   325         String fieldName = (String)attributes.get("field");
       
   326         if (fieldName != null) {
       
   327             e.setValue(getFieldValue(e.getTarget(), fieldName));
       
   328         }
       
   329         expStack.add(e);
       
   330     }
       
   331 
       
   332     private Object getFieldValue(Object target, String fieldName) {
       
   333         try {
       
   334             Class type = target.getClass();
       
   335             if (type == Class.class) {
       
   336                 type = (Class)target;
       
   337             }
       
   338             java.lang.reflect.Field f = sun.reflect.misc.FieldUtil.getField(type, fieldName);
       
   339             return f.get(target);
       
   340         }
       
   341         catch (Exception e) {
       
   342             if (is != null) {
       
   343                 is.getExceptionListener().exceptionThrown(e);
       
   344             }
       
   345             return null;
       
   346         }
       
   347     }
       
   348 
       
   349     private String attrsToString(AttributeList attrs) {
       
   350         StringBuffer b = new StringBuffer();
       
   351         for (int i = 0; i < attrs.getLength (); i++) {
       
   352             b.append(attrs.getName(i)+"=\""+attrs.getValue(i)+"\" ");
       
   353         }
       
   354         return b.toString();
       
   355     }
       
   356 
       
   357     public void characters(char buf [], int offset, int len) throws SAXException {
       
   358         chars.append(new String(buf, offset, len));
       
   359     }
       
   360 
       
   361     private void parseCharCode(String name, Map map) {
       
   362         if (name == "char") {
       
   363             String value = (String) map.get("code");
       
   364             if (value != null) {
       
   365                 int code = Integer.decode(value);
       
   366                 for (char ch : Character.toChars(code)) {
       
   367                     this.chars.append(ch);
       
   368                 }
       
   369             }
       
   370         }
       
   371     }
       
   372 
       
   373     public Object lookup(String s) {
       
   374         Expression e = (Expression)environment.get(s);
       
   375         if (e == null) {
       
   376             simulateException("Unbound variable: " + s);
       
   377         }
       
   378         return getValue(e);
       
   379     }
       
   380 
       
   381     public void register(String id, Object value) {
       
   382         Expression e = new MutableExpression();
       
   383         e.setValue(value);
       
   384         environment.put(id, e);
       
   385     }
       
   386 
       
   387     public void endElement(String name) throws SAXException {
       
   388         name = name.intern(); // Xerces parser does not supply unique tag names.
       
   389         if (name == "string") {
       
   390             this.isString = false;
       
   391         } else if (this.isString) {
       
   392             return;
       
   393         }
       
   394         if (name == "java") {
       
   395             return;
       
   396         }
       
   397         if (isPrimitive(name) || name == "string" || name == "class") {
       
   398             addArg(chars.toString());
       
   399         }
       
   400         if (name == "object" || name == "array" || name == "void" ||
       
   401                 isPrimitive(name) || name == "string" || name == "class" ||
       
   402                 name == "null") {
       
   403             Expression e = (Expression)pop(expStack);
       
   404             Object value = getValue(e);
       
   405             if (name != "void") {
       
   406                 addArg(value);
       
   407             }
       
   408         }
       
   409         else {
       
   410             simulateException("Unrecognized closing tag: " + name);
       
   411         }
       
   412     }
       
   413 }
       
   414 
       
   415 
       
   416 class MutableExpression extends Expression {
       
   417     private Object target;
       
   418     private String methodName;
       
   419 
       
   420     private Object property;
       
   421     private Vector argV = new Vector();
       
   422 
       
   423     private String capitalize(String propertyName) {
       
   424         if (propertyName.length() == 0) {
       
   425             return propertyName;
       
   426         }
       
   427         return propertyName.substring(0, 1).toUpperCase(ENGLISH) + propertyName.substring(1);
       
   428     }
       
   429 
       
   430     public MutableExpression() {
       
   431         super(null, null, null);
       
   432     }
       
   433 
       
   434     public Object[] getArguments() {
       
   435         return argV.toArray();
       
   436     }
       
   437 
       
   438     public String getMethodName() {
       
   439         if (property == null) {
       
   440             return methodName;
       
   441         }
       
   442         int setterArgs = (property instanceof String) ? 1 : 2;
       
   443         String methodName = (argV.size() == setterArgs) ? "set" : "get";
       
   444         if (property instanceof String) {
       
   445             return methodName + capitalize((String)property);
       
   446         }
       
   447         else {
       
   448             return methodName;
       
   449         }
       
   450     }
       
   451 
       
   452     public void addArg(Object arg) {
       
   453         argV.add(arg);
       
   454     }
       
   455 
       
   456     public void setTarget(Object target) {
       
   457         this.target = target;
       
   458     }
       
   459 
       
   460     public Object getTarget() {
       
   461         return target;
       
   462     }
       
   463 
       
   464     public void setMethodName(String methodName) {
       
   465         this.methodName = methodName;
       
   466     }
       
   467 
       
   468     public void setProperty(Object property) {
       
   469         this.property = property;
       
   470     }
       
   471 
       
   472     public void setValue(Object value) {
       
   473         super.setValue(value);
       
   474     }
       
   475 
       
   476     public Object getValue() throws Exception {
       
   477         return super.getValue();
       
   478     }
       
   479 }