Index: main/java/java/beans/Encoder.java =================================================================== --- main/java/java/beans/Encoder.java (revision 431328) +++ main/java/java/beans/Encoder.java (working copy) @@ -21,6 +21,7 @@ package java.beans; import java.lang.reflect.Field; +import java.lang.reflect.Method; import java.util.HashMap; import java.util.Vector; @@ -119,6 +120,7 @@ Statement statement; Object[] oldArgs = oldStm.getArguments(); + // FIXME add target processing here write(oldArgs); statement = new Statement(node.getObjectValue(), oldStm.getMethodName(), oldArgs); @@ -140,44 +142,55 @@ */ public void writeExpression(Expression oldExp) { try { - Object oldInstance = oldExp.getValue(); + Object oldValue = oldExp.getValue(); + Object oldTarget = oldExp.getTarget(); - ObjectNode node = null; - Class type = null; + ObjectNode valueNode = null; + Class valueType = null; - if (oldInstance != null) { - type = oldInstance.getClass(); - node = nodes.get(oldInstance); + // write target + if (!Statement.isPDConstructor(oldExp) && + !Statement.isStaticMethodCall(oldExp)) + { + ObjectNode parent; + + //XXX investigate + //write(oldTarget); + parent = nodes.get(oldTarget); + if (parent != null) { + parent.addExpression(oldExp); + } } - if (node == null) { - if (isNull(type) || isPrimitive(type) || isString(type) - //|| isClass(type) - ) { - node = new ObjectNode(oldExp); + // write value + + if (oldValue != null) { + valueType = oldValue.getClass(); + valueNode = nodes.get(oldValue); + } + + if (valueNode == null) { + + if (isNull(valueType) || isPrimitive(valueType) + || isString(valueType)) + { + valueNode = new ObjectNode(oldExp); } else { write(oldExp.getArguments()); - node = new ObjectNode(oldExp, nodes); + valueNode = new ObjectNode(oldExp, nodes); } - nodes.put(oldInstance, node); - - // if an expression is not a constructor - // FIXME prevents instance methods of Class and Method objects - // from being handled correctly - if (!(oldExp.getTarget() instanceof Class - || oldExp.getTarget() instanceof Field)) { - ObjectNode parent = nodes.get(oldExp.getTarget()); - - parent.addExpression(oldExp); - } + nodes.put(oldValue, valueNode); } else if (oldExp.getMethodName().equals("new")) { - node.addReference(); + valueNode.addReference(); } else { - node.addReferencedExpression(oldExp); + // XXX the information about referencedExpressions is not + // being used by anyone + // node.addReferencedExpression(oldExp); } } catch (Exception e) { // TODO - remove written args + e.printStackTrace(); getExceptionListener().exceptionThrown(e); } } @@ -274,7 +287,7 @@ static boolean isArray(Class type) { return type.isArray(); } - + static String getPrimitiveName(Class type) { String result = null; Index: main/java/java/beans/Statement.java =================================================================== --- main/java/java/beans/Statement.java (revision 431328) +++ main/java/java/beans/Statement.java (working copy) @@ -152,7 +152,7 @@ } } else if (target instanceof Class) { Method method = null; - + try { // try to look for static method at first method = findMethod((Class) target, methodName, arguments, @@ -166,17 +166,18 @@ result = method.invoke(target, arguments); } } else { - final Method method = findMethod(target.getClass(), methodName, + Method method = findMethod(target.getClass(), methodName, arguments, false); - AccessController.doPrivileged(new PrivilegedAction() { + // XXX investigate: do we really need this? +// AccessController.doPrivileged(new PrivilegedAction() { +// +// public Object run() { +// mtd.setAccessible(true); +// return null; +// } +// }); - public Object run() { - method.setAccessible(true); - return null; - } - }); - result = method.invoke(target, arguments); } } catch (InvocationTargetException ite) { @@ -186,7 +187,7 @@ } return result; } - + private Method findArrayMethod() throws NoSuchMethodException { // the code below reproduces exact RI exception throwing behavior if (!methodName.equals("set") && !methodName.equals("get")) { @@ -270,7 +271,7 @@ /** * Searches for best matching method for given name and argument types. */ - private static Method findMethod(Class targetClass, String methodName, + static Method findMethod(Class targetClass, String methodName, Object[] arguments, boolean methodIsStatic) throws NoSuchMethodException { @@ -328,6 +329,79 @@ return foundMethodsArr[0]; } + static boolean isStaticMethodCall(Statement stmt) { + Object target = stmt.getTarget(); + String mName = stmt.getMethodName(); + + if (!(target instanceof Class)) { + return false; + } + + try { + Statement.findMethod((Class) target, mName, + stmt.getArguments(), true); + return true; + } catch (NoSuchMethodException e) { + return false; + } + } + + /** + * The list of "method signatures" used by persistence delegates to create + * objects. Not necessary reflects to real methods. + */ + private static String[][] pdConstructorSignatures = { + {"java.lang.Class", "new", "java.lang.Boolean", "", "", ""}, + {"java.lang.Class", "new", "java.lang.Byte", "", "", ""}, + {"java.lang.Class", "new", "java.lang.Character", "", "", ""}, + {"java.lang.Class", "new", "java.lang.Double", "", "", ""}, + {"java.lang.Class", "new", "java.lang.Float", "", "", ""}, + {"java.lang.Class", "new", "java.lang.Integer", "", "", ""}, + {"java.lang.Class", "new", "java.lang.Long", "", "", ""}, + {"java.lang.Class", "new", "java.lang.Short", "", "", ""}, + {"java.lang.Class", "new", "java.lang.String", "", "", ""}, + {"java.lang.Class", "forName", "java.lang.String", "", "", ""}, + {"java.lang.Class", "newInstance", "java.lang.Class", + "java.lang.Integer", "", ""}, + {"java.lang.reflect.Field", "get", "null", "", "", ""}, + {"java.lang.Class", "forName", "java.lang.String", "", "", ""} + }; + + static boolean isPDConstructor(Statement stmt) { + Object target = stmt.getTarget(); + String methodName = stmt.getMethodName(); + Object[] args = stmt.getArguments(); + String[] sig = new String[pdConstructorSignatures[0].length]; + + if (target == null || methodName == null || args == null || + args.length == 0) + { + // not a constructor for sure + return false; + } + + sig[0] = target.getClass().getName(); + sig[1] = methodName; + + for (int i = 2; i < sig.length; i++) { + if (args.length > i - 2) { + sig[i] = args[i - 2] != null ? + args[i - 2].getClass().getName() : "null"; + } else { + sig[i] = ""; + } + + } + + for (int i = 0; i < pdConstructorSignatures.length; i++) { + if (Arrays.equals(sig, pdConstructorSignatures[i])) { + return true; + } + } + + return false; + } + private static boolean isPrimitiveWrapper(Class wrapper, Class base) { return (base == boolean.class) && (wrapper == Boolean.class) || (base == byte.class) && (wrapper == Byte.class) Index: main/java/org/apache/harmony/beans/java_lang_reflect_FieldPersistenceDelegate.java =================================================================== --- main/java/org/apache/harmony/beans/java_lang_reflect_FieldPersistenceDelegate.java (revision 0) +++ main/java/org/apache/harmony/beans/java_lang_reflect_FieldPersistenceDelegate.java (revision 0) @@ -0,0 +1,59 @@ +/* Copyright 2006 The Apache Software Foundation or its licensors, as applicable + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.harmony.beans; + +import java.lang.reflect.Field; + +import java.beans.Encoder; +import java.beans.Expression; +import java.beans.PersistenceDelegate; + +/** + * This is a persistence delegate for the {@link java.lang.reflect.Field} class. + */ +public class java_lang_reflect_FieldPersistenceDelegate extends + PersistenceDelegate { + + protected Expression instantiate(Object oldInstance, Encoder out) { + // should not be null or have a type other than Field + assert oldInstance instanceof Field : oldInstance; + + Field oldField = (Field) oldInstance; + Class declClass = oldField.getDeclaringClass(); + + return new Expression(oldField, declClass, "getDeclaredField", + new Object[] { oldField.getName() }); + } + + protected void initialize(Class type, Object oldInstance, + Object newInstance, Encoder out) + { + // check for consistency + assert oldInstance instanceof Field : oldInstance; + assert newInstance instanceof Field : newInstance; + assert newInstance.equals(oldInstance); + } + + protected boolean mutatesTo(Object oldInstance, Object newInstance) { + assert oldInstance instanceof Field : oldInstance; + + if (!(newInstance instanceof Field)) { + // if null or not a Field + return false; + } + + return oldInstance.equals(newInstance); + } +} Index: main/java/org/apache/harmony/beans/ObjectNode.java =================================================================== --- main/java/org/apache/harmony/beans/ObjectNode.java (revision 431328) +++ main/java/org/apache/harmony/beans/ObjectNode.java (working copy) @@ -41,7 +41,8 @@ private LinkedHashSet statements = new LinkedHashSet(); private Vector expressions = new Vector(); - private Vector referencedExpressions = new Vector(); + // XXX referencedExpressions is not used indeed + //private Vector referencedExpressions = new Vector(); private int referencesNumber = 0; private String id = null; @@ -104,18 +105,19 @@ public int getReferencesNumber() { return referencesNumber; } + + // XXX never called by other classes +// public int getReferencedExpressionsNumber() { +// return referencedExpressions.size(); +// } - public int getReferencedExpressionsNumber() { - return referencedExpressions.size(); - } - public void addReference() { referencesNumber++; } - public void addReferencedExpression(Expression expr) { - referencedExpressions.add(expr); - } +// public void addReferencedExpression(Expression expr) { +// referencedExpressions.add(expr); +// } public String getId() { return id; @@ -137,9 +139,10 @@ return expressions.iterator(); } - public Iterator referencedExpressions() { - return referencedExpressions.iterator(); - } + // XXX never called by other classes +// public Iterator referencedExpressions() { +// return referencedExpressions.iterator(); +// } public Iterator statements() { return statements.iterator();