From 9330abadeaef38e2ed74c6f97f7c933250ae2edc Mon Sep 17 00:00:00 2001 From: Sergey Malenkov Date: Mon, 22 Dec 2008 17:42:49 +0300 Subject: [PATCH] 4864117: RFE: Make XMLDecoder API more reusable Reviewed-by: peterz, loneid --- .../classes/com/sun/beans/ObjectHandler.java | 479 ------------------ .../beans/decoder/AccessorElementHandler.java | 105 ++++ .../beans/decoder/ArrayElementHandler.java | 133 +++++ .../beans/decoder/BooleanElementHandler.java | 69 +++ .../sun/beans/decoder/ByteElementHandler.java | 63 +++ .../sun/beans/decoder/CharElementHandler.java | 92 ++++ .../beans/decoder/ClassElementHandler.java | 62 +++ .../sun/beans/decoder/DocumentHandler.java | 389 ++++++++++++++ .../beans/decoder/DoubleElementHandler.java | 63 +++ .../com/sun/beans/decoder/ElementHandler.java | 224 ++++++++ .../beans/decoder/FalseElementHandler.java | 56 ++ .../beans/decoder/FieldElementHandler.java | 189 +++++++ .../beans/decoder/FloatElementHandler.java | 63 +++ .../sun/beans/decoder/IntElementHandler.java | 63 +++ .../sun/beans/decoder/JavaElementHandler.java | 151 ++++++ .../sun/beans/decoder/LongElementHandler.java | 63 +++ .../beans/decoder/MethodElementHandler.java | 109 ++++ .../sun/beans/decoder/NewElementHandler.java | 205 ++++++++ .../sun/beans/decoder/NullElementHandler.java | 76 +++ .../beans/decoder/ObjectElementHandler.java | 168 ++++++ .../beans/decoder/PropertyElementHandler.java | 287 +++++++++++ .../beans/decoder/ShortElementHandler.java | 63 +++ .../beans/decoder/StringElementHandler.java | 116 +++++ .../sun/beans/decoder/TrueElementHandler.java | 56 ++ .../com/sun/beans/decoder/ValueObject.java | 50 ++ .../sun/beans/decoder/ValueObjectImpl.java | 88 ++++ .../sun/beans/decoder/VarElementHandler.java | 82 +++ .../sun/beans/decoder/VoidElementHandler.java | 68 +++ .../com/sun/beans/finder/AbstractFinder.java | 213 ++++++++ .../com/sun/beans/finder/ClassFinder.java | 99 ++-- .../sun/beans/finder/ConstructorFinder.java | 127 +++++ .../com/sun/beans/finder/FieldFinder.java | 106 ++++ .../com/sun/beans/finder/MethodFinder.java | 205 ++++++++ .../sun/beans/finder/PrimitiveTypeMap.java | 29 +- .../sun/beans/finder/PrimitiveWrapperMap.java | 86 ++++ .../com/sun/beans/finder/Signature.java | 169 ++++++ .../share/classes/java/beans/MetaData.java | 4 +- .../classes/java/beans/ReflectionUtils.java | 13 +- .../share/classes/java/beans/XMLDecoder.java | 153 +++--- .../javax/swing/plaf/synth/SynthParser.java | 107 ++-- .../java/beans/XMLDecoder/Test4864117.java | 146 ++++++ .../java/beans/XMLDecoder/Test6341798.java | 4 +- .../beans/XMLDecoder/spec/AbstractTest.java | 76 +++ .../java/beans/XMLDecoder/spec/TestArray.java | 86 ++++ .../beans/XMLDecoder/spec/TestBoolean.java | 52 ++ .../java/beans/XMLDecoder/spec/TestByte.java | 56 ++ .../java/beans/XMLDecoder/spec/TestChar.java | 52 ++ .../java/beans/XMLDecoder/spec/TestClass.java | 61 +++ .../beans/XMLDecoder/spec/TestDouble.java | 58 +++ .../java/beans/XMLDecoder/spec/TestFalse.java | 48 ++ .../java/beans/XMLDecoder/spec/TestField.java | 74 +++ .../java/beans/XMLDecoder/spec/TestFloat.java | 58 +++ .../java/beans/XMLDecoder/spec/TestInt.java | 64 +++ .../java/beans/XMLDecoder/spec/TestJava.java | 63 +++ .../java/beans/XMLDecoder/spec/TestLong.java | 68 +++ .../beans/XMLDecoder/spec/TestMethod.java | 178 +++++++ .../java/beans/XMLDecoder/spec/TestNew.java | 90 ++++ .../java/beans/XMLDecoder/spec/TestNull.java | 48 ++ .../beans/XMLDecoder/spec/TestObject.java | 84 +++ .../beans/XMLDecoder/spec/TestProperty.java | 88 ++++ .../java/beans/XMLDecoder/spec/TestShort.java | 60 +++ .../beans/XMLDecoder/spec/TestString.java | 60 +++ .../java/beans/XMLDecoder/spec/TestTrue.java | 48 ++ .../java/beans/XMLDecoder/spec/TestVar.java | 54 ++ 64 files changed, 5946 insertions(+), 673 deletions(-) delete mode 100644 jdk/src/share/classes/com/sun/beans/ObjectHandler.java create mode 100644 jdk/src/share/classes/com/sun/beans/decoder/AccessorElementHandler.java create mode 100644 jdk/src/share/classes/com/sun/beans/decoder/ArrayElementHandler.java create mode 100644 jdk/src/share/classes/com/sun/beans/decoder/BooleanElementHandler.java create mode 100644 jdk/src/share/classes/com/sun/beans/decoder/ByteElementHandler.java create mode 100644 jdk/src/share/classes/com/sun/beans/decoder/CharElementHandler.java create mode 100644 jdk/src/share/classes/com/sun/beans/decoder/ClassElementHandler.java create mode 100644 jdk/src/share/classes/com/sun/beans/decoder/DocumentHandler.java create mode 100644 jdk/src/share/classes/com/sun/beans/decoder/DoubleElementHandler.java create mode 100644 jdk/src/share/classes/com/sun/beans/decoder/ElementHandler.java create mode 100644 jdk/src/share/classes/com/sun/beans/decoder/FalseElementHandler.java create mode 100644 jdk/src/share/classes/com/sun/beans/decoder/FieldElementHandler.java create mode 100644 jdk/src/share/classes/com/sun/beans/decoder/FloatElementHandler.java create mode 100644 jdk/src/share/classes/com/sun/beans/decoder/IntElementHandler.java create mode 100644 jdk/src/share/classes/com/sun/beans/decoder/JavaElementHandler.java create mode 100644 jdk/src/share/classes/com/sun/beans/decoder/LongElementHandler.java create mode 100644 jdk/src/share/classes/com/sun/beans/decoder/MethodElementHandler.java create mode 100644 jdk/src/share/classes/com/sun/beans/decoder/NewElementHandler.java create mode 100644 jdk/src/share/classes/com/sun/beans/decoder/NullElementHandler.java create mode 100644 jdk/src/share/classes/com/sun/beans/decoder/ObjectElementHandler.java create mode 100644 jdk/src/share/classes/com/sun/beans/decoder/PropertyElementHandler.java create mode 100644 jdk/src/share/classes/com/sun/beans/decoder/ShortElementHandler.java create mode 100644 jdk/src/share/classes/com/sun/beans/decoder/StringElementHandler.java create mode 100644 jdk/src/share/classes/com/sun/beans/decoder/TrueElementHandler.java create mode 100644 jdk/src/share/classes/com/sun/beans/decoder/ValueObject.java create mode 100644 jdk/src/share/classes/com/sun/beans/decoder/ValueObjectImpl.java create mode 100644 jdk/src/share/classes/com/sun/beans/decoder/VarElementHandler.java create mode 100644 jdk/src/share/classes/com/sun/beans/decoder/VoidElementHandler.java create mode 100644 jdk/src/share/classes/com/sun/beans/finder/AbstractFinder.java create mode 100644 jdk/src/share/classes/com/sun/beans/finder/ConstructorFinder.java create mode 100644 jdk/src/share/classes/com/sun/beans/finder/FieldFinder.java create mode 100644 jdk/src/share/classes/com/sun/beans/finder/MethodFinder.java create mode 100644 jdk/src/share/classes/com/sun/beans/finder/PrimitiveWrapperMap.java create mode 100644 jdk/src/share/classes/com/sun/beans/finder/Signature.java create mode 100644 jdk/test/java/beans/XMLDecoder/Test4864117.java create mode 100644 jdk/test/java/beans/XMLDecoder/spec/AbstractTest.java create mode 100644 jdk/test/java/beans/XMLDecoder/spec/TestArray.java create mode 100644 jdk/test/java/beans/XMLDecoder/spec/TestBoolean.java create mode 100644 jdk/test/java/beans/XMLDecoder/spec/TestByte.java create mode 100644 jdk/test/java/beans/XMLDecoder/spec/TestChar.java create mode 100644 jdk/test/java/beans/XMLDecoder/spec/TestClass.java create mode 100644 jdk/test/java/beans/XMLDecoder/spec/TestDouble.java create mode 100644 jdk/test/java/beans/XMLDecoder/spec/TestFalse.java create mode 100644 jdk/test/java/beans/XMLDecoder/spec/TestField.java create mode 100644 jdk/test/java/beans/XMLDecoder/spec/TestFloat.java create mode 100644 jdk/test/java/beans/XMLDecoder/spec/TestInt.java create mode 100644 jdk/test/java/beans/XMLDecoder/spec/TestJava.java create mode 100644 jdk/test/java/beans/XMLDecoder/spec/TestLong.java create mode 100644 jdk/test/java/beans/XMLDecoder/spec/TestMethod.java create mode 100644 jdk/test/java/beans/XMLDecoder/spec/TestNew.java create mode 100644 jdk/test/java/beans/XMLDecoder/spec/TestNull.java create mode 100644 jdk/test/java/beans/XMLDecoder/spec/TestObject.java create mode 100644 jdk/test/java/beans/XMLDecoder/spec/TestProperty.java create mode 100644 jdk/test/java/beans/XMLDecoder/spec/TestShort.java create mode 100644 jdk/test/java/beans/XMLDecoder/spec/TestString.java create mode 100644 jdk/test/java/beans/XMLDecoder/spec/TestTrue.java create mode 100644 jdk/test/java/beans/XMLDecoder/spec/TestVar.java diff --git a/jdk/src/share/classes/com/sun/beans/ObjectHandler.java b/jdk/src/share/classes/com/sun/beans/ObjectHandler.java deleted file mode 100644 index 6daeab953a2..00000000000 --- a/jdk/src/share/classes/com/sun/beans/ObjectHandler.java +++ /dev/null @@ -1,479 +0,0 @@ -/* - * Copyright 2003-2006 Sun Microsystems, Inc. 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. Sun designates this - * particular file as subject to the "Classpath" exception as provided - * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, - * CA 95054 USA or visit www.sun.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 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. - * - * @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. - * - * @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. - * - * @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); - } - - 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) { - int code = Integer.decode(value); - for (char ch : Character.toChars(code)) { - this.chars.append(ch); - } - } - } - } - - 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(); - } -} diff --git a/jdk/src/share/classes/com/sun/beans/decoder/AccessorElementHandler.java b/jdk/src/share/classes/com/sun/beans/decoder/AccessorElementHandler.java new file mode 100644 index 00000000000..d34fce45635 --- /dev/null +++ b/jdk/src/share/classes/com/sun/beans/decoder/AccessorElementHandler.java @@ -0,0 +1,105 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.beans.decoder; + +/** + * This is base class that simplifies access to entities (fields or properties). + * The {@code name} attribute specifies the name of the accessible entity. + * The element defines getter if it contains no argument + * or setter if it contains one argument. + * + * @since 1.7 + * + * @author Sergey A. Malenkov + */ +abstract class AccessorElementHandler extends ElementHandler { + private String name; + private ValueObject value; + + /** + * Parses attributes of the element. + * The following atributes are supported: + *
+ *
name + *
the name of the accessible entity + *
id + *
the identifier of the variable that is intended to store the result + *
+ * + * @param name the attribute name + * @param value the attribute value + */ + @Override + public void addAttribute(String name, String value) { + if (name.equals("name")) { // NON-NLS: the attribute name + this.name = value; + } else { + super.addAttribute(name, value); + } + } + + /** + * Adds the argument that is used to set the value of this element. + * + * @param argument the value of the element that contained in this one + */ + @Override + protected final void addArgument(Object argument) { + if (this.value != null) { + throw new IllegalStateException("Could not add argument to evaluated element"); + } + setValue(this.name, argument); + this.value = ValueObjectImpl.VOID; + } + + /** + * Returns the value of this element. + * + * @return the value of this element + */ + @Override + protected final ValueObject getValueObject() { + if (this.value == null) { + this.value = ValueObjectImpl.create(getValue(this.name)); + } + return this.value; + } + + /** + * Returns the value of the entity with specified {@code name}. + * + * @param name the name of the accessible entity + * @return the value of the specified entity + */ + protected abstract Object getValue(String name); + + /** + * Sets the new value for the entity with specified {@code name}. + * + * @param name the name of the accessible entity + * @param value the new value for the specified entity + */ + protected abstract void setValue(String name, Object value); +} diff --git a/jdk/src/share/classes/com/sun/beans/decoder/ArrayElementHandler.java b/jdk/src/share/classes/com/sun/beans/decoder/ArrayElementHandler.java new file mode 100644 index 00000000000..0bfcec6e46a --- /dev/null +++ b/jdk/src/share/classes/com/sun/beans/decoder/ArrayElementHandler.java @@ -0,0 +1,133 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.beans.decoder; + +import java.lang.reflect.Array; + +/** + * This class is intended to handle <array> element, + * that is used to array creation. + * The {@code length} attribute specifies the length of the array. + * The {@code class} attribute specifies the elements type. + * The {@link Object} type is used by default. + * For example:
+ * <array length="10"/>
+ * is equivalent to {@code new Component[10]} in Java code. + * The {@code set} and {@code get} methods, + * as defined in the {@link java.util.List} interface, + * can be used as if they could be applied to array instances. + * The {@code index} attribute can thus be used with arrays. + * For example:
+ * <array length="3" class="java.lang.String">
+ *     <void index="1">
+ *         <string>Hello, world</string>
+ *     </void>
+ * </array>
+ * is equivalent to the following Java code:
+ * String[] s = new String[3];
+ * s[1] = "Hello, world";
+ * It is possible to omit the {@code length} attribute and + * specify the values directly, without using {@code void} tags. + * The length of the array is equal to the number of values specified. + * For example:
+ * <array id="array" class="int">
+ *     <int>123</int>
+ *     <int>456</int>
+ * </array>
+ * is equivalent to {@code int[] array = {123, 456}} in Java code. + *

The following atributes are supported: + *

+ *
length + *
the array length + *
class + *
the type of object for instantiation + *
id + *
the identifier of the variable that is intended to store the result + *
+ * + * @since 1.7 + * + * @author Sergey A. Malenkov + */ +final class ArrayElementHandler extends NewElementHandler { + private Integer length; + + /** + * Parses attributes of the element. + * The following atributes are supported: + *
+ *
length + *
the array length + *
class + *
the type of object for instantiation + *
id + *
the identifier of the variable that is intended to store the result + *
+ * + * @param name the attribute name + * @param value the attribute value + */ + @Override + public void addAttribute(String name, String value) { + if (name.equals("length")) { // NON-NLS: the attribute name + this.length = Integer.valueOf(value); + } else { + super.addAttribute(name, value); + } + } + + /** + * Calculates the value of this element + * if the lentgh attribute is set. + */ + @Override + public void startElement() { + if (this.length != null) { + getValueObject(); + } + } + + /** + * Creates an instance of the array. + * + * @param type the base class + * @param args the array of arguments + * @return the value of this element + */ + @Override + protected ValueObject getValueObject(Class type, Object[] args) { + if (type == null) { + type = Object.class; + } + if (this.length != null) { + return ValueObjectImpl.create(Array.newInstance(type, this.length)); + } + Object array = Array.newInstance(type, args.length); + for (int i = 0; i < args.length; i++) { + Array.set(array, i, args[i]); + } + return ValueObjectImpl.create(array); + } +} diff --git a/jdk/src/share/classes/com/sun/beans/decoder/BooleanElementHandler.java b/jdk/src/share/classes/com/sun/beans/decoder/BooleanElementHandler.java new file mode 100644 index 00000000000..a5f401b5f49 --- /dev/null +++ b/jdk/src/share/classes/com/sun/beans/decoder/BooleanElementHandler.java @@ -0,0 +1,69 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.beans.decoder; + +/** + * This class is intended to handle <boolean> element. + * This element specifies {@code boolean} values. + * The class {@link Boolean} is used as wrapper for these values. + * The result value is created from text of the body of this element. + * The body parsing is described in the class {@link StringElementHandler}. + * For example:
+ * <boolean>true</boolean>
+ * is shortcut to
+ * <method name="valueOf" class="java.lang.Boolean">
+ *     <string>true</string>
+ * </method>
+ * which is equivalent to {@code Boolean.valueOf("true")} in Java code. + *

The following atribute is supported: + *

+ *
id + *
the identifier of the variable that is intended to store the result + *
+ * + * @since 1.7 + * + * @author Sergey A. Malenkov + */ +final class BooleanElementHandler extends StringElementHandler { + + /** + * Creates {@code boolean} value from + * the text of the body of this element. + * + * @param argument the text of the body + * @return evaluated {@code boolean} value + */ + @Override + public Object getValue(String argument) { + if (Boolean.TRUE.toString().equalsIgnoreCase(argument)) { + return Boolean.TRUE; + } + if (Boolean.FALSE.toString().equalsIgnoreCase(argument)) { + return Boolean.FALSE; + } + throw new IllegalArgumentException("Unsupported boolean argument: " + argument); + } +} diff --git a/jdk/src/share/classes/com/sun/beans/decoder/ByteElementHandler.java b/jdk/src/share/classes/com/sun/beans/decoder/ByteElementHandler.java new file mode 100644 index 00000000000..d7d458f0104 --- /dev/null +++ b/jdk/src/share/classes/com/sun/beans/decoder/ByteElementHandler.java @@ -0,0 +1,63 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.beans.decoder; + +/** + * This class is intended to handle <byte> element. + * This element specifies {@code byte} values. + * The class {@link Byte} is used as wrapper for these values. + * The result value is created from text of the body of this element. + * The body parsing is described in the class {@link StringElementHandler}. + * For example:
+ * <byte>127</byte>
+ * is shortcut to
+ * <method name="decode" class="java.lang.Byte">
+ *     <string>127</string>
+ * </method>
+ * which is equivalent to {@code Byte.decode("127")} in Java code. + *

The following atribute is supported: + *

+ *
id + *
the identifier of the variable that is intended to store the result + *
+ * + * @since 1.7 + * + * @author Sergey A. Malenkov + */ +final class ByteElementHandler extends StringElementHandler { + + /** + * Creates {@code byte} value from + * the text of the body of this element. + * + * @param argument the text of the body + * @return evaluated {@code byte} value + */ + @Override + public Object getValue(String argument) { + return Byte.decode(argument); + } +} diff --git a/jdk/src/share/classes/com/sun/beans/decoder/CharElementHandler.java b/jdk/src/share/classes/com/sun/beans/decoder/CharElementHandler.java new file mode 100644 index 00000000000..910b5a63f70 --- /dev/null +++ b/jdk/src/share/classes/com/sun/beans/decoder/CharElementHandler.java @@ -0,0 +1,92 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.beans.decoder; + +/** + * This class is intended to handle <char> element. + * This element specifies {@code char} values. + * The class {@link Character} is used as wrapper for these values. + * The result value is created from text of the body of this element. + * The body parsing is described in the class {@link StringElementHandler}. + * For example:
+ * <char>X</char>
+ * which is equivalent to {@code Character.valueOf('X')} in Java code. + *

The following atributes are supported: + *

+ *
code + *
this attribute specifies character code + *
id + *
the identifier of the variable that is intended to store the result + *
+ * The {@code code} attribute can be used for characters + * that are illegal in XML document, for example:
+ * <char code="0"/>
+ * + * @since 1.7 + * + * @author Sergey A. Malenkov + */ +final class CharElementHandler extends StringElementHandler { + + /** + * Parses attributes of the element. + * The following atributes are supported: + *
+ *
code + *
this attribute specifies character code + *
id + *
the identifier of the variable that is intended to store the result + *
+ * + * @param name the attribute name + * @param value the attribute value + */ + @Override + public void addAttribute(String name, String value) { + if (name.equals("code")) { // NON-NLS: the attribute name + int code = Integer.decode(value); + for (char ch : Character.toChars(code)) { + addCharacter(ch); + } + } else { + super.addAttribute(name, value); + } + } + + /** + * Creates {@code char} value from + * the text of the body of this element. + * + * @param argument the text of the body + * @return evaluated {@code char} value + */ + @Override + public Object getValue(String argument) { + if (argument.length() != 1) { + throw new IllegalArgumentException("Wrong characters count"); + } + return Character.valueOf(argument.charAt(0)); + } +} diff --git a/jdk/src/share/classes/com/sun/beans/decoder/ClassElementHandler.java b/jdk/src/share/classes/com/sun/beans/decoder/ClassElementHandler.java new file mode 100644 index 00000000000..c6ca9856416 --- /dev/null +++ b/jdk/src/share/classes/com/sun/beans/decoder/ClassElementHandler.java @@ -0,0 +1,62 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.beans.decoder; + +/** + * This class is intended to handle <class> element. + * This element specifies {@link Class} values. + * The result value is created from text of the body of this element. + * The body parsing is described in the class {@link StringElementHandler}. + * For example:
+ * <class>java.lang.Class</class>
+ * is shortcut to
+ * <method name="forName" class="java.lang.Class">
+ *     <string>java.lang.Class</string>
+ * </method>
+ * which is equivalent to {@code Class.forName("java.lang.Class")} in Java code. + *

The following atribute is supported: + *

+ *
id + *
the identifier of the variable that is intended to store the result + *
+ * + * @since 1.7 + * + * @author Sergey A. Malenkov + */ +final class ClassElementHandler extends StringElementHandler { + + /** + * Creates class by the name from + * the text of the body of this element. + * + * @param argument the text of the body + * @return evaluated {@code Class} value + */ + @Override + public Object getValue(String argument) { + return getOwner().findClass(argument); + } +} diff --git a/jdk/src/share/classes/com/sun/beans/decoder/DocumentHandler.java b/jdk/src/share/classes/com/sun/beans/decoder/DocumentHandler.java new file mode 100644 index 00000000000..4c409a12a9b --- /dev/null +++ b/jdk/src/share/classes/com/sun/beans/decoder/DocumentHandler.java @@ -0,0 +1,389 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.beans.decoder; + +import com.sun.beans.finder.ClassFinder; + +import java.beans.ExceptionListener; + +import java.io.IOException; + +import java.lang.ref.Reference; +import java.lang.ref.WeakReference; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.parsers.SAXParserFactory; + +import org.xml.sax.Attributes; +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; +import org.xml.sax.helpers.DefaultHandler; + +/** + * The main class to parse JavaBeans XML archive. + * + * @since 1.7 + * + * @author Sergey A. Malenkov + * + * @see ElementHandler + */ +public final class DocumentHandler extends DefaultHandler { + private final Map> handlers = new HashMap>(); + + private final Map environment = new HashMap(); + + private final List objects = new ArrayList(); + + private Reference loader; + private ExceptionListener listener; + private Object owner; + + private ElementHandler handler; + + /** + * Creates new instance of document handler. + */ + public DocumentHandler() { + setElementHandler("java", JavaElementHandler.class); // NON-NLS: the element name + setElementHandler("null", NullElementHandler.class); // NON-NLS: the element name + setElementHandler("array", ArrayElementHandler.class); // NON-NLS: the element name + setElementHandler("class", ClassElementHandler.class); // NON-NLS: the element name + setElementHandler("string", StringElementHandler.class); // NON-NLS: the element name + setElementHandler("object", ObjectElementHandler.class); // NON-NLS: the element name + + setElementHandler("void", VoidElementHandler.class); // NON-NLS: the element name + setElementHandler("char", CharElementHandler.class); // NON-NLS: the element name + setElementHandler("byte", ByteElementHandler.class); // NON-NLS: the element name + setElementHandler("short", ShortElementHandler.class); // NON-NLS: the element name + setElementHandler("int", IntElementHandler.class); // NON-NLS: the element name + setElementHandler("long", LongElementHandler.class); // NON-NLS: the element name + setElementHandler("float", FloatElementHandler.class); // NON-NLS: the element name + setElementHandler("double", DoubleElementHandler.class); // NON-NLS: the element name + setElementHandler("boolean", BooleanElementHandler.class); // NON-NLS: the element name + + // some handlers for new elements + setElementHandler("new", NewElementHandler.class); // NON-NLS: the element name + setElementHandler("var", VarElementHandler.class); // NON-NLS: the element name + setElementHandler("true", TrueElementHandler.class); // NON-NLS: the element name + setElementHandler("false", FalseElementHandler.class); // NON-NLS: the element name + setElementHandler("field", FieldElementHandler.class); // NON-NLS: the element name + setElementHandler("method", MethodElementHandler.class); // NON-NLS: the element name + setElementHandler("property", PropertyElementHandler.class); // NON-NLS: the element name + } + + /** + * Returns the class loader used to instantiate objects. + * If the class loader has not been explicitly set + * then {@code null} is returned. + * + * @return the class loader used to instantiate objects + */ + public ClassLoader getClassLoader() { + return (this.loader != null) + ? this.loader.get() + : null; + } + + /** + * Sets the class loader used to instantiate objects. + * If the class loader is not set + * then default class loader will be used. + * + * @param loader a classloader to use + */ + public void setClassLoader(ClassLoader loader) { + this.loader = new WeakReference(loader); + } + + /** + * Returns the exception listener for parsing. + * The exception listener is notified + * when handler catches recoverable exceptions. + * If the exception listener has not been explicitly set + * then default exception listener is returned. + * + * @return the exception listener for parsing + */ + public ExceptionListener getExceptionListener() { + return this.listener; + } + + /** + * Sets the exception listener for parsing. + * The exception listener is notified + * when handler catches recoverable exceptions. + * + * @param listener the exception listener for parsing + */ + public void setExceptionListener(ExceptionListener listener) { + this.listener = listener; + } + + /** + * Returns the owner of this document handler. + * + * @return the owner of this document handler + */ + public Object getOwner() { + return this.owner; + } + + /** + * Sets the owner of this document handler. + * + * @param owner the owner of this document handler + */ + public void setOwner(Object owner) { + this.owner = owner; + } + + /** + * Returns the handler for the element with specified name. + * + * @param name the name of the element + * @return the corresponding element handler + */ + public Class getElementHandler(String name) { + Class type = this.handlers.get(name); + if (type == null) { + throw new IllegalArgumentException("Unsupported element: " + name); + } + return type; + } + + /** + * Sets the handler for the element with specified name. + * + * @param name the name of the element + * @param handler the corresponding element handler + */ + public void setElementHandler(String name, Class handler) { + this.handlers.put(name, handler); + } + + /** + * Indicates whether the variable with specified identifier is defined. + * + * @param id the identifier + * @return @{code true} if the variable is defined; + * @{code false} otherwise + */ + public boolean hasVariable(String id) { + return this.environment.containsKey(id); + } + + /** + * Returns the value of the variable with specified identifier. + * + * @param id the identifier + * @return the value of the variable + */ + public Object getVariable(String id) { + if (!this.environment.containsKey(id)) { + throw new IllegalArgumentException("Unbound variable: " + id); + } + return this.environment.get(id); + } + + /** + * Sets new value of the variable with specified identifier. + * + * @param id the identifier + * @param value new value of the variable + */ + public void setVariable(String id, Object value) { + this.environment.put(id, value); + } + + /** + * Returns the array of readed objects. + * + * @return the array of readed objects + */ + public Object[] getObjects() { + return this.objects.toArray(); + } + + /** + * Adds the object to the list of readed objects. + * + * @param object the object that is readed from XML document + */ + void addObject(Object object) { + this.objects.add(object); + } + + /** + * Prepares this handler to read objects from XML document. + */ + @Override + public void startDocument() { + this.objects.clear(); + this.handler = null; + } + + /** + * Parses opening tag of XML element + * using corresponding element handler. + * + * @param uri the namespace URI, or the empty string + * if the element has no namespace URI or + * if namespace processing is not being performed + * @param localName the local name (without prefix), or the empty string + * if namespace processing is not being performed + * @param qName the qualified name (with prefix), or the empty string + * if qualified names are not available + * @param attributes the attributes attached to the element + */ + @Override + public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { + ElementHandler parent = this.handler; + try { + this.handler = getElementHandler(qName).newInstance(); + this.handler.setOwner(this); + this.handler.setParent(parent); + } + catch (Exception exception) { + throw new SAXException(exception); + } + for (int i = 0; i < attributes.getLength(); i++) + try { + String name = attributes.getQName(i); + String value = attributes.getValue(i); + this.handler.addAttribute(name, value); + } + catch (RuntimeException exception) { + handleException(exception); + } + + this.handler.startElement(); + } + + /** + * Parses closing tag of XML element + * using corresponding element handler. + * + * @param uri the namespace URI, or the empty string + * if the element has no namespace URI or + * if namespace processing is not being performed + * @param localName the local name (without prefix), or the empty string + * if namespace processing is not being performed + * @param qName the qualified name (with prefix), or the empty string + * if qualified names are not available + */ + @Override + public void endElement(String uri, String localName, String qName) { + try { + this.handler.endElement(); + } + catch (RuntimeException exception) { + handleException(exception); + } + finally { + this.handler = this.handler.getParent(); + } + } + + /** + * Parses character data inside XML element. + * + * @param chars the array of characters + * @param start the start position in the character array + * @param length the number of characters to use + */ + @Override + public void characters(char[] chars, int start, int length) { + if (this.handler != null) { + try { + while (0 < length--) { + this.handler.addCharacter(chars[start++]); + } + } + catch (RuntimeException exception) { + handleException(exception); + } + } + } + + /** + * Handles an exception using current exception listener. + * + * @param exception an exception to handle + * @see #setExceptionListener + */ + public void handleException(Exception exception) { + if (this.listener == null) { + throw new IllegalStateException(exception); + } + this.listener.exceptionThrown(exception); + } + + /** + * Starts parsing of the specified input source. + * + * @param input the input source to parse + */ + public void parse(InputSource input) { + try { + SAXParserFactory.newInstance().newSAXParser().parse(input, this); + } + catch (ParserConfigurationException exception) { + handleException(exception); + } + catch (SAXException wrapper) { + Exception exception = wrapper.getException(); + if (exception == null) { + exception = wrapper; + } + handleException(exception); + } + catch (IOException exception) { + handleException(exception); + } + } + + /** + * Resolves class by name using current class loader. + * This method handles exception using current exception listener. + * + * @param name the name of the class + * @return the object that represents the class + */ + public Class findClass(String name) { + try { + return ClassFinder.resolveClass(name, getClassLoader()); + } + catch (ClassNotFoundException exception) { + handleException(exception); + return null; + } + } +} diff --git a/jdk/src/share/classes/com/sun/beans/decoder/DoubleElementHandler.java b/jdk/src/share/classes/com/sun/beans/decoder/DoubleElementHandler.java new file mode 100644 index 00000000000..e0f58677627 --- /dev/null +++ b/jdk/src/share/classes/com/sun/beans/decoder/DoubleElementHandler.java @@ -0,0 +1,63 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.beans.decoder; + +/** + * This class is intended to handle <double> element. + * This element specifies {@code double} values. + * The class {@link Double} is used as wrapper for these values. + * The result value is created from text of the body of this element. + * The body parsing is described in the class {@link StringElementHandler}. + * For example:
+ * <double>1.23e45</double>
+ * is shortcut to
+ * <method name="valueOf" class="java.lang.Double">
+ *     <string>1.23e45</string>
+ * </method>
+ * which is equivalent to {@code Double.valueOf("1.23e45")} in Java code. + *

The following atribute is supported: + *

+ *
id + *
the identifier of the variable that is intended to store the result + *
+ * + * @since 1.7 + * + * @author Sergey A. Malenkov + */ +final class DoubleElementHandler extends StringElementHandler { + + /** + * Creates {@code double} value from + * the text of the body of this element. + * + * @param argument the text of the body + * @return evaluated {@code double} value + */ + @Override + public Object getValue(String argument) { + return Double.valueOf(argument); + } +} diff --git a/jdk/src/share/classes/com/sun/beans/decoder/ElementHandler.java b/jdk/src/share/classes/com/sun/beans/decoder/ElementHandler.java new file mode 100644 index 00000000000..ca85cd6ed08 --- /dev/null +++ b/jdk/src/share/classes/com/sun/beans/decoder/ElementHandler.java @@ -0,0 +1,224 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.beans.decoder; + +/** + * The base class for element handlers. + * + * @since 1.7 + * + * @author Sergey A. Malenkov + * + * @see DocumentHandler + */ +public abstract class ElementHandler { + private DocumentHandler owner; + private ElementHandler parent; + + private String id; + + /** + * Returns the document handler that creates this element handler. + * + * @return the owner document handler + */ + public final DocumentHandler getOwner() { + return this.owner; + } + + /** + * Sets the document handler that creates this element handler. + * The owner document handler should be set after instantiation. + * Such approach is used to simplify the extensibility. + * + * @param owner the owner document handler + * @see DocumentHandler#startElement + */ + final void setOwner(DocumentHandler owner) { + if (owner == null) { + throw new IllegalArgumentException("Every element should have owner"); + } + this.owner = owner; + } + + /** + * Returns the element handler that contains this one. + * + * @return the parent element handler + */ + public final ElementHandler getParent() { + return this.parent; + } + + /** + * Sets the element handler that contains this one. + * The parent element handler should be set after instantiation. + * Such approach is used to simplify the extensibility. + * + * @param parent the parent element handler + * @see DocumentHandler#startElement + */ + final void setParent(ElementHandler parent) { + this.parent = parent; + } + + /** + * Returns the value of the variable with specified identifier. + * + * @param id the identifier + * @return the value of the variable + */ + protected final Object getVariable(String id) { + if (id.equals(this.id)) { + ValueObject value = getValueObject(); + if (value.isVoid()) { + throw new IllegalStateException("The element does not return value"); + } + return value.getValue(); + } + return (this.parent != null) + ? this.parent.getVariable(id) + : this.owner.getVariable(id); + } + + /** + * Returns the value of the parent element. + * + * @return the value of the parent element + */ + protected Object getContextBean() { + if (this.parent != null) { + ValueObject value = this.parent.getValueObject(); + if (!value.isVoid()) { + return value.getValue(); + } + throw new IllegalStateException("The outer element does not return value"); + } else { + Object value = this.owner.getOwner(); + if (value != null) { + return value; + } + throw new IllegalStateException("The topmost element does not have context"); + } + } + + /** + * Parses attributes of the element. + * By default, the following atribute is supported: + *
+ *
id + *
the identifier of the variable that is intended to store the result + *
+ * + * @param name the attribute name + * @param value the attribute value + */ + public void addAttribute(String name, String value) { + if (name.equals("id")) { // NON-NLS: the attribute name + this.id = value; + } else { + throw new IllegalArgumentException("Unsupported attribute: " + name); + } + } + + /** + * This method is called before parsing of the element's body. + * All attributes are parsed at this point. + * By default, do nothing. + */ + public void startElement() { + } + + /** + * This method is called after parsing of the element's body. + * By default, it calculates the value of this element. + * The following tasks are executing for any non-void value: + *
    + *
  1. If the {@code id} attribute is set + * the value of the variable with the specified identifier + * is set to the value of this element.
  2. + *
  3. This element is used as an argument of parent element if it is possible.
  4. + *
+ * + * @see #isArgument + */ + public void endElement() { + // do nothing if no value returned + ValueObject value = getValueObject(); + if (!value.isVoid()) { + if (this.id != null) { + this.owner.setVariable(this.id, value.getValue()); + } + if (isArgument()) { + if (this.parent != null) { + this.parent.addArgument(value.getValue()); + } else { + this.owner.addObject(value.getValue()); + } + } + } + } + + /** + * Adds the character that contained in this element. + * By default, only whitespaces are acceptable. + * + * @param ch the character + */ + public void addCharacter(char ch) { + if ((ch != ' ') && (ch != '\n') && (ch != '\t') && (ch != '\r')) { + throw new IllegalStateException("Illegal character with code " + (int) ch); + } + } + + /** + * Adds the argument that is used to calculate the value of this element. + * By default, no arguments are acceptable. + * + * @param argument the value of the element that contained in this one + */ + protected void addArgument(Object argument) { + throw new IllegalStateException("Could not add argument to simple element"); + } + + /** + * Tests whether the value of this element can be used + * as an argument of the element that contained in this one. + * + * @return {@code true} if the value of this element can be used + * as an argument of the element that contained in this one, + * {@code false} otherwise + */ + protected boolean isArgument() { + return this.id == null; + } + + /** + * Returns the value of this element. + * + * @return the value of this element + */ + protected abstract ValueObject getValueObject(); +} diff --git a/jdk/src/share/classes/com/sun/beans/decoder/FalseElementHandler.java b/jdk/src/share/classes/com/sun/beans/decoder/FalseElementHandler.java new file mode 100644 index 00000000000..6e8d786aa14 --- /dev/null +++ b/jdk/src/share/classes/com/sun/beans/decoder/FalseElementHandler.java @@ -0,0 +1,56 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.beans.decoder; + +/** + * This class is intended to handle <false> element. + * This element specifies {@code false} value. + * It should not contain body or inner elements. + * For example:
+ * <false/>
+ * is equivalent to {@code false} in Java code. + *

The following atribute is supported: + *

+ *
id + *
the identifier of the variable that is intended to store the result + *
+ * + * @since 1.7 + * + * @author Sergey A. Malenkov + */ +final class FalseElementHandler extends NullElementHandler { + + /** + * Returns {@code Boolean.FALSE} + * as a value of <false> element. + * + * @return {@code Boolean.FALSE} by default + */ + @Override + public Object getValue() { + return Boolean.FALSE; + } +} diff --git a/jdk/src/share/classes/com/sun/beans/decoder/FieldElementHandler.java b/jdk/src/share/classes/com/sun/beans/decoder/FieldElementHandler.java new file mode 100644 index 00000000000..ac255dde7fd --- /dev/null +++ b/jdk/src/share/classes/com/sun/beans/decoder/FieldElementHandler.java @@ -0,0 +1,189 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.beans.decoder; + +import com.sun.beans.finder.FieldFinder; + +import java.lang.reflect.Field; + +/** + * This class is intended to handle <field> element. + * This element simplifies access to the fields. + * If the {@code class} attribute is specified + * this element accesses static field of specified class. + * This element defines getter if it contains no argument. + * It returns the value of the field in this case. + * For example:
+ * <field name="TYPE" class="java.lang.Long"/>
+ * is equivalent to {@code Long.TYPE} in Java code. + * This element defines setter if it contains one argument. + * It does not return the value of the field in this case. + * For example:
+ * <field name="id"><int>0</int></field>
+ * is equivalent to {@code id = 0} in Java code. + *

The following atributes are supported: + *

+ *
name + *
the field name + *
class + *
the type is used for static fields only + *
id + *
the identifier of the variable that is intended to store the result + *
+ * + * @since 1.7 + * + * @author Sergey A. Malenkov + */ +final class FieldElementHandler extends AccessorElementHandler { + private Class type; + + /** + * Parses attributes of the element. + * The following atributes are supported: + *
+ *
name + *
the field name + *
class + *
the type is used for static fields only + *
id + *
the identifier of the variable that is intended to store the result + *
+ * + * @param name the attribute name + * @param value the attribute value + */ + @Override + public void addAttribute(String name, String value) { + if (name.equals("class")) { // NON-NLS: the attribute name + this.type = getOwner().findClass(value); + } else { + super.addAttribute(name, value); + } + } + + /** + * Tests whether the value of this element can be used + * as an argument of the element that contained in this one. + * + * @return {@code true} if the value of this element should be used + * as an argument of the element that contained in this one, + * {@code false} otherwise + */ + @Override + protected boolean isArgument() { + return super.isArgument() && (this.type != null); // only static accessor can be used an argument + } + + /** + * Returns the context of the field. + * The context of the static field is the class object. + * The context of the non-static field is the value of the parent element. + * + * @return the context of the field + */ + @Override + protected Object getContextBean() { + return (this.type != null) + ? this.type + : super.getContextBean(); + } + + /** + * Returns the value of the field with specified {@code name}. + * + * @param name the name of the field + * @return the value of the specified field + */ + @Override + protected Object getValue(String name) { + try { + return getFieldValue(getContextBean(), name); + } + catch (Exception exception) { + getOwner().handleException(exception); + } + return null; + } + + /** + * Sets the new value for the field with specified {@code name}. + * + * @param name the name of the field + * @param value the new value for the specified field + */ + @Override + protected void setValue(String name, Object value) { + try { + setFieldValue(getContextBean(), name, value); + } + catch (Exception exception) { + getOwner().handleException(exception); + } + } + + /** + * Performs the search of the field with specified {@code name} + * in specified context and returns its value. + * + * @param bean the context bean that contains field + * @param name the name of the field + * @return the value of the field + * @throws IllegalAccessException if the field is not accesible + * @throws NoSuchFieldException if the field is not found + */ + static Object getFieldValue(Object bean, String name) throws IllegalAccessException, NoSuchFieldException { + return findField(bean, name).get(bean); + } + + /** + * Performs the search of the field with specified {@code name} + * in specified context and updates its value. + * + * @param bean the context bean that contains field + * @param name the name of the field + * @param value the new value for the field + * @throws IllegalAccessException if the field is not accesible + * @throws NoSuchFieldException if the field is not found + */ + private static void setFieldValue(Object bean, String name, Object value) throws IllegalAccessException, NoSuchFieldException { + findField(bean, name).set(bean, value); + } + + /** + * Performs the search of the field + * with specified {@code name} in specified context. + * + * @param bean the context bean that contains field + * @param name the name of the field + * @return field object that represents found field + * @throws NoSuchFieldException if the field is not found + */ + private static Field findField(Object bean, String name) throws NoSuchFieldException { + return (bean instanceof Class) + ? FieldFinder.findStaticField((Class) bean, name) + : FieldFinder.findField(bean.getClass(), name); + } +} diff --git a/jdk/src/share/classes/com/sun/beans/decoder/FloatElementHandler.java b/jdk/src/share/classes/com/sun/beans/decoder/FloatElementHandler.java new file mode 100644 index 00000000000..08311b49f29 --- /dev/null +++ b/jdk/src/share/classes/com/sun/beans/decoder/FloatElementHandler.java @@ -0,0 +1,63 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.beans.decoder; + +/** + * This class is intended to handle <float> element. + * This element specifies {@code float} values. + * The class {@link Float} is used as wrapper for these values. + * The result value is created from text of the body of this element. + * The body parsing is described in the class {@link StringElementHandler}. + * For example:
+ * <float>-1.23</float>
+ * is shortcut to
+ * <method name="valueOf" class="java.lang.Float">
+ *     <string>-1.23</string>
+ * </method>
+ * which is equivalent to {@code Float.valueOf("-1.23")} in Java code. + *

The following atribute is supported: + *

+ *
id + *
the identifier of the variable that is intended to store the result + *
+ * + * @since 1.7 + * + * @author Sergey A. Malenkov + */ +final class FloatElementHandler extends StringElementHandler { + + /** + * Creates {@code float} value from + * the text of the body of this element. + * + * @param argument the text of the body + * @return evaluated {@code float} value + */ + @Override + public Object getValue(String argument) { + return Float.valueOf(argument); + } +} diff --git a/jdk/src/share/classes/com/sun/beans/decoder/IntElementHandler.java b/jdk/src/share/classes/com/sun/beans/decoder/IntElementHandler.java new file mode 100644 index 00000000000..ec5063fcd8e --- /dev/null +++ b/jdk/src/share/classes/com/sun/beans/decoder/IntElementHandler.java @@ -0,0 +1,63 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.beans.decoder; + +/** + * This class is intended to handle <int> element. + * This element specifies {@code int} values. + * The class {@link Integer} is used as wrapper for these values. + * The result value is created from text of the body of this element. + * The body parsing is described in the class {@link StringElementHandler}. + * For example:
+ * <int>-1</int>
+ * is shortcut to
+ * <method name="decode" class="java.lang.Integer">
+ *     <string>-1</string>
+ * </method>
+ * which is equivalent to {@code Integer.decode("-1")} in Java code. + *

The following atribute is supported: + *

+ *
id + *
the identifier of the variable that is intended to store the result + *
+ * + * @since 1.7 + * + * @author Sergey A. Malenkov + */ +final class IntElementHandler extends StringElementHandler { + + /** + * Creates {@code int} value from + * the text of the body of this element. + * + * @param argument the text of the body + * @return evaluated {@code int} value + */ + @Override + public Object getValue(String argument) { + return Integer.decode(argument); + } +} diff --git a/jdk/src/share/classes/com/sun/beans/decoder/JavaElementHandler.java b/jdk/src/share/classes/com/sun/beans/decoder/JavaElementHandler.java new file mode 100644 index 00000000000..2d416a139fb --- /dev/null +++ b/jdk/src/share/classes/com/sun/beans/decoder/JavaElementHandler.java @@ -0,0 +1,151 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.beans.decoder; + +import java.beans.XMLDecoder; + +/** + * This class is intended to handle <java> element. + * Each element that appears in the body of this element + * is evaluated in the context of the decoder itself. + * Typically this outer context is used to retrieve the owner of the decoder, + * which can be set before reading the archive. + *

The following atributes are supported: + *

+ *
version + *
the Java version (not supported) + *
class + *
the type of preferable parser (not supported) + *
id + *
the identifier of the variable that is intended to store the result + *
+ * + * @see DocumentHandler#getOwner + * @see DocumentHandler#setOwner + * @since 1.7 + * + * @author Sergey A. Malenkov + */ +final class JavaElementHandler extends ElementHandler { + private Class type; + private ValueObject value; + + /** + * Parses attributes of the element. + * The following atributes are supported: + *
+ *
version + *
the Java version (not supported) + *
class + *
the type of preferable parser (not supported) + *
id + *
the identifier of the variable that is intended to store the result + *
+ * + * @param name the attribute name + * @param value the attribute value + */ + @Override + public void addAttribute(String name, String value) { + if (name.equals("version")) { // NON-NLS: the attribute name + // unsupported attribute + } else if (name.equals("class")) { // NON-NLS: the attribute name + // check class for owner + this.type = getOwner().findClass(value); + } else { + super.addAttribute(name, value); + } + } + + /** + * Adds the argument to the list of readed objects. + * + * @param argument the value of the element that contained in this one + */ + @Override + protected void addArgument(Object argument) { + getOwner().addObject(argument); + } + + /** + * Tests whether the value of this element can be used + * as an argument of the element that contained in this one. + * + * @return {@code true} if the value of this element should be used + * as an argument of the element that contained in this one, + * {@code false} otherwise + */ + @Override + protected boolean isArgument() { + return false; // do not use owner as object + } + + /** + * Returns the value of this element. + * + * @return the value of this element + */ + @Override + protected ValueObject getValueObject() { + if (this.value == null) { + this.value = ValueObjectImpl.create(getValue()); + } + return this.value; + } + + /** + * Returns the owner of the owner document handler + * as a value of <java> element. + * + * @return the owner of the owner document handler + */ + private Object getValue() { + Object owner = getOwner().getOwner(); + if ((this.type == null) || isValid(owner)) { + return owner; + } + if (owner instanceof XMLDecoder) { + XMLDecoder decoder = (XMLDecoder) owner; + owner = decoder.getOwner(); + if (isValid(owner)) { + return owner; + } + } + throw new IllegalStateException("Unexpected owner class: " + owner.getClass().getName()); + } + + /** + * Validates the owner of the <java> element. + * The owner is valid if it is {@code null} or an instance + * of the class specified by the {@code class} attribute. + * + * @param owner the owner of the <java> element + * @return {@code true} if the {@code owner} is valid; + * {@code false} otherwise + */ + private boolean isValid(Object owner) { + return (owner == null) || this.type.isInstance(owner); + } +} diff --git a/jdk/src/share/classes/com/sun/beans/decoder/LongElementHandler.java b/jdk/src/share/classes/com/sun/beans/decoder/LongElementHandler.java new file mode 100644 index 00000000000..a26f2f57fb6 --- /dev/null +++ b/jdk/src/share/classes/com/sun/beans/decoder/LongElementHandler.java @@ -0,0 +1,63 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.beans.decoder; + +/** + * This class is intended to handle <long> element. + * This element specifies {@code long} values. + * The class {@link Long} is used as wrapper for these values. + * The result value is created from text of the body of this element. + * The body parsing is described in the class {@link StringElementHandler}. + * For example:
+ * <long>0xFFFF</long>
+ * is shortcut to
+ * <method name="decode" class="java.lang.Long">
+ *     <string>0xFFFF</string>
+ * </method>
+ * which is equivalent to {@code Long.decode("0xFFFF")} in Java code. + *

The following atribute is supported: + *

+ *
id + *
the identifier of the variable that is intended to store the result + *
+ * + * @since 1.7 + * + * @author Sergey A. Malenkov + */ +final class LongElementHandler extends StringElementHandler { + + /** + * Creates {@code long} value from + * the text of the body of this element. + * + * @param argument the text of the body + * @return evaluated {@code long} value + */ + @Override + public Object getValue(String argument) { + return Long.decode(argument); + } +} diff --git a/jdk/src/share/classes/com/sun/beans/decoder/MethodElementHandler.java b/jdk/src/share/classes/com/sun/beans/decoder/MethodElementHandler.java new file mode 100644 index 00000000000..34d030c90b3 --- /dev/null +++ b/jdk/src/share/classes/com/sun/beans/decoder/MethodElementHandler.java @@ -0,0 +1,109 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.beans.decoder; + +import com.sun.beans.finder.MethodFinder; + +import java.lang.reflect.Method; + +/** + * This class is intended to handle <method> element. + * It describes invocation of the method. + * The {@code name} attribute denotes + * the name of the method to invoke. + * If the {@code class} attribute is specified + * this element invokes static method of specified class. + * The inner elements specifies the arguments of the method. + * For example:
+ * <method name="valueOf" class="java.lang.Long">
+ *     <string>10</string>
+ * </method>
+ * is equivalent to {@code Long.valueOf("10")} in Java code. + *

The following atributes are supported: + *

+ *
name + *
the method name + *
class + *
the type of object for instantiation + *
id + *
the identifier of the variable that is intended to store the result + *
+ * + * @since 1.7 + * + * @author Sergey A. Malenkov + */ +final class MethodElementHandler extends NewElementHandler { + private String name; + + /** + * Parses attributes of the element. + * The following atributes are supported: + *
+ *
name + *
the method name + *
class + *
the type of object for instantiation + *
id + *
the identifier of the variable that is intended to store the result + *
+ * + * @param name the attribute name + * @param value the attribute value + */ + @Override + public void addAttribute(String name, String value) { + if (name.equals("name")) { // NON-NLS: the attribute name + this.name = value; + } else { + super.addAttribute(name, value); + } + } + + /** + * Returns the result of method execution. + * + * @param type the base class + * @param args the array of arguments + * @return the value of this element + * @throws Exception if calculation is failed + */ + @Override + protected ValueObject getValueObject(Class type, Object[] args) throws Exception { + Object bean = getContextBean(); + Class[] types = getArgumentTypes(args); + Method method = (type != null) + ? MethodFinder.findStaticMethod(type, this.name, types) + : MethodFinder.findMethod(bean.getClass(), this.name, types); + + if (method.isVarArgs()) { + args = getArguments(args, method.getParameterTypes()); + } + Object value = method.invoke(bean, args); + return method.getReturnType().equals(void.class) + ? ValueObjectImpl.VOID + : ValueObjectImpl.create(value); + } +} diff --git a/jdk/src/share/classes/com/sun/beans/decoder/NewElementHandler.java b/jdk/src/share/classes/com/sun/beans/decoder/NewElementHandler.java new file mode 100644 index 00000000000..fc7debfc500 --- /dev/null +++ b/jdk/src/share/classes/com/sun/beans/decoder/NewElementHandler.java @@ -0,0 +1,205 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.beans.decoder; + +import com.sun.beans.finder.ConstructorFinder; + +import java.lang.reflect.Array; +import java.lang.reflect.Constructor; + +import java.util.ArrayList; +import java.util.List; + +/** + * This class is intended to handle <new> element. + * It describes instantiation of the object. + * The {@code class} attribute denotes + * the name of the class to instantiate. + * The inner elements specifies the arguments of the constructor. + * For example:
+ * <new class="java.lang.Long">
+ *     <string>10</string>
+ * </new>
+ * is equivalent to {@code new Long("10")} in Java code. + *

The following atributes are supported: + *

+ *
class + *
the type of object for instantiation + *
id + *
the identifier of the variable that is intended to store the result + *
+ * + * @since 1.7 + * + * @author Sergey A. Malenkov + */ +class NewElementHandler extends ElementHandler { + private List arguments = new ArrayList(); + private ValueObject value = ValueObjectImpl.VOID; + + private Class type; + + /** + * Parses attributes of the element. + * The following atributes are supported: + *
+ *
class + *
the type of object for instantiation + *
id + *
the identifier of the variable that is intended to store the result + *
+ * + * @param name the attribute name + * @param value the attribute value + */ + @Override + public void addAttribute(String name, String value) { + if (name.equals("class")) { // NON-NLS: the attribute name + this.type = getOwner().findClass(value); + } else { + super.addAttribute(name, value); + } + } + + /** + * Adds the argument to the list of arguments + * that is used to calculate the value of this element. + * + * @param argument the value of the element that contained in this one + */ + @Override + protected final void addArgument(Object argument) { + if (this.arguments == null) { + throw new IllegalStateException("Could not add argument to evaluated element"); + } + this.arguments.add(argument); + } + + /** + * Returns the context of the method. + * The context of the static method is the class object. + * The context of the non-static method is the value of the parent element. + * + * @return the context of the method + */ + @Override + protected final Object getContextBean() { + return (this.type != null) + ? this.type + : super.getContextBean(); + } + + /** + * Returns the value of this element. + * + * @return the value of this element + */ + @Override + protected final ValueObject getValueObject() { + if (this.arguments != null) { + try { + this.value = getValueObject(this.type, this.arguments.toArray()); + } + catch (Exception exception) { + getOwner().handleException(exception); + } + finally { + this.arguments = null; + } + } + return this.value; + } + + /** + * Calculates the value of this element + * using the base class and the array of arguments. + * By default, it creates an instance of the base class. + * This method should be overridden in those handlers + * that extend behavior of this element. + * + * @param type the base class + * @param args the array of arguments + * @return the value of this element + * @throws Exception if calculation is failed + */ + ValueObject getValueObject(Class type, Object[] args) throws Exception { + if (type == null) { + throw new IllegalArgumentException("Class name is not set"); + } + Class[] types = getArgumentTypes(args); + Constructor constructor = ConstructorFinder.findConstructor(type, types); + if (constructor.isVarArgs()) { + args = getArguments(args, constructor.getParameterTypes()); + } + return ValueObjectImpl.create(constructor.newInstance(args)); + } + + /** + * Converts the array of arguments to the array of corresponding classes. + * If argument is {@code null} the class is {@code null} too. + * + * @param arguments the array of arguments + * @return the array of corresponding classes + */ + static Class[] getArgumentTypes(Object[] arguments) { + Class[] types = new Class[arguments.length]; + for (int i = 0; i < arguments.length; i++) { + if (arguments[i] != null) { + types[i] = arguments[i].getClass(); + } + } + return types; + } + + /** + * Resolves variable arguments. + * + * @param arguments the array of arguments + * @param types the array of parameter types + * @return the resolved array of arguments + */ + static Object[] getArguments(Object[] arguments, Class[] types) { + int index = types.length - 1; + if (types.length == arguments.length) { + Object argument = arguments[index]; + if (argument == null) { + return arguments; + } + Class type = types[index]; + if (type.isAssignableFrom(argument.getClass())) { + return arguments; + } + } + int length = arguments.length - index; + Class type = types[index].getComponentType(); + Object array = Array.newInstance(type, length); + System.arraycopy(arguments, index, array, 0, length); + + Object[] args = new Object[types.length]; + System.arraycopy(arguments, 0, args, 0, index); + args[index] = array; + return args; + } +} diff --git a/jdk/src/share/classes/com/sun/beans/decoder/NullElementHandler.java b/jdk/src/share/classes/com/sun/beans/decoder/NullElementHandler.java new file mode 100644 index 00000000000..a3e2d699c39 --- /dev/null +++ b/jdk/src/share/classes/com/sun/beans/decoder/NullElementHandler.java @@ -0,0 +1,76 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.beans.decoder; + +/** + * This class is intended to handle <null> element. + * This element specifies {@code null} value. + * It should not contain body or inner elements. + * For example:
+ * <null/>
+ * is equivalent to {@code null} in Java code. + *

The following atribute is supported: + *

+ *
id + *
the identifier of the variable that is intended to store the result + *
+ * + * @since 1.7 + * + * @author Sergey A. Malenkov + */ +class NullElementHandler extends ElementHandler implements ValueObject { + + /** + * Returns the value of this element. + * + * @return the value of this element + */ + @Override + protected final ValueObject getValueObject() { + return this; + } + + /** + * Returns {@code null} + * as a value of <null> element. + * This method should be overridden in those handlers + * that extend behavior of this element. + * + * @return {@code null} by default + */ + public Object getValue() { + return null; + } + + /** + * Returns {@code void} state of this value object. + * + * @return {@code false} always + */ + public final boolean isVoid() { + return false; + } +} diff --git a/jdk/src/share/classes/com/sun/beans/decoder/ObjectElementHandler.java b/jdk/src/share/classes/com/sun/beans/decoder/ObjectElementHandler.java new file mode 100644 index 00000000000..3ab5ddca942 --- /dev/null +++ b/jdk/src/share/classes/com/sun/beans/decoder/ObjectElementHandler.java @@ -0,0 +1,168 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.beans.decoder; + +import java.beans.Expression; + +import static java.util.Locale.ENGLISH; + +/** + * This class is intended to handle <object> element. + * This element looks like <void> element, + * but its value is always used as an argument for element + * that contains this one. + *

The following atributes are supported: + *

+ *
class + *
the type is used for static methods and fields + *
method + *
the method name + *
property + *
the property name + *
index + *
the property index + *
field + *
the field name + *
idref + *
the identifier to refer to the variable + *
id + *
the identifier of the variable that is intended to store the result + *
+ * + * @since 1.7 + * + * @author Sergey A. Malenkov + */ +class ObjectElementHandler extends NewElementHandler { + private String idref; + private String field; + private Integer index; + private String property; + private String method; + + /** + * Parses attributes of the element. + * The following atributes are supported: + *
+ *
class + *
the type is used for static methods and fields + *
method + *
the method name + *
property + *
the property name + *
index + *
the property index + *
field + *
the field name + *
idref + *
the identifier to refer to the variable + *
id + *
the identifier of the variable that is intended to store the result + *
+ * + * @param name the attribute name + * @param value the attribute value + */ + @Override + public final void addAttribute(String name, String value) { + if (name.equals("idref")) { // NON-NLS: the attribute name + this.idref = value; + } else if (name.equals("field")) { // NON-NLS: the attribute name + this.field = value; + } else if (name.equals("index")) { // NON-NLS: the attribute name + this.index = Integer.valueOf(value); + addArgument(this.index); // hack for compatibility + } else if (name.equals("property")) { // NON-NLS: the attribute name + this.property = value; + } else if (name.equals("method")) { // NON-NLS: the attribute name + this.method = value; + } else { + super.addAttribute(name, value); + } + } + + /** + * Calculates the value of this element + * if the field attribute or the idref attribute is set. + */ + @Override + public final void startElement() { + if ((this.field != null) || (this.idref != null)) { + getValueObject(); + } + } + + /** + * Tests whether the value of this element can be used + * as an argument of the element that contained in this one. + * + * @return {@code true} if the value of this element can be used + * as an argument of the element that contained in this one, + * {@code false} otherwise + */ + @Override + protected boolean isArgument() { + return true; // hack for compatibility + } + + /** + * Creates the value of this element. + * + * @param type the base class + * @param args the array of arguments + * @return the value of this element + * @throws Exception if calculation is failed + */ + @Override + protected final ValueObject getValueObject(Class type, Object[] args) throws Exception { + if (this.field != null) { + return ValueObjectImpl.create(FieldElementHandler.getFieldValue(getContextBean(), this.field)); + } + if (this.idref != null) { + return ValueObjectImpl.create(getVariable(this.idref)); + } + Object bean = getContextBean(); + String name; + if (this.index != null) { + name = (args.length == 2) + ? PropertyElementHandler.SETTER + : PropertyElementHandler.GETTER; + } else if (this.property != null) { + name = (args.length == 1) + ? PropertyElementHandler.SETTER + : PropertyElementHandler.GETTER; + + if (0 < this.property.length()) { + name += this.property.substring(0, 1).toUpperCase(ENGLISH) + this.property.substring(1); + } + } else { + name = (this.method != null) && (0 < this.method.length()) + ? this.method + : "new"; // NON-NLS: the constructor marker + } + Expression expression = new Expression(bean, name, args); + return ValueObjectImpl.create(expression.getValue()); + } +} diff --git a/jdk/src/share/classes/com/sun/beans/decoder/PropertyElementHandler.java b/jdk/src/share/classes/com/sun/beans/decoder/PropertyElementHandler.java new file mode 100644 index 00000000000..dcc55062945 --- /dev/null +++ b/jdk/src/share/classes/com/sun/beans/decoder/PropertyElementHandler.java @@ -0,0 +1,287 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.beans.decoder; + +import com.sun.beans.finder.MethodFinder; + +import java.beans.IndexedPropertyDescriptor; +import java.beans.IntrospectionException; +import java.beans.Introspector; +import java.beans.PropertyDescriptor; + +import java.lang.reflect.Array; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; + +/** + * This class is intended to handle <property> element. + * This element simplifies access to the properties. + * If the {@code index} attribute is specified + * this element uses additional {@code int} parameter. + * If the {@code name} attribute is not specified + * this element uses method "get" as getter + * and method "set" as setter. + * This element defines getter if it contains no argument. + * It returns the value of the property in this case. + * For example:
+ * <property name="object" index="10"/>
+ * is shortcut to
+ * <method name="getObject">
+ *     <int>10</int>
+ * </method>
+ * which is equivalent to {@code getObject(10)} in Java code. + * This element defines setter if it contains one argument. + * It does not return the value of the property in this case. + * For example:
+ * <property><int>0</int></property>
+ * is shortcut to
+ * <method name="set">
+ *     <int>0</int>
+ * </method>
+ * which is equivalent to {@code set(0)} in Java code. + *

The following atributes are supported: + *

+ *
name + *
the property name + *
index + *
the property index + *
id + *
the identifier of the variable that is intended to store the result + *
+ * + * @since 1.7 + * + * @author Sergey A. Malenkov + */ +final class PropertyElementHandler extends AccessorElementHandler { + static final String GETTER = "get"; // NON-NLS: the getter prefix + static final String SETTER = "set"; // NON-NLS: the setter prefix + + private Integer index; + + /** + * Parses attributes of the element. + * The following atributes are supported: + *
+ *
name + *
the property name + *
index + *
the property index + *
id + *
the identifier of the variable that is intended to store the result + *
+ * + * @param name the attribute name + * @param value the attribute value + */ + @Override + public void addAttribute(String name, String value) { + if (name.equals("index")) { // NON-NLS: the attribute name + this.index = Integer.valueOf(value); + } else { + super.addAttribute(name, value); + } + } + + /** + * Tests whether the value of this element can be used + * as an argument of the element that contained in this one. + * + * @return {@code true} if the value of this element should be used + * as an argument of the element that contained in this one, + * {@code false} otherwise + */ + @Override + protected boolean isArgument() { + return false; // non-static accessor cannot be used an argument + } + + /** + * Returns the value of the property with specified {@code name}. + * + * @param name the name of the property + * @return the value of the specified property + */ + @Override + protected Object getValue(String name) { + try { + return getPropertyValue(getContextBean(), name, this.index); + } + catch (Exception exception) { + getOwner().handleException(exception); + } + return null; + } + + /** + * Sets the new value for the property with specified {@code name}. + * + * @param name the name of the property + * @param value the new value for the specified property + */ + @Override + protected void setValue(String name, Object value) { + try { + setPropertyValue(getContextBean(), name, this.index, value); + } + catch (Exception exception) { + getOwner().handleException(exception); + } + } + + /** + * Performs the search of the getter for the property + * with specified {@code name} in specified class + * and returns value of the property. + * + * @param bean the context bean that contains property + * @param name the name of the property + * @param index the index of the indexed property + * @return the value of the property + * @throws IllegalAccessException if the property is not accesible + * @throws IntrospectionException if the bean introspection is failed + * @throws InvocationTargetException if the getter cannot be invoked + * @throws NoSuchMethodException if the getter is not found + */ + private static Object getPropertyValue(Object bean, String name, Integer index) throws IllegalAccessException, IntrospectionException, InvocationTargetException, NoSuchMethodException { + Class type = bean.getClass(); + if (index == null) { + return findGetter(type, name).invoke(bean); + } else if (type.isArray() && (name == null)) { + return Array.get(bean, index); + } else { + return findGetter(type, name, int.class).invoke(bean, index); + } + } + + /** + * Performs the search of the setter for the property + * with specified {@code name} in specified class + * and updates value of the property. + * + * @param bean the context bean that contains property + * @param name the name of the property + * @param index the index of the indexed property + * @param value the new value for the property + * @throws IllegalAccessException if the property is not accesible + * @throws IntrospectionException if the bean introspection is failed + * @throws InvocationTargetException if the setter cannot be invoked + * @throws NoSuchMethodException if the setter is not found + */ + private static void setPropertyValue(Object bean, String name, Integer index, Object value) throws IllegalAccessException, IntrospectionException, InvocationTargetException, NoSuchMethodException { + Class type = bean.getClass(); + Class param = (value != null) + ? value.getClass() + : null; + + if (index == null) { + findSetter(type, name, param).invoke(bean, value); + } else if (type.isArray() && (name == null)) { + Array.set(bean, index, value); + } else { + findSetter(type, name, int.class, param).invoke(bean, index, value); + } + } + + /** + * Performs the search of the getter for the property + * with specified {@code name} in specified class. + * + * @param type the class that contains method + * @param name the name of the property + * @param args the method arguments + * @return method object that represents found getter + * @throws IntrospectionException if the bean introspection is failed + * @throws NoSuchMethodException if method is not found + */ + private static Method findGetter(Class type, String name, Class...args) throws IntrospectionException, NoSuchMethodException { + if (name == null) { + return MethodFinder.findInstanceMethod(type, GETTER, args); + } + PropertyDescriptor pd = getProperty(type, name); + if (args.length == 0) { + Method method = pd.getReadMethod(); + if (method != null) { + return method; + } + } else if (pd instanceof IndexedPropertyDescriptor) { + IndexedPropertyDescriptor ipd = (IndexedPropertyDescriptor) pd; + Method method = ipd.getIndexedReadMethod(); + if (method != null) { + return method; + } + } + throw new IntrospectionException("Could not find getter for the " + name + " property"); + } + + /** + * Performs the search of the setter for the property + * with specified {@code name} in specified class. + * + * @param type the class that contains method + * @param name the name of the property + * @param args the method arguments + * @return method object that represents found setter + * @throws IntrospectionException if the bean introspection is failed + * @throws NoSuchMethodException if method is not found + */ + private static Method findSetter(Class type, String name, Class...args) throws IntrospectionException, NoSuchMethodException { + if (name == null) { + return MethodFinder.findInstanceMethod(type, SETTER, args); + } + PropertyDescriptor pd = getProperty(type, name); + if (args.length == 1) { + Method method = pd.getWriteMethod(); + if (method != null) { + return method; + } + } else if (pd instanceof IndexedPropertyDescriptor) { + IndexedPropertyDescriptor ipd = (IndexedPropertyDescriptor) pd; + Method method = ipd.getIndexedWriteMethod(); + if (method != null) { + return method; + } + } + throw new IntrospectionException("Could not find setter for the " + name + " property"); + } + + /** + * Performs the search of the descriptor for the property + * with specified {@code name} in specified class. + * + * @param type the class to introspect + * @param name the property name + * @return descriptor for the named property + * @throws IntrospectionException if property descriptor is not found + */ + private static PropertyDescriptor getProperty(Class type, String name) throws IntrospectionException { + for (PropertyDescriptor pd : Introspector.getBeanInfo(type).getPropertyDescriptors()) { + if (name.equals(pd.getName())) { + return pd; + } + } + throw new IntrospectionException("Could not find the " + name + " property descriptor"); + } +} diff --git a/jdk/src/share/classes/com/sun/beans/decoder/ShortElementHandler.java b/jdk/src/share/classes/com/sun/beans/decoder/ShortElementHandler.java new file mode 100644 index 00000000000..5f91e254424 --- /dev/null +++ b/jdk/src/share/classes/com/sun/beans/decoder/ShortElementHandler.java @@ -0,0 +1,63 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.beans.decoder; + +/** + * This class is intended to handle <short> element. + * This element specifies {@code short} values. + * The class {@link Short} is used as wrapper for these values. + * The result value is created from text of the body of this element. + * The body parsing is described in the class {@link StringElementHandler}. + * For example:
+ * <short>200</short>
+ * is shortcut to
+ * <method name="decode" class="java.lang.Short">
+ *     <string>200</string>
+ * </method>
+ * which is equivalent to {@code Short.decode("200")} in Java code. + *

The following atribute is supported: + *

+ *
id + *
the identifier of the variable that is intended to store the result + *
+ * + * @since 1.7 + * + * @author Sergey A. Malenkov + */ +final class ShortElementHandler extends StringElementHandler { + + /** + * Creates {@code short} value from + * the text of the body of this element. + * + * @param argument the text of the body + * @return evaluated {@code short} value + */ + @Override + public Object getValue(String argument) { + return Short.decode(argument); + } +} diff --git a/jdk/src/share/classes/com/sun/beans/decoder/StringElementHandler.java b/jdk/src/share/classes/com/sun/beans/decoder/StringElementHandler.java new file mode 100644 index 00000000000..6075f436aa0 --- /dev/null +++ b/jdk/src/share/classes/com/sun/beans/decoder/StringElementHandler.java @@ -0,0 +1,116 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.beans.decoder; + +/** + * This class is intended to handle <string> element. + * This element specifies {@link String} values. + * The result value is created from text of the body of this element. + * For example:
+ * <string>description</string>
+ * is equivalent to {@code "description"} in Java code. + * The value of inner element is calculated + * before adding to the string using {@link String#valueOf(Object)}. + * Note that all characters are used including whitespaces (' ', '\t', '\n', '\r'). + * So the value of the element
+ * <string><true></string>
+ * is not equal to the value of the element
+ * <string>
+ *     <true>
+ * </string>
+ *

The following atribute is supported: + *

+ *
id + *
the identifier of the variable that is intended to store the result + *
+ * + * @since 1.7 + * + * @author Sergey A. Malenkov + */ +public class StringElementHandler extends ElementHandler { + private StringBuilder sb = new StringBuilder(); + private ValueObject value = ValueObjectImpl.NULL; + + /** + * Adds the character that contained in this element. + * + * @param ch the character + */ + @Override + public final void addCharacter(char ch) { + if (this.sb == null) { + throw new IllegalStateException("Could not add chararcter to evaluated string element"); + } + this.sb.append(ch); + } + + /** + * Adds the string value of the argument to the string value of this element. + * + * @param argument the value of the element that contained in this one + */ + @Override + protected final void addArgument(Object argument) { + if (this.sb == null) { + throw new IllegalStateException("Could not add argument to evaluated string element"); + } + this.sb.append(argument); + } + + /** + * Returns the value of this element. + * + * @return the value of this element + */ + @Override + protected final ValueObject getValueObject() { + if (this.sb != null) { + try { + this.value = ValueObjectImpl.create(getValue(this.sb.toString())); + } + catch (RuntimeException exception) { + getOwner().handleException(exception); + } + finally { + this.sb = null; + } + } + return this.value; + } + + /** + * Returns the text of the body of this element. + * This method evaluates value from text of the body, + * and should be overridden in those handlers + * that extend behavior of this element. + * + * @param argument the text of the body + * @return evaluated value + */ + protected Object getValue(String argument) { + return argument; + } +} diff --git a/jdk/src/share/classes/com/sun/beans/decoder/TrueElementHandler.java b/jdk/src/share/classes/com/sun/beans/decoder/TrueElementHandler.java new file mode 100644 index 00000000000..faf8904d4d0 --- /dev/null +++ b/jdk/src/share/classes/com/sun/beans/decoder/TrueElementHandler.java @@ -0,0 +1,56 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.beans.decoder; + +/** + * This class is intended to handle <true> element. + * This element specifies {@code true} value. + * It should not contain body or inner elements. + * For example:
+ * <true/>
+ * is equivalent to {@code true} in Java code. + *

The following atribute is supported: + *

+ *
id + *
the identifier of the variable that is intended to store the result + *
+ * + * @since 1.7 + * + * @author Sergey A. Malenkov + */ +final class TrueElementHandler extends NullElementHandler { + + /** + * Returns {@code Boolean.TRUE} + * as a value of <true> element. + * + * @return {@code Boolean.TRUE} by default + */ + @Override + public Object getValue() { + return Boolean.TRUE; + } +} diff --git a/jdk/src/share/classes/com/sun/beans/decoder/ValueObject.java b/jdk/src/share/classes/com/sun/beans/decoder/ValueObject.java new file mode 100644 index 00000000000..04f28278e34 --- /dev/null +++ b/jdk/src/share/classes/com/sun/beans/decoder/ValueObject.java @@ -0,0 +1,50 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.beans.decoder; + +/** + * This interface represents the result of method execution. + * + * @since 1.7 + * + * @author Sergey A. Malenkov + */ +public interface ValueObject { + + /** + * Returns the result of method execution. + * + * @return the result of method execution + */ + Object getValue(); + + /** + * Returns {@code void} state of this value object. + * + * @return {@code true} if value can be ignored, + * {@code false} otherwise + */ + boolean isVoid(); +} diff --git a/jdk/src/share/classes/com/sun/beans/decoder/ValueObjectImpl.java b/jdk/src/share/classes/com/sun/beans/decoder/ValueObjectImpl.java new file mode 100644 index 00000000000..cb891fe6c61 --- /dev/null +++ b/jdk/src/share/classes/com/sun/beans/decoder/ValueObjectImpl.java @@ -0,0 +1,88 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.beans.decoder; + +/** + * This utility class provides {@code static} method + * to create the object that contains the result of method execution. + * + * @since 1.7 + * + * @author Sergey A. Malenkov + */ +final class ValueObjectImpl implements ValueObject { + static final ValueObject NULL = new ValueObjectImpl(null); + static final ValueObject VOID = new ValueObjectImpl(); + + /** + * Returns the object that describes returning value. + * + * @param value the result of method execution + * @return the object that describes value + */ + static ValueObject create(Object value) { + return (value != null) + ? new ValueObjectImpl(value) + : NULL; + } + + private Object value; + private boolean isVoid; + + /** + * Creates the object that describes returning void value. + */ + private ValueObjectImpl() { + this.isVoid = true; + } + + /** + * Creates the object that describes returning non-void value. + * + * @param value the result of method execution + */ + private ValueObjectImpl(Object value) { + this.value = value; + } + + /** + * Returns the result of method execution. + * + * @return the result of method execution + */ + public Object getValue() { + return this.value; + } + + /** + * Returns {@code void} state of this value object. + * + * @return {@code true} if value should be ignored, + * {@code false} otherwise + */ + public boolean isVoid() { + return this.isVoid; + } +} diff --git a/jdk/src/share/classes/com/sun/beans/decoder/VarElementHandler.java b/jdk/src/share/classes/com/sun/beans/decoder/VarElementHandler.java new file mode 100644 index 00000000000..d948c18e538 --- /dev/null +++ b/jdk/src/share/classes/com/sun/beans/decoder/VarElementHandler.java @@ -0,0 +1,82 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.beans.decoder; + +/** + * This class is intended to handle <var> element. + * This element retrieves the value of specified variable. + * For example:
+ * <var id="id1" idref="id2"/>
+ * is equivalent to {@code id1 = id2} in Java code. + *

The following atributes are supported: + *

+ *
idref + *
the identifier to refer to the variable + *
id + *
the identifier of the variable that is intended to store the result + *
+ * + * @since 1.7 + * + * @author Sergey A. Malenkov + */ +final class VarElementHandler extends ElementHandler { + private ValueObject value; + + /** + * Parses attributes of the element. + * The following atributes are supported: + *
+ *
idref + *
the identifier to refer to the variable + *
id + *
the identifier of the variable that is intended to store the result + *
+ * + * @param name the attribute name + * @param value the attribute value + */ + @Override + public void addAttribute(String name, String value) { + if (name.equals("idref")) { // NON-NLS: the attribute name + this.value = ValueObjectImpl.create(getVariable(value)); + } else { + super.addAttribute(name, value); + } + } + + /** + * Returns the value of this element. + * + * @return the value of this element + */ + @Override + protected ValueObject getValueObject() { + if (this.value == null) { + throw new IllegalArgumentException("Variable name is not set"); + } + return this.value; + } +} diff --git a/jdk/src/share/classes/com/sun/beans/decoder/VoidElementHandler.java b/jdk/src/share/classes/com/sun/beans/decoder/VoidElementHandler.java new file mode 100644 index 00000000000..44726a0f7a1 --- /dev/null +++ b/jdk/src/share/classes/com/sun/beans/decoder/VoidElementHandler.java @@ -0,0 +1,68 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.beans.decoder; + +/** + * This class is intended to handle <void> element. + * This element looks like <object> element, + * but its value is not used as an argument for element + * that contains this one. + *

The following atributes are supported: + *

+ *
class + *
the type is used for static methods and fields + *
method + *
the method name + *
property + *
the property name + *
index + *
the property index + *
field + *
the field name + *
idref + *
the identifier to refer to the variable + *
id + *
the identifier of the variable that is intended to store the result + *
+ * + * @since 1.7 + * + * @author Sergey A. Malenkov + */ +final class VoidElementHandler extends ObjectElementHandler { + + /** + * Tests whether the value of this element can be used + * as an argument of the element that contained in this one. + * + * @return {@code true} if the value of this element should be used + * as an argument of the element that contained in this one, + * {@code false} otherwise + */ + @Override + protected boolean isArgument() { + return false; // hack for compatibility + } +} diff --git a/jdk/src/share/classes/com/sun/beans/finder/AbstractFinder.java b/jdk/src/share/classes/com/sun/beans/finder/AbstractFinder.java new file mode 100644 index 00000000000..396d6cbf8f8 --- /dev/null +++ b/jdk/src/share/classes/com/sun/beans/finder/AbstractFinder.java @@ -0,0 +1,213 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.beans.finder; + +import java.util.HashMap; +import java.util.Map; + +/** + * This abstract class provides functionality + * to find a public method or constructor + * with specified parameter types. + * It supports a variable number of parameters. + * + * @since 1.7 + * + * @author Sergey A. Malenkov + */ +abstract class AbstractFinder { + private final Class[] args; + + /** + * Creates finder for array of classes of arguments. + * If a particular element of array equals {@code null}, + * than the appropriate pair of classes + * does not take into consideration. + * + * @param args array of classes of arguments + */ + protected AbstractFinder(Class[] args) { + this.args = args; + } + + /** + * Returns an array of {@code Class} objects + * that represent the formal parameter types of the method + * Returns an empty array if the method takes no parameters. + * + * @param method the object that represents method + * @return the parameter types of the method + */ + protected abstract Class[] getParameters(T method); + + /** + * Returns {@code true} if and only if the method + * was declared to take a variable number of arguments. + * + * @param method the object that represents method + * @return {@code true} if the method was declared + * to take a variable number of arguments; + * {@code false} otherwise + */ + protected abstract boolean isVarArgs(T method); + + /** + * Checks validness of the method. + * At least the valid method should be public. + * + * @param method the object that represents method + * @return {@code true} if the method is valid, + * {@code false} otherwise + */ + protected abstract boolean isValid(T method); + + /** + * Performs a search in the {@code methods} array. + * The one method is selected from the array of the valid methods. + * The list of parameters of the selected method shows + * the best correlation with the list of arguments + * specified at class initialization. + * If more than one method is both accessible and applicable + * to a method invocation, it is necessary to choose one + * to provide the descriptor for the run-time method dispatch. + * The most specific method should be chosen. + * + * @param methods the array of methods to search within + * @return the object that represents found method + * @throws NoSuchMethodException if no method was found or several + * methods meet the search criteria + * @see #isAssignable + */ + final T find(T[] methods) throws NoSuchMethodException { + Map[]> map = new HashMap[]>(); + + T oldMethod = null; + Class[] oldParams = null; + boolean ambiguous = false; + + for (T newMethod : methods) { + if (isValid(newMethod)) { + Class[] newParams = getParameters(newMethod); + if (newParams.length == this.args.length) { + PrimitiveWrapperMap.replacePrimitivesWithWrappers(newParams); + if (isAssignable(newParams, this.args)) { + if (oldMethod == null) { + oldMethod = newMethod; + oldParams = newParams; + } else { + boolean useNew = isAssignable(oldParams, newParams); + boolean useOld = isAssignable(newParams, oldParams); + + if (useOld == useNew) { + ambiguous = true; + } else if (useNew) { + oldMethod = newMethod; + oldParams = newParams; + ambiguous = false; + } + } + } + } + if (isVarArgs(newMethod)) { + int length = newParams.length - 1; + if (length <= this.args.length) { + Class[] array = new Class[this.args.length]; + System.arraycopy(newParams, 0, array, 0, length); + if (length < this.args.length) { + Class type = newParams[length].getComponentType(); + if (type.isPrimitive()) { + type = PrimitiveWrapperMap.getType(type.getName()); + } + for (int i = length; i < this.args.length; i++) { + array[i] = type; + } + } + map.put(newMethod, array); + } + } + } + } + for (T newMethod : methods) { + Class[] newParams = map.get(newMethod); + if (newParams != null) { + if (isAssignable(newParams, this.args)) { + if (oldMethod == null) { + oldMethod = newMethod; + oldParams = newParams; + } else { + boolean useNew = isAssignable(oldParams, newParams); + boolean useOld = isAssignable(newParams, oldParams); + + if (useOld == useNew) { + if (oldParams == map.get(oldMethod)) { + ambiguous = true; + } + } else if (useNew) { + oldMethod = newMethod; + oldParams = newParams; + ambiguous = false; + } + } + } + } + } + + if (ambiguous) { + throw new NoSuchMethodException("Ambiguous methods are found"); + } + if (oldMethod == null) { + throw new NoSuchMethodException("Method is not found"); + } + return oldMethod; + } + + /** + * Determines if every class in {@code min} array is either the same as, + * or is a superclass of, the corresponding class in {@code max} array. + * The length of every array must equal the number of arguments. + * This comparison is performed in the {@link #find} method + * before the first call of the isAssignable method. + * If an argument equals {@code null} + * the appropriate pair of classes does not take into consideration. + * + * @param min the array of classes to be checked + * @param max the array of classes that is used to check + * @return {@code true} if all classes in {@code min} array + * are assignable from corresponding classes in {@code max} array, + * {@code false} otherwise + * + * @see Class#isAssignableFrom + */ + private boolean isAssignable(Class[] min, Class[] max) { + for (int i = 0; i < this.args.length; i++) { + if (null != this.args[i]) { + if (!min[i].isAssignableFrom(max[i])) { + return false; + } + } + } + return true; + } +} diff --git a/jdk/src/share/classes/com/sun/beans/finder/ClassFinder.java b/jdk/src/share/classes/com/sun/beans/finder/ClassFinder.java index 79b77415653..01a72fa5809 100644 --- a/jdk/src/share/classes/com/sun/beans/finder/ClassFinder.java +++ b/jdk/src/share/classes/com/sun/beans/finder/ClassFinder.java @@ -1,5 +1,5 @@ /* - * Copyright 2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2006-2008 Sun Microsystems, Inc. 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 @@ -25,7 +25,7 @@ package com.sun.beans.finder; /** - * This is utility class that provides static methods + * This is utility class that provides {@code static} methods * to find a class with the specified name using the specified class loader. * * @since 1.7 @@ -33,137 +33,138 @@ package com.sun.beans.finder; * @author Sergey A. Malenkov */ public final class ClassFinder { + /** - * Returns the Class object associated + * Returns the {@code Class} object associated * with the class or interface with the given string name, * using the default class loader. *

- * The name can denote an array class + * The {@code name} can denote an array class * (see {@link Class#getName} for details). * * @param name fully qualified name of the desired class * @return class object representing the desired class * - * @exception ClassNotFoundException if the class cannot be located - * by the specified class loader + * @throws ClassNotFoundException if the class cannot be located + * by the specified class loader * * @see Class#forName(String) * @see Class#forName(String,boolean,ClassLoader) * @see ClassLoader#getSystemClassLoader() * @see Thread#getContextClassLoader() */ - public static Class findClass( String name ) throws ClassNotFoundException { + public static Class findClass(String name) throws ClassNotFoundException { try { ClassLoader loader = Thread.currentThread().getContextClassLoader(); - if ( loader == null ) { + if (loader == null) { // can be null in IE (see 6204697) loader = ClassLoader.getSystemClassLoader(); } - if ( loader != null ) { - return Class.forName( name, false, loader ); + if (loader != null) { + return Class.forName(name, false, loader); } - } catch ( ClassNotFoundException exception ) { + } catch (ClassNotFoundException exception) { // use current class loader instead - } catch ( SecurityException exception ) { + } catch (SecurityException exception) { // use current class loader instead } - return Class.forName( name ); + return Class.forName(name); } /** - * Returns the Class object associated with + * Returns the {@code Class} object associated with * the class or interface with the given string name, * using the given class loader. *

- * The name can denote an array class + * The {@code name} can denote an array class * (see {@link Class#getName} for details). *

- * If the parameter loader is null, + * If the parameter {@code loader} is null, * the class is loaded through the default class loader. * * @param name fully qualified name of the desired class * @param loader 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 + * @throws ClassNotFoundException if the class cannot be located + * by the specified class loader * * @see #findClass(String,ClassLoader) * @see Class#forName(String,boolean,ClassLoader) */ - public static Class findClass( String name, ClassLoader loader ) throws ClassNotFoundException { - if ( loader != null ) { + public static Class findClass(String name, ClassLoader loader) throws ClassNotFoundException { + if (loader != null) { try { - return Class.forName( name, false, loader ); - } catch ( ClassNotFoundException exception ) { + return Class.forName(name, false, loader); + } catch (ClassNotFoundException exception) { // use default class loader instead - } catch ( SecurityException exception ) { + } catch (SecurityException exception) { // use default class loader instead } } - return findClass( name ); + return findClass(name); } /** - * Returns the Class object associated + * Returns the {@code Class} object associated * with the class or interface with the given string name, * using the default class loader. *

- * The name can denote an array class + * The {@code name} can denote an array class * (see {@link Class#getName} for details). *

* This method can be used to obtain - * any of the Class objects - * representing void or primitive Java types: - * char, byte, short, - * int, long, float, - * double and boolean. + * any of the {@code Class} objects + * representing {@code void} or primitive Java types: + * {@code char}, {@code byte}, {@code short}, + * {@code int}, {@code long}, {@code float}, + * {@code double} and {@code boolean}. * * @param name fully qualified name of the desired class * @return class object representing the desired class * - * @exception ClassNotFoundException if the class cannot be located - * by the specified class loader + * @throws ClassNotFoundException if the class cannot be located + * by the specified class loader * * @see #resolveClass(String,ClassLoader) */ - public static Class resolveClass( String name ) throws ClassNotFoundException { - return resolveClass( name, null ); + public static Class resolveClass(String name) throws ClassNotFoundException { + return resolveClass(name, null); } /** - * Returns the Class object associated with + * Returns the {@code Class} object associated with * the class or interface with the given string name, * using the given class loader. *

- * The name can denote an array class + * The {@code name} can denote an array class * (see {@link Class#getName} for details). *

- * If the parameter loader is null, + * If the parameter {@code loader} is null, * the class is loaded through the default class loader. *

* This method can be used to obtain - * any of the Class objects - * representing void or primitive Java types: - * char, byte, short, - * int, long, float, - * double and boolean. + * any of the {@code Class} objects + * representing {@code void} or primitive Java types: + * {@code char}, {@code byte}, {@code short}, + * {@code int}, {@code long}, {@code float}, + * {@code double} and {@code boolean}. * * @param name fully qualified name of the desired class * @param loader 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 + * @throws ClassNotFoundException if the class cannot be located + * by the specified class loader * * @see #findClass(String,ClassLoader) * @see PrimitiveTypeMap#getType(String) */ - public static Class resolveClass( String name, ClassLoader loader ) throws ClassNotFoundException { - Class type = PrimitiveTypeMap.getType( name ); - return ( type == null ) - ? findClass( name, loader ) + public static Class resolveClass(String name, ClassLoader loader) throws ClassNotFoundException { + Class type = PrimitiveTypeMap.getType(name); + return (type == null) + ? findClass(name, loader) : type; } diff --git a/jdk/src/share/classes/com/sun/beans/finder/ConstructorFinder.java b/jdk/src/share/classes/com/sun/beans/finder/ConstructorFinder.java new file mode 100644 index 00000000000..e7bb33421fe --- /dev/null +++ b/jdk/src/share/classes/com/sun/beans/finder/ConstructorFinder.java @@ -0,0 +1,127 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.beans.finder; + +import com.sun.beans.WeakCache; + +import java.lang.reflect.Constructor; +import java.lang.reflect.Modifier; + +/** + * This utility class provides {@code static} methods + * to find a public constructor with specified parameter types + * in specified class. + * + * @since 1.7 + * + * @author Sergey A. Malenkov + */ +public final class ConstructorFinder extends AbstractFinder> { + private static final WeakCache> CACHE = new WeakCache>(); + + /** + * Finds public constructor + * that is declared in public class. + * + * @param type the class that can have constructor + * @param args parameter types that is used to find constructor + * @return object that represents found constructor + * @throws NoSuchMethodException if constructor could not be found + * or some constructors are found + */ + public static Constructor findConstructor(Class type, Class...args) throws NoSuchMethodException { + if (type.isPrimitive()) { + throw new NoSuchMethodException("Primitive wrapper does not contain constructors"); + } + if (type.isInterface()) { + throw new NoSuchMethodException("Interface does not contain constructors"); + } + if (Modifier.isAbstract(type.getModifiers())) { + throw new NoSuchMethodException("Abstract class cannot be instantiated"); + } + if (!Modifier.isPublic(type.getModifiers())) { + throw new NoSuchMethodException("Class is not accessible"); + } + PrimitiveWrapperMap.replacePrimitivesWithWrappers(args); + Signature signature = new Signature(type, args); + + Constructor constructor = CACHE.get(signature); + if (constructor != null) { + return constructor; + } + constructor = new ConstructorFinder(args).find(type.getConstructors()); + CACHE.put(signature, constructor); + return constructor; + } + + /** + * Creates constructor finder with specified array of parameter types. + * + * @param args the array of parameter types + */ + private ConstructorFinder(Class[] args) { + super(args); + } + + /** + * Returns an array of {@code Class} objects + * that represent the formal parameter types of the constructor + * Returns an empty array if the constructor takes no parameters. + * + * @param constructor the object that represents constructor + * @return the parameter types of the constructor + */ + @Override + protected Class[] getParameters(Constructor constructor) { + return constructor.getParameterTypes(); + } + + /** + * Returns {@code true} if and only if the constructor + * was declared to take a variable number of arguments. + * + * @param constructor the object that represents constructor + * @return {@code true} if the constructor was declared + * to take a variable number of arguments; + * {@code false} otherwise + */ + @Override + protected boolean isVarArgs(Constructor constructor) { + return constructor.isVarArgs(); + } + + /** + * Checks validness of the constructor. + * The valid constructor should be public. + * + * @param constructor the object that represents constructor + * @return {@code true} if the constructor is valid, + * {@code false} otherwise + */ + @Override + protected boolean isValid(Constructor constructor) { + return Modifier.isPublic(constructor.getModifiers()); + } +} diff --git a/jdk/src/share/classes/com/sun/beans/finder/FieldFinder.java b/jdk/src/share/classes/com/sun/beans/finder/FieldFinder.java new file mode 100644 index 00000000000..cb17d02417d --- /dev/null +++ b/jdk/src/share/classes/com/sun/beans/finder/FieldFinder.java @@ -0,0 +1,106 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.beans.finder; + +import java.lang.reflect.Field; +import java.lang.reflect.Modifier; + +/** + * This utility class provides {@code static} methods + * to find a public field with specified name + * in specified class. + * + * @since 1.7 + * + * @author Sergey A. Malenkov + */ +public final class FieldFinder { + + /** + * Finds public field (static or non-static) + * that is declared in public class. + * + * @param type the class that can have field + * @param name the name of field to find + * @return object that represents found field + * @throws NoSuchFieldException if field is not found + * @see Class#getField + */ + public static Field findField(Class type, String name) throws NoSuchFieldException { + if (name == null) { + throw new IllegalArgumentException("Field name is not set"); + } + Field field = type.getField(name); + if (!Modifier.isPublic(field.getModifiers())) { + throw new NoSuchFieldException("Field '" + name + "' is not public"); + } + if (!Modifier.isPublic(field.getDeclaringClass().getModifiers())) { + throw new NoSuchFieldException("Field '" + name + "' is not accessible"); + } + return field; + } + + /** + * Finds public non-static field + * that is declared in public class. + * + * @param type the class that can have field + * @param name the name of field to find + * @return object that represents found field + * @throws NoSuchFieldException if field is not found + * @see Class#getField + */ + public static Field findInstanceField(Class type, String name) throws NoSuchFieldException { + Field field = findField(type, name); + if (Modifier.isStatic(field.getModifiers())) { + throw new NoSuchFieldException("Field '" + name + "' is static"); + } + return field; + } + + /** + * Finds public static field + * that is declared in public class. + * + * @param type the class that can have field + * @param name the name of field to find + * @return object that represents found field + * @throws NoSuchFieldException if field is not found + * @see Class#getField + */ + public static Field findStaticField(Class type, String name) throws NoSuchFieldException { + Field field = findField(type, name); + if (!Modifier.isStatic(field.getModifiers())) { + throw new NoSuchFieldException("Field '" + name + "' is not static"); + } + return field; + } + + /** + * Disable instantiation. + */ + private FieldFinder() { + } +} diff --git a/jdk/src/share/classes/com/sun/beans/finder/MethodFinder.java b/jdk/src/share/classes/com/sun/beans/finder/MethodFinder.java new file mode 100644 index 00000000000..d4aa0844ad3 --- /dev/null +++ b/jdk/src/share/classes/com/sun/beans/finder/MethodFinder.java @@ -0,0 +1,205 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.beans.finder; + +import com.sun.beans.WeakCache; + +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; + +/** + * This utility class provides {@code static} methods + * to find a public method with specified name and parameter types + * in specified class. + * + * @since 1.7 + * + * @author Sergey A. Malenkov + */ +public final class MethodFinder extends AbstractFinder { + private static final WeakCache CACHE = new WeakCache(); + + /** + * Finds public method (static or non-static) + * that is accessible from public class. + * + * @param type the class that can have method + * @param name the name of method to find + * @param args parameter types that is used to find method + * @return object that represents found method + * @throws NoSuchMethodException if method could not be found + * or some methods are found + */ + public static Method findMethod(Class type, String name, Class...args) throws NoSuchMethodException { + if (name == null) { + throw new IllegalArgumentException("Method name is not set"); + } + PrimitiveWrapperMap.replacePrimitivesWithWrappers(args); + Signature signature = new Signature(type, name, args); + + Method method = CACHE.get(signature); + if (method != null) { + return method; + } + method = findAccessibleMethod(new MethodFinder(name, args).find(type.getMethods())); + CACHE.put(signature, method); + return method; + } + + /** + * Finds public non-static method + * that is accessible from public class. + * + * @param type the class that can have method + * @param name the name of method to find + * @param args parameter types that is used to find method + * @return object that represents found method + * @throws NoSuchMethodException if method could not be found + * or some methods are found + */ + public static Method findInstanceMethod(Class type, String name, Class... args) throws NoSuchMethodException { + Method method = findMethod(type, name, args); + if (Modifier.isStatic(method.getModifiers())) { + throw new NoSuchMethodException("Method '" + name + "' is static"); + } + return method; + } + + /** + * Finds public static method + * that is accessible from public class. + * + * @param type the class that can have method + * @param name the name of method to find + * @param args parameter types that is used to find method + * @return object that represents found method + * @throws NoSuchMethodException if method could not be found + * or some methods are found + */ + public static Method findStaticMethod(Class type, String name, Class...args) throws NoSuchMethodException { + Method method = findMethod(type, name, args); + if (!Modifier.isStatic(method.getModifiers())) { + throw new NoSuchMethodException("Method '" + name + "' is not static"); + } + return method; + } + + /** + * Finds method that is accessible from public class or interface through class hierarchy. + * + * @param method object that represents found method + * @return object that represents accessible method + * @throws NoSuchMethodException if method is not accessible or is not found + * in specified superclass or interface + */ + private static Method findAccessibleMethod(Method method) throws NoSuchMethodException { + Class type = method.getDeclaringClass(); + if (Modifier.isPublic(type.getModifiers())) { + return method; + } + if (Modifier.isStatic(method.getModifiers())) { + throw new NoSuchMethodException("Method '" + method.getName() + "' is not accessible"); + } + for (Class face : type.getInterfaces()) { + try { + return findAccessibleMethod(method, face); + } + catch (NoSuchMethodException exception) { + // try to find in superclass or another interface + } + } + return findAccessibleMethod(method, type.getSuperclass()); + } + + /** + * Finds method that accessible from specified class. + * + * @param method object that represents found method + * @param type class that is used to find accessible method + * @return object that represents accessible method + * @throws NoSuchMethodException if method is not accessible or is not found + * in specified superclass or interface + */ + private static Method findAccessibleMethod(Method method, Class type) throws NoSuchMethodException { + String name = method.getName(); + Class[] params = method.getParameterTypes(); + return findAccessibleMethod(type.getMethod(name, params)); + } + + + private final String name; + + /** + * Creates method finder with specified array of parameter types. + * + * @param name the name of method to find + * @param args the array of parameter types + */ + private MethodFinder(String name, Class[] args) { + super(args); + this.name = name; + } + + /** + * Returns an array of {@code Class} objects + * that represent the formal parameter types of the method + * Returns an empty array if the method takes no parameters. + * + * @param method the object that represents method + * @return the parameter types of the method + */ + @Override + protected Class[] getParameters(Method method) { + return method.getParameterTypes(); + } + + /** + * Returns {@code true} if and only if the method + * was declared to take a variable number of arguments. + * + * @param method the object that represents method + * @return {@code true} if the method was declared + * to take a variable number of arguments; + * {@code false} otherwise + */ + @Override + protected boolean isVarArgs(Method method) { + return method.isVarArgs(); + } + + /** + * Checks validness of the method. + * The valid method should be public and + * should have the specified name. + * + * @param method the object that represents method + * @return {@code true} if the method is valid, + * {@code false} otherwise + */ + @Override + protected boolean isValid(Method method) { + return Modifier.isPublic(method.getModifiers()) && method.getName().equals(this.name); + } +} diff --git a/jdk/src/share/classes/com/sun/beans/finder/PrimitiveTypeMap.java b/jdk/src/share/classes/com/sun/beans/finder/PrimitiveTypeMap.java index 0bdb09e5be1..36a552b906c 100644 --- a/jdk/src/share/classes/com/sun/beans/finder/PrimitiveTypeMap.java +++ b/jdk/src/share/classes/com/sun/beans/finder/PrimitiveTypeMap.java @@ -1,5 +1,5 @@ /* - * Copyright 2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2006-2008 Sun Microsystems, Inc. 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 @@ -36,29 +36,30 @@ import java.util.Map; * @author Sergey A. Malenkov */ final class PrimitiveTypeMap { + /** * Returns primitive type class by its name. * * @param name the name of primitive type * @return found primitive type class, - * or null if not found + * or {@code null} if not found */ - static Class getType( String name ) { - return map.get( name ); + static Class getType(String name) { + return map.get(name); } - private static final Map map = new HashMap( 9 ); + private static final Map> map = new HashMap>(9); static { - map.put( boolean.class.getName(), boolean.class ); - map.put( char.class.getName(), char.class ); - map.put( byte.class.getName(), byte.class ); - map.put( short.class.getName(), short.class ); - map.put( int.class.getName(), int.class ); - map.put( long.class.getName(), long.class ); - map.put( float.class.getName(), float.class ); - map.put( double.class.getName(), double.class ); - map.put( void.class.getName(), void.class ); + map.put(boolean.class.getName(), boolean.class); + map.put(char.class.getName(), char.class); + map.put(byte.class.getName(), byte.class); + map.put(short.class.getName(), short.class); + map.put(int.class.getName(), int.class); + map.put(long.class.getName(), long.class); + map.put(float.class.getName(), float.class); + map.put(double.class.getName(), double.class); + map.put(void.class.getName(), void.class); } /** diff --git a/jdk/src/share/classes/com/sun/beans/finder/PrimitiveWrapperMap.java b/jdk/src/share/classes/com/sun/beans/finder/PrimitiveWrapperMap.java new file mode 100644 index 00000000000..f39b3ea3df0 --- /dev/null +++ b/jdk/src/share/classes/com/sun/beans/finder/PrimitiveWrapperMap.java @@ -0,0 +1,86 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.beans.finder; + +import java.util.HashMap; +import java.util.Map; + +/** + * This utility class associates + * name of primitive type with appropriate wrapper. + * + * @since 1.7 + * + * @author Sergey A. Malenkov + */ +public final class PrimitiveWrapperMap { + + /** + * Replaces all primitive types in specified array with wrappers. + * + * @param types array of classes where all primitive types + * will be replaced by appropriate wrappers + */ + static void replacePrimitivesWithWrappers(Class[] types) { + for (int i = 0; i < types.length; i++) { + if (types[i] != null) { + if (types[i].isPrimitive()) { + types[i] = getType(types[i].getName()); + } + } + } + } + + /** + * Returns wrapper for primitive type by its name. + * + * @param name the name of primitive type + * @return found wrapper for primitive type, + * or {@code null} if not found + */ + public static Class getType(String name) { + return map.get(name); + } + + private static final Map> map = new HashMap>(9); + + static { + map.put(Boolean.TYPE.getName(), Boolean.class); + map.put(Character.TYPE.getName(), Character.class); + map.put(Byte.TYPE.getName(), Byte.class); + map.put(Short.TYPE.getName(), Short.class); + map.put(Integer.TYPE.getName(), Integer.class); + map.put(Long.TYPE.getName(), Long.class); + map.put(Float.TYPE.getName(), Float.class); + map.put(Double.TYPE.getName(), Double.class); + map.put(Void.TYPE.getName(), Void.class); + } + + /** + * Disable instantiation. + */ + private PrimitiveWrapperMap() { + } +} diff --git a/jdk/src/share/classes/com/sun/beans/finder/Signature.java b/jdk/src/share/classes/com/sun/beans/finder/Signature.java new file mode 100644 index 00000000000..8c09e11f4b4 --- /dev/null +++ b/jdk/src/share/classes/com/sun/beans/finder/Signature.java @@ -0,0 +1,169 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.beans.finder; + +/** + * This class is designed to be a key of a cache + * of constructors or methods. + * + * @since 1.7 + * + * @author Sergey A. Malenkov + */ +final class Signature { + private final Class type; + private final String name; + private final Class[] args; + + private volatile int code; + + /** + * Constructs signature for constructor. + * + * @param type the class that contains constructor + * @param args the types of constructor's parameters + */ + Signature(Class type, Class[] args) { + this(type, null, args); + } + + /** + * Constructs signature for method. + * + * @param type the class that contains method + * @param name the name of the method + * @param args the types of method's parameters + */ + Signature(Class type, String name, Class[] args) { + this.type = type; + this.name = name; + this.args = args; + } + + /** + * Indicates whether some other object is "equal to" this one. + * + * @param object the reference object with which to compare + * @return {@code true} if this object is the same as the + * {@code object} argument, {@code false} otherwise + * @see #hashCode() + */ + @Override + public boolean equals(Object object) { + if (this == object) { + return true; + } + if (object instanceof Signature) { + Signature signature = (Signature) object; + return isEqual(signature.type, this.type) + && isEqual(signature.name, this.name) + && isEqual(signature.args, this.args); + } + return false; + } + + /** + * Indicates whether some object is "equal to" another one. + * This method supports {@code null} values. + * + * @param obj1 the first reference object that will compared + * @param obj2 the second reference object that will compared + * @return {@code true} if first object is the same as the second object, + * {@code false} otherwise + */ + private static boolean isEqual(Object obj1, Object obj2) { + return (obj1 == null) + ? obj2 == null + : obj1.equals(obj2); + } + + /** + * Indicates whether some array is "equal to" another one. + * This method supports {@code null} values. + * + * @param args1 the first reference array that will compared + * @param args2 the second reference array that will compared + * @return {@code true} if first array is the same as the second array, + * {@code false} otherwise + */ + private static boolean isEqual(Class[] args1, Class[] args2) { + if ((args1 == null) || (args2 == null)) { + return args1 == args2; + } + if (args1.length != args2.length) { + return false; + } + for (int i = 0; i < args1.length; i++) { + if (!isEqual(args1[i], args2[i])) { + return false; + } + } + return true; + } + + /** + * Returns a hash code value for the object. + * This method is supported for the benefit of hashtables + * such as {@link java.util.HashMap} or {@link java.util.HashSet}. + * Hash code computed using algorithm + * suggested in Effective Java, Item 8. + * + * @return a hash code value for this object + * @see #equals(Object) + */ + @Override + public int hashCode() { + if (this.code == 0) { + int code = 17; + code = addHashCode(code, this.type); + code = addHashCode(code, this.name); + + if (this.args != null) { + for (Class arg : this.args) { + code = addHashCode(code, arg); + } + } + this.code = code; + } + return this.code; + } + + /** + * Adds hash code value if specified object. + * This is a part of the algorithm + * suggested in Effective Java, Item 8. + * + * @param code current hash code value + * @param object object that updates hash code value + * @return updated hash code value + * @see #hashCode() + */ + private static int addHashCode(int code, Object object) { + code *= 37; + return (object != null) + ? code + object.hashCode() + : code; + } +} diff --git a/jdk/src/share/classes/java/beans/MetaData.java b/jdk/src/share/classes/java/beans/MetaData.java index 5d8fd697918..defd196457e 100644 --- a/jdk/src/share/classes/java/beans/MetaData.java +++ b/jdk/src/share/classes/java/beans/MetaData.java @@ -24,6 +24,8 @@ */ package java.beans; +import com.sun.beans.finder.PrimitiveWrapperMap; + import java.awt.AWTKeyStroke; import java.awt.BorderLayout; import java.awt.Dimension; @@ -204,7 +206,7 @@ class java_lang_Class_PersistenceDelegate extends PersistenceDelegate { if (c.isPrimitive()) { Field field = null; try { - field = ReflectionUtils.typeToClass(c).getDeclaredField("TYPE"); + field = PrimitiveWrapperMap.getType(c.getName()).getDeclaredField("TYPE"); } catch (NoSuchFieldException ex) { System.err.println("Unknown primitive type: " + c); } diff --git a/jdk/src/share/classes/java/beans/ReflectionUtils.java b/jdk/src/share/classes/java/beans/ReflectionUtils.java index 167b02995f0..c2553fd4176 100644 --- a/jdk/src/share/classes/java/beans/ReflectionUtils.java +++ b/jdk/src/share/classes/java/beans/ReflectionUtils.java @@ -1,5 +1,5 @@ /* - * Copyright 2003-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2003-2008 Sun Microsystems, Inc. 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 @@ -24,6 +24,8 @@ */ package java.beans; +import com.sun.beans.finder.PrimitiveWrapperMap; + import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.Method; @@ -34,7 +36,6 @@ import java.lang.ref.SoftReference; import java.util.*; -import com.sun.beans.ObjectHandler; import sun.reflect.misc.MethodUtil; import sun.reflect.misc.ConstructorUtil; import sun.reflect.misc.ReflectUtil; @@ -47,10 +48,6 @@ class ReflectionUtils { private static Reference methodCacheRef; - public static Class typeToClass(Class type) { - return type.isPrimitive() ? ObjectHandler.typeNameToClass(type.getName()) : type; - } - public static boolean isPrimitive(Class type) { return primitiveTypeFor(type) != null; } @@ -99,7 +96,7 @@ class ReflectionUtils { for(int j = 0; j < argClasses.length && match; j++) { Class argType = argTypes[j]; if (argType.isPrimitive()) { - argType = typeToClass(argType); + argType = PrimitiveWrapperMap.getType(argType.getName()); } if (explicit) { // Test each element for equality @@ -210,7 +207,7 @@ class ReflectionUtils { for (int i = 0; i < args.length; i++) { Class mArg = mArgs[i]; if (mArg.isPrimitive()) { - mArg = typeToClass(mArg); + mArg = PrimitiveWrapperMap.getType(mArg.getName()); } if (args[i] == mArg) { matches++; diff --git a/jdk/src/share/classes/java/beans/XMLDecoder.java b/jdk/src/share/classes/java/beans/XMLDecoder.java index 688edfae406..5e0327d65f5 100644 --- a/jdk/src/share/classes/java/beans/XMLDecoder.java +++ b/jdk/src/share/classes/java/beans/XMLDecoder.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2005 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2000-2008 Sun Microsystems, Inc. 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 @@ -24,19 +24,14 @@ */ package java.beans; -import com.sun.beans.ObjectHandler; +import com.sun.beans.decoder.DocumentHandler; +import java.io.Closeable; import java.io.InputStream; import java.io.IOException; -import java.lang.ref.Reference; -import java.lang.ref.WeakReference; - -import org.xml.sax.SAXException; - -import javax.xml.parsers.SAXParserFactory; -import javax.xml.parsers.ParserConfigurationException; -import javax.xml.parsers.SAXParser; +import org.xml.sax.InputSource; +import org.xml.sax.helpers.DefaultHandler; /** * The XMLDecoder class is used to read XML documents @@ -66,11 +61,11 @@ import javax.xml.parsers.SAXParser; * @author Philip Milne */ public class XMLDecoder { - private InputStream in; + private final DocumentHandler handler = new DocumentHandler(); + private final InputSource input; private Object owner; - private ExceptionListener exceptionListener; - private ObjectHandler handler; - private Reference clref; + private Object[] array; + private int index; /** * Creates a new input stream for reading archives @@ -126,36 +121,45 @@ public class XMLDecoder { */ public XMLDecoder(InputStream in, Object owner, ExceptionListener exceptionListener, ClassLoader cl) { - this.in = in; - setOwner(owner); - setExceptionListener(exceptionListener); - setClassLoader(cl); + this(new InputSource(in), owner, exceptionListener, cl); } /** - * Set the class loader used to instantiate objects for this stream. + * Creates a new decoder to parse XML archives + * created by the {@code XMLEncoder} class. + * If the input source {@code is} is {@code null}, + * no exception is thrown and no parsing is performed. + * This behavior is similar to behavior of other constructors + * that use {@code InputStream} as a parameter. * - * @param cl a classloader to use; if null then the default class loader - * will be used + * @param is the input source to parse + * + * @since 1.7 */ - private void setClassLoader(ClassLoader cl) { - if (cl != null) { - this.clref = new WeakReference(cl); - } + public XMLDecoder(InputSource is) { + this(is, null, null, null); } /** - * Return the class loader used to instantiate objects. If the class loader - * has not been explicitly set then null is returned. + * Creates a new decoder to parse XML archives + * created by the {@code XMLEncoder} class. * - * @return the class loader used to instantiate objects + * @param is the input source to parse + * @param owner the owner of this decoder + * @param el the exception handler for the parser, + * or {@code null} to use the default exception handler + * @param cl the class loader used for instantiating objects, + * or {@code null} to use the default class loader + * + * @since 1.7 */ - private ClassLoader getClassLoader() { - if (clref != null) { - return (ClassLoader)clref.get(); - } - return null; + private XMLDecoder(InputSource is, Object owner, ExceptionListener el, ClassLoader cl) { + this.input = is; + this.owner = owner; + setExceptionListener(el); + this.handler.setClassLoader(cl); + this.handler.setOwner(this); } /** @@ -163,8 +167,14 @@ public class XMLDecoder { * with this stream. */ public void close() { + if (parsingComplete()) { + close(this.input.getCharacterStream()); + close(this.input.getByteStream()); + } + } + + private void close(Closeable in) { if (in != null) { - getHandler(); try { in.close(); } @@ -174,6 +184,17 @@ public class XMLDecoder { } } + private boolean parsingComplete() { + if (this.input == null) { + return false; + } + if (this.array == null) { + this.handler.parse(this.input); + this.array = this.handler.getObjects(); + } + return true; + } + /** * Sets the exception handler for this stream to exceptionListener. * The exception handler is notified when this stream catches recoverable @@ -185,7 +206,10 @@ public class XMLDecoder { * @see #getExceptionListener */ public void setExceptionListener(ExceptionListener exceptionListener) { - this.exceptionListener = exceptionListener; + if (exceptionListener == null) { + exceptionListener = Statement.defaultExceptionListener; + } + this.handler.setExceptionListener(exceptionListener); } /** @@ -197,8 +221,7 @@ public class XMLDecoder { * @see #setExceptionListener */ public ExceptionListener getExceptionListener() { - return (exceptionListener != null) ? exceptionListener : - Statement.defaultExceptionListener; + return this.handler.getExceptionListener(); } /** @@ -212,10 +235,9 @@ public class XMLDecoder { * @see XMLEncoder#writeObject */ public Object readObject() { - if (in == null) { - return null; - } - return getHandler().dequeueResult(); + return (parsingComplete()) + ? this.array[this.index++] + : null; } /** @@ -241,33 +263,32 @@ public class XMLDecoder { } /** - * Returns the object handler for input stream. - * The object handler is created if necessary. + * Creates a new handler for SAX parser + * that can be used to parse embedded XML archives + * created by the {@code XMLEncoder} class. * - * @return the object handler + * The {@code owner} should be used if parsed XML document contains + * the method call within context of the <java> element. + * The {@code null} value may cause illegal parsing in such case. + * The same problem may occur, if the {@code owner} class + * does not contain expected method to call. See details here. + * + * @param owner the owner of the default handler + * that can be used as a value of <java> element + * @param el the exception handler for the parser, + * or {@code null} to use the default exception handler + * @param cl the class loader used for instantiating objects, + * or {@code null} to use the default class loader + * @return an instance of {@code DefaultHandler} for SAX parser + * + * @since 1.7 */ - private ObjectHandler getHandler() { - if ( handler == null ) { - SAXParserFactory factory = SAXParserFactory.newInstance(); - try { - SAXParser parser = factory.newSAXParser(); - handler = new ObjectHandler( this, getClassLoader() ); - parser.parse( in, handler ); - } - catch ( ParserConfigurationException e ) { - getExceptionListener().exceptionThrown( e ); - } - catch ( SAXException se ) { - Exception e = se.getException(); - if ( e == null ) { - e = se; - } - getExceptionListener().exceptionThrown( e ); - } - catch ( IOException ioe ) { - getExceptionListener().exceptionThrown( ioe ); - } - } + public static DefaultHandler createHandler(Object owner, ExceptionListener el, ClassLoader cl) { + DocumentHandler handler = new DocumentHandler(); + handler.setOwner(owner); + handler.setExceptionListener(el); + handler.setClassLoader(cl); return handler; } } diff --git a/jdk/src/share/classes/javax/swing/plaf/synth/SynthParser.java b/jdk/src/share/classes/javax/swing/plaf/synth/SynthParser.java index 5f7a9b6c282..7fe2278fd20 100644 --- a/jdk/src/share/classes/javax/swing/plaf/synth/SynthParser.java +++ b/jdk/src/share/classes/javax/swing/plaf/synth/SynthParser.java @@ -1,5 +1,5 @@ /* - * Copyright 2003-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2003-2008 Sun Microsystems, Inc. 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 @@ -59,16 +59,16 @@ import javax.xml.parsers.ParserConfigurationException; import javax.xml.parsers.SAXParser; import javax.xml.parsers.SAXParserFactory; -import org.xml.sax.AttributeList; -import org.xml.sax.HandlerBase; +import org.xml.sax.Attributes; import org.xml.sax.InputSource; import org.xml.sax.Locator; import org.xml.sax.SAXException; import org.xml.sax.SAXParseException; +import org.xml.sax.helpers.DefaultHandler; -import com.sun.beans.ObjectHandler; +import com.sun.beans.decoder.DocumentHandler; -class SynthParser extends HandlerBase { +class SynthParser extends DefaultHandler { // // Known element names // @@ -119,7 +119,7 @@ class SynthParser extends HandlerBase { /** * Lazily created, used for anything we don't understand. */ - private ObjectHandler _handler; + private DocumentHandler _handler; /** * Indicates the depth of how many elements we've encountered but don't @@ -292,8 +292,9 @@ class SynthParser extends HandlerBase { /** * Handles beans persistance. */ - private ObjectHandler getHandler() { + private DocumentHandler getHandler() { if (_handler == null) { + _handler = new DocumentHandler(); if (_urlResourceBase != null) { // getHandler() is never called before parse() so it is safe // to create a URLClassLoader with _resourceBase. @@ -304,14 +305,13 @@ class SynthParser extends HandlerBase { URL[] urls = new URL[] { getResource(".") }; ClassLoader parent = Thread.currentThread().getContextClassLoader(); ClassLoader urlLoader = new URLClassLoader(urls, parent); - _handler = new ObjectHandler(null, urlLoader); + _handler.setClassLoader(urlLoader); } else { - _handler = new ObjectHandler(null, - _classResourceBase.getClassLoader()); + _handler.setClassLoader(_classResourceBase.getClassLoader()); } for (String key : _mapping.keySet()) { - _handler.register(key, _mapping.get(key)); + _handler.setVariable(key, _mapping.get(key)); } } return _handler; @@ -336,8 +336,8 @@ class SynthParser extends HandlerBase { private Object lookup(String key, Class type) throws SAXException { Object value; if (_handler != null) { - if ((value = _handler.lookup(key)) != null) { - return checkCast(value, type); + if (_handler.hasVariable(key)) { + return checkCast(_handler.getVariable(key), type); } } value = _mapping.get(key); @@ -354,11 +354,11 @@ class SynthParser extends HandlerBase { private void register(String key, Object value) throws SAXException { if (key != null) { if (_mapping.get(key) != null || - (_handler != null && _handler.lookup(key) != null)) { + (_handler != null && _handler.hasVariable(key))) { throw new SAXException("ID " + key + " is already defined"); } if (_handler != null) { - _handler.register(key, value); + _handler.setVariable(key, value); } else { _mapping.put(key, value); @@ -400,12 +400,12 @@ class SynthParser extends HandlerBase { // The following methods are invoked from startElement/stopElement // - private void startStyle(AttributeList attributes) throws SAXException { + private void startStyle(Attributes attributes) throws SAXException { String id = null; _style = null; for(int i = attributes.getLength() - 1; i >= 0; i--) { - String key = attributes.getName(i); + String key = attributes.getQName(i); if (key.equals(ATTRIBUTE_CLONE)) { _style = (ParsedSynthStyle)((ParsedSynthStyle)lookup( attributes.getValue(i), ParsedSynthStyle.class)). @@ -421,7 +421,7 @@ class SynthParser extends HandlerBase { register(id, _style); } - private void endStyle() throws SAXException { + private void endStyle() { int size = _stylePainters.size(); if (size > 0) { _style.setPainters(_stylePainters.toArray(new ParsedSynthStyle.PainterInfo[size])); @@ -435,14 +435,14 @@ class SynthParser extends HandlerBase { _style = null; } - private void startState(AttributeList attributes) throws SAXException { + private void startState(Attributes attributes) throws SAXException { ParsedSynthStyle.StateInfo stateInfo = null; int state = 0; String id = null; _stateInfo = null; for(int i = attributes.getLength() - 1; i >= 0; i--) { - String key = attributes.getName(i); + String key = attributes.getQName(i); if (key.equals(ATTRIBUTE_ID)) { id = attributes.getValue(i); } @@ -496,7 +496,7 @@ class SynthParser extends HandlerBase { _stateInfos.add(_stateInfo); } - private void endState() throws SAXException { + private void endState() { int size = _statePainters.size(); if (size > 0) { _stateInfo.setPainters(_statePainters.toArray(new ParsedSynthStyle.PainterInfo[size])); @@ -505,7 +505,7 @@ class SynthParser extends HandlerBase { _stateInfo = null; } - private void startFont(AttributeList attributes) throws SAXException { + private void startFont(Attributes attributes) throws SAXException { Font font = null; int style = Font.PLAIN; int size = 0; @@ -513,7 +513,7 @@ class SynthParser extends HandlerBase { String name = null; for(int i = attributes.getLength() - 1; i >= 0; i--) { - String key = attributes.getName(i); + String key = attributes.getQName(i); if (key.equals(ATTRIBUTE_ID)) { id = attributes.getValue(i); } @@ -568,13 +568,13 @@ class SynthParser extends HandlerBase { } } - private void startColor(AttributeList attributes) throws SAXException { + private void startColor(Attributes attributes) throws SAXException { Color color = null; String id = null; _colorTypes.clear(); for(int i = attributes.getLength() - 1; i >= 0; i--) { - String key = attributes.getName(i); + String key = attributes.getQName(i); if (key.equals(ATTRIBUTE_ID)) { id = attributes.getValue(i); } @@ -697,7 +697,7 @@ class SynthParser extends HandlerBase { } } - private void startProperty(AttributeList attributes, + private void startProperty(Attributes attributes, Object property) throws SAXException { Object value = null; String key = null; @@ -707,7 +707,7 @@ class SynthParser extends HandlerBase { String aValue = null; for(int i = attributes.getLength() - 1; i >= 0; i--) { - String aName = attributes.getName(i); + String aName = attributes.getQName(i); if (aName.equals(ATTRIBUTE_TYPE)) { String type = attributes.getValue(i).toUpperCase(); if (type.equals("IDREF")) { @@ -795,11 +795,11 @@ class SynthParser extends HandlerBase { } } - private void startGraphics(AttributeList attributes) throws SAXException { + private void startGraphics(Attributes attributes) throws SAXException { SynthGraphicsUtils graphics = null; for(int i = attributes.getLength() - 1; i >= 0; i--) { - String key = attributes.getName(i); + String key = attributes.getQName(i); if (key.equals(ATTRIBUTE_IDREF)) { graphics = (SynthGraphicsUtils)lookup(attributes.getValue(i), SynthGraphicsUtils.class); @@ -813,7 +813,7 @@ class SynthParser extends HandlerBase { } } - private void startInsets(AttributeList attributes) throws SAXException { + private void startInsets(Attributes attributes) throws SAXException { int top = 0; int bottom = 0; int left = 0; @@ -822,7 +822,7 @@ class SynthParser extends HandlerBase { String id = null; for(int i = attributes.getLength() - 1; i >= 0; i--) { - String key = attributes.getName(i); + String key = attributes.getQName(i); try { if (key.equals(ATTRIBUTE_IDREF)) { @@ -858,13 +858,13 @@ class SynthParser extends HandlerBase { } } - private void startBind(AttributeList attributes) throws SAXException { + private void startBind(Attributes attributes) throws SAXException { ParsedSynthStyle style = null; String path = null; int type = -1; for(int i = attributes.getLength() - 1; i >= 0; i--) { - String key = attributes.getName(i); + String key = attributes.getQName(i); if (key.equals(ATTRIBUTE_STYLE)) { style = (ParsedSynthStyle)lookup(attributes.getValue(i), @@ -899,7 +899,7 @@ class SynthParser extends HandlerBase { } } - private void startPainter(AttributeList attributes, String type) throws SAXException { + private void startPainter(Attributes attributes, String type) throws SAXException { Insets sourceInsets = null; Insets destInsets = null; String path = null; @@ -915,7 +915,7 @@ class SynthParser extends HandlerBase { boolean paintCenterSpecified = false; for(int i = attributes.getLength() - 1; i >= 0; i--) { - String key = attributes.getName(i); + String key = attributes.getQName(i); String value = attributes.getValue(i); if (key.equals(ATTRIBUTE_ID)) { @@ -1042,12 +1042,12 @@ class SynthParser extends HandlerBase { painters.add(painterInfo); } - private void startImageIcon(AttributeList attributes) throws SAXException { + private void startImageIcon(Attributes attributes) throws SAXException { String path = null; String id = null; for(int i = attributes.getLength() - 1; i >= 0; i--) { - String key = attributes.getName(i); + String key = attributes.getQName(i); if (key.equals(ATTRIBUTE_ID)) { id = attributes.getValue(i); @@ -1062,12 +1062,11 @@ class SynthParser extends HandlerBase { register(id, new LazyImageIcon(getResource(path))); } - private void startOpaque(AttributeList attributes) throws - SAXException { + private void startOpaque(Attributes attributes) { if (_style != null) { _style.setOpaque(true); for(int i = attributes.getLength() - 1; i >= 0; i--) { - String key = attributes.getName(i); + String key = attributes.getQName(i); if (key.equals(ATTRIBUTE_VALUE)) { _style.setOpaque("true".equals(attributes.getValue(i). @@ -1077,12 +1076,12 @@ class SynthParser extends HandlerBase { } } - private void startInputMap(AttributeList attributes) throws SAXException { + private void startInputMap(Attributes attributes) throws SAXException { _inputMapBindings.clear(); _inputMapID = null; if (_style != null) { for(int i = attributes.getLength() - 1; i >= 0; i--) { - String key = attributes.getName(i); + String key = attributes.getQName(i); if (key.equals(ATTRIBUTE_ID)) { _inputMapID = attributes.getValue(i); @@ -1101,7 +1100,7 @@ class SynthParser extends HandlerBase { _inputMapID = null; } - private void startBindKey(AttributeList attributes) throws SAXException { + private void startBindKey(Attributes attributes) throws SAXException { if (_inputMapID == null) { // Not in an inputmap, bail. return; @@ -1110,7 +1109,7 @@ class SynthParser extends HandlerBase { String key = null; String value = null; for(int i = attributes.getLength() - 1; i >= 0; i--) { - String aKey = attributes.getName(i); + String aKey = attributes.getQName(i); if (aKey.equals(ATTRIBUTE_KEY)) { key = attributes.getValue(i); @@ -1129,26 +1128,26 @@ class SynthParser extends HandlerBase { } // - // SAX methods, these forward to the ObjectHandler if we don't know + // SAX methods, these forward to the DocumentHandler if we don't know // the element name. // public InputSource resolveEntity(String publicId, String systemId) - throws SAXException { + throws IOException, SAXException { if (isForwarding()) { return getHandler().resolveEntity(publicId, systemId); } return null; } - public void notationDecl(String name, String publicId, String systemId) { + public void notationDecl(String name, String publicId, String systemId) throws SAXException { if (isForwarding()) { getHandler().notationDecl(name, publicId, systemId); } } public void unparsedEntityDecl(String name, String publicId, - String systemId, String notationName) { + String systemId, String notationName) throws SAXException { if (isForwarding()) { getHandler().unparsedEntityDecl(name, publicId, systemId, notationName); @@ -1173,7 +1172,7 @@ class SynthParser extends HandlerBase { } } - public void startElement(String name, AttributeList attributes) + public void startElement(String uri, String local, String name, Attributes attributes) throws SAXException { name = name.intern(); if (name == ELEMENT_STYLE) { @@ -1223,18 +1222,18 @@ class SynthParser extends HandlerBase { } else if (name != ELEMENT_SYNTH) { if (_depth++ == 0) { - getHandler().reset(); + getHandler().startDocument(); } - getHandler().startElement(name, attributes); + getHandler().startElement(uri, local, name, attributes); } } - public void endElement(String name) throws SAXException { + public void endElement(String uri, String local, String name) throws SAXException { if (isForwarding()) { - getHandler().endElement(name); + getHandler().endElement(uri, local, name); _depth--; if (!isForwarding()) { - getHandler().reset(); + getHandler().startDocument(); } } else { diff --git a/jdk/test/java/beans/XMLDecoder/Test4864117.java b/jdk/test/java/beans/XMLDecoder/Test4864117.java new file mode 100644 index 00000000000..a3459f918c6 --- /dev/null +++ b/jdk/test/java/beans/XMLDecoder/Test4864117.java @@ -0,0 +1,146 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. 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. + * + * 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 4864117 + * @summary Tests XMLDecoder within another DefaultHandler for SAX parser + * @author Sergey Malenkov + */ + +import java.beans.XMLDecoder; +import java.beans.ExceptionListener; + +import java.io.ByteArrayInputStream; +import java.io.InputStream; +import java.io.IOException; + +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.parsers.SAXParserFactory; + +import org.xml.sax.Attributes; +import org.xml.sax.SAXException; +import org.xml.sax.helpers.DefaultHandler; + +public final class Test4864117 extends DefaultHandler implements ExceptionListener { + private static final String TEST = "test"; + private static final String DATA + = "\n" + + " \n" + + " Hello, world!\n" + + " \n" + + ""; + + public static void main(String[] args) { + Test4864117 test = new Test4864117(); + InputStream input = new ByteArrayInputStream(DATA.getBytes()); + Exception error = null; + try { + SAXParserFactory.newInstance().newSAXParser().parse(input, test); + } + catch (ParserConfigurationException exception) { + error = exception; + } + catch (SAXException exception) { + error = exception.getException(); + if (error == null) { + error = exception; + } + } + catch (IOException exception) { + error = exception; + } + if (error != null) { + throw new Error("unexpected error", error); + } + test.print('?', test.getMessage()); + } + + private String message; + + public String getMessage() { + if (this.message == null) { + throw new Error("owner's method is not called"); + } + return this.message; + } + + public void setMessage(String message) { + this.message = message; + print(':', this.message); + } + + // DefaultHandler implementation + + private DefaultHandler handler; + private int depth; + + @Override + public void startDocument() throws SAXException { + this.handler = XMLDecoder.createHandler(this, this, null); + this.handler.startDocument(); + } + + @Override + public void endDocument() { + this.handler = null; + } + + @Override + public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { + print('>', qName); + if (this.depth > 0) { + this.handler.startElement(uri, localName, qName, attributes); + } else if (!TEST.equals(qName)) { + throw new SAXException("unexpected element name: " + qName); + } + this.depth++; + } + + @Override + public void endElement(String uri, String localName, String qName) throws SAXException { + this.depth--; + print('<', qName); + if (this.depth > 0) { + this.handler.endElement(uri, localName, qName); + } else if (!TEST.equals(qName)) { + throw new SAXException("unexpected element name: " + qName); + } + } + + @Override + public void characters(char[] ch, int start, int length) throws SAXException { + this.handler.characters(ch, start, length); + } + + public void exceptionThrown(Exception exception) { + throw new Error("unexpected exception", exception); + } + + private void print(char ch, String name) { + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < this.depth; i++) sb.append(' '); + sb.append(ch).append(' ').append(name); + System.out.println(sb.toString()); + } +} diff --git a/jdk/test/java/beans/XMLDecoder/Test6341798.java b/jdk/test/java/beans/XMLDecoder/Test6341798.java index 2bc43e87565..677ff842352 100644 --- a/jdk/test/java/beans/XMLDecoder/Test6341798.java +++ b/jdk/test/java/beans/XMLDecoder/Test6341798.java @@ -1,5 +1,5 @@ /* - * Copyright 2005-2007 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2005-2008 Sun Microsystems, Inc. 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 @@ -39,7 +39,7 @@ public class Test6341798 { private static final String DATA = "\n" - + " \n" + + " \n" + " \n" + " true\n" + " \n" diff --git a/jdk/test/java/beans/XMLDecoder/spec/AbstractTest.java b/jdk/test/java/beans/XMLDecoder/spec/AbstractTest.java new file mode 100644 index 00000000000..2b8abb2af9e --- /dev/null +++ b/jdk/test/java/beans/XMLDecoder/spec/AbstractTest.java @@ -0,0 +1,76 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. 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. + * + * 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +import java.beans.ExceptionListener; +import java.beans.XMLDecoder; + +import java.io.ByteArrayInputStream; + +abstract class AbstractTest implements ExceptionListener { + public void exceptionThrown(Exception exception) { + throw new Error("unexpected exception", exception); + } + + /** + * Validates the XML decoder for XML archive + * that defined in the public field of the subclass. + * + * @param decoder the initialized XML decoder + * @throws Error if validation failed + */ + protected abstract void validate(XMLDecoder decoder); + + /** + * This is entry point to start testing. + * + * @param security use {@code true} to start + * second pass in secure context + */ + final void test(boolean security) { + byte[] array = getFieldValue("XML").getBytes(); // NON-NLS: the field name + ByteArrayInputStream input = new ByteArrayInputStream(array); + XMLDecoder decoder = new XMLDecoder(input); + decoder.setExceptionListener(this); + validate(decoder); + try { + throw new Error("unexpected object" + decoder.readObject()); + } catch (ArrayIndexOutOfBoundsException exception) { + // expected exception + } + decoder.close(); + if (security) { + System.setSecurityManager(new SecurityManager()); + test(false); + } + } + + private String getFieldValue(String field) { + try { + return getClass().getField(field).get(this).toString(); + } catch (NoSuchFieldException exception) { + throw new Error("unexpected exception", exception); + } catch (IllegalAccessException exception) { + throw new Error("unexpected exception", exception); + } + } +} diff --git a/jdk/test/java/beans/XMLDecoder/spec/TestArray.java b/jdk/test/java/beans/XMLDecoder/spec/TestArray.java new file mode 100644 index 00000000000..7ae34a148e5 --- /dev/null +++ b/jdk/test/java/beans/XMLDecoder/spec/TestArray.java @@ -0,0 +1,86 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. 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. + * + * 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @summary Tests element + * @author Sergey Malenkov + */ + +import java.beans.XMLDecoder; +import java.lang.reflect.Array; + +public final class TestArray extends AbstractTest { + public static final String XML + = "\n" + + " \n" + + " -111\n" + + " 1111\n" + + " \n" + + " \n" + + " \n" + + " Hello, world!\n" + + " \n" + + " \n" + + ""; + + public static void main(String[] args) { + new TestArray().test(true); + } + + @Override + protected void validate(XMLDecoder decoder) { + Number[] numbers = getArray(Number.class, 2, decoder.readObject()); + if (!numbers[0].equals(Byte.valueOf("-111"))) { // NON-NLS: hardcoded in XML + throw new Error("unexpected byte value"); + } + if (!numbers[1].equals(Long.valueOf("1111"))) { // NON-NLS: hardcoded in XML + throw new Error("unexpected long value"); + } + + Object[] objects = getArray(Object.class, 3, decoder.readObject()); + if (objects[0] != null) { + throw new Error("unexpected first value"); + } + if (!objects[1].equals("Hello, world!")) { // NON-NLS: hardcoded in XML + throw new Error("unexpected string value"); + } + if (objects[2] != null) { + throw new Error("unexpected last value"); + } + } + + private static T[] getArray(Class component, int length, Object object) { + Class type = object.getClass(); + if (!type.isArray()) { + throw new Error("array expected"); + } + if (!type.getComponentType().equals(component)) { + throw new Error("unexpected component type"); + } + if (length != Array.getLength(object)) { + throw new Error("unexpected array length"); + } + return (T[]) object; + } +} diff --git a/jdk/test/java/beans/XMLDecoder/spec/TestBoolean.java b/jdk/test/java/beans/XMLDecoder/spec/TestBoolean.java new file mode 100644 index 00000000000..e24d1fb4f72 --- /dev/null +++ b/jdk/test/java/beans/XMLDecoder/spec/TestBoolean.java @@ -0,0 +1,52 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. 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. + * + * 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @summary Tests element + * @author Sergey Malenkov + */ + +import java.beans.XMLDecoder; + +public final class TestBoolean extends AbstractTest { + public static final String XML + = "\n" + + " true\n" + + " false\n" + + ""; + + public static void main(String[] args) { + new TestBoolean().test(true); + } + + @Override + protected void validate(XMLDecoder decoder) { + if (!Boolean.TRUE.equals(decoder.readObject())) { + throw new Error("true expected"); + } + if (!Boolean.FALSE.equals(decoder.readObject())) { + throw new Error("false expected"); + } + } +} diff --git a/jdk/test/java/beans/XMLDecoder/spec/TestByte.java b/jdk/test/java/beans/XMLDecoder/spec/TestByte.java new file mode 100644 index 00000000000..46693d94c0b --- /dev/null +++ b/jdk/test/java/beans/XMLDecoder/spec/TestByte.java @@ -0,0 +1,56 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. 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. + * + * 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @summary Tests element + * @author Sergey Malenkov + */ + +import java.beans.XMLDecoder; + +public final class TestByte extends AbstractTest { + public static final String XML + = "\n" + + " 0\n" + + " 127\n" + + " -128\n" + + ""; + + public static void main(String[] args) { + new TestByte().test(true); + } + + @Override + protected void validate(XMLDecoder decoder) { + validate((byte) 0, decoder.readObject()); + validate(Byte.MAX_VALUE, decoder.readObject()); + validate(Byte.MIN_VALUE, decoder.readObject()); + } + + private static void validate(byte value, Object object) { + if (!object.equals(Byte.valueOf(value))) { + throw new Error("byte " + value + " expected"); + } + } +} diff --git a/jdk/test/java/beans/XMLDecoder/spec/TestChar.java b/jdk/test/java/beans/XMLDecoder/spec/TestChar.java new file mode 100644 index 00000000000..cb29b713bce --- /dev/null +++ b/jdk/test/java/beans/XMLDecoder/spec/TestChar.java @@ -0,0 +1,52 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. 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. + * + * 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @summary Tests element + * @author Sergey Malenkov + */ + +import java.beans.XMLDecoder; + +public final class TestChar extends AbstractTest { + public static final String XML + = "\n" + + " X\n" + + " \n" + + ""; + + public static void main(String[] args) { + new TestChar().test(true); + } + + @Override + protected void validate(XMLDecoder decoder) { + if (!decoder.readObject().equals(Character.valueOf('X'))) { + throw new Error("unexpected character"); + } + if (!decoder.readObject().equals(Character.valueOf((char) 0x20))) { + throw new Error("unexpected character code"); + } + } +} diff --git a/jdk/test/java/beans/XMLDecoder/spec/TestClass.java b/jdk/test/java/beans/XMLDecoder/spec/TestClass.java new file mode 100644 index 00000000000..2c16ba75f3c --- /dev/null +++ b/jdk/test/java/beans/XMLDecoder/spec/TestClass.java @@ -0,0 +1,61 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. 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. + * + * 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @summary Tests element + * @author Sergey Malenkov + */ + +import java.beans.XMLDecoder; + +public final class TestClass extends AbstractTest { + public static final String PREFIX = "javax.swing.colorchooser."; + public static final String INTERFACE = "ColorSelectionModel"; + public static final String PUBLIC_CLASS = "DefaultColorSelectionModel"; + public static final String PRIVATE_CLASS = "DiagramComponent"; + public static final String XML + = "\n" + + " " + PREFIX + INTERFACE + "\n" + + " " + PREFIX + PUBLIC_CLASS + "\n" + + " " + PREFIX + PRIVATE_CLASS + "\n" + + ""; + + public static void main(String[] args) { + new TestClass().test(true); + } + + @Override + protected void validate(XMLDecoder decoder) { + validate(PREFIX + INTERFACE, decoder.readObject()); + validate(PREFIX + PUBLIC_CLASS, decoder.readObject()); + validate(PREFIX + PRIVATE_CLASS, decoder.readObject()); + } + + private static void validate(String name, Object object) { + Class type = (Class) object; + if (!type.getName().equals(name)) { + throw new Error(name + " expected"); + } + } +} diff --git a/jdk/test/java/beans/XMLDecoder/spec/TestDouble.java b/jdk/test/java/beans/XMLDecoder/spec/TestDouble.java new file mode 100644 index 00000000000..8e3d918c886 --- /dev/null +++ b/jdk/test/java/beans/XMLDecoder/spec/TestDouble.java @@ -0,0 +1,58 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. 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. + * + * 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @summary Tests element + * @author Sergey Malenkov + */ + +import java.beans.XMLDecoder; + +public final class TestDouble extends AbstractTest { + public static final String XML + = "\n" + + " 0\n" + + " 1000\n" + + " -1.1e15\n" + + " 10.11e-123\n" + + ""; + + public static void main(String[] args) { + new TestDouble().test(true); + } + + @Override + protected void validate(XMLDecoder decoder) { + validate(0.0, decoder.readObject()); + validate(1000.0, decoder.readObject()); + validate(-1.1e15, decoder.readObject()); + validate(10.11e-123, decoder.readObject()); + } + + private static void validate(double value, Object object) { + if (!object.equals(Double.valueOf(value))) { + throw new Error("double " + value + " expected"); + } + } +} diff --git a/jdk/test/java/beans/XMLDecoder/spec/TestFalse.java b/jdk/test/java/beans/XMLDecoder/spec/TestFalse.java new file mode 100644 index 00000000000..57a81b87740 --- /dev/null +++ b/jdk/test/java/beans/XMLDecoder/spec/TestFalse.java @@ -0,0 +1,48 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. 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. + * + * 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @summary Tests element + * @author Sergey Malenkov + */ + +import java.beans.XMLDecoder; + +public final class TestFalse extends AbstractTest { + public static final String XML + = "\n" + + " \n" + + ""; + + public static void main(String[] args) { + new TestFalse().test(true); + } + + @Override + protected void validate(XMLDecoder decoder) { + if (!Boolean.FALSE.equals(decoder.readObject())) { + throw new Error("false expected"); + } + } +} diff --git a/jdk/test/java/beans/XMLDecoder/spec/TestField.java b/jdk/test/java/beans/XMLDecoder/spec/TestField.java new file mode 100644 index 00000000000..aa84408814e --- /dev/null +++ b/jdk/test/java/beans/XMLDecoder/spec/TestField.java @@ -0,0 +1,74 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. 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. + * + * 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @summary Tests element + * @author Sergey Malenkov + */ + +import java.beans.XMLDecoder; + +public final class TestField extends AbstractTest { + public static final String XML + = "\n" + + " \n" + + " \n" + + " static postfix\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " postfix\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + ""; + + public static void main(String[] args) { + new TestField().test(true); + } + + public static String FIELD; + public String field; + + @Override + protected void validate(XMLDecoder decoder) { + FIELD = "static prefix"; + field = "prefix"; + decoder.setOwner(this); + validate(decoder, "static prefix"); + validate(decoder, "static postfix"); + validate(decoder, "prefix"); + validate(decoder, "postfix"); + } + + private static void validate(XMLDecoder decoder, String name) { + if (!decoder.readObject().equals(name)) { + throw new Error(name + " expected"); + } + } +} diff --git a/jdk/test/java/beans/XMLDecoder/spec/TestFloat.java b/jdk/test/java/beans/XMLDecoder/spec/TestFloat.java new file mode 100644 index 00000000000..bb1287f8804 --- /dev/null +++ b/jdk/test/java/beans/XMLDecoder/spec/TestFloat.java @@ -0,0 +1,58 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. 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. + * + * 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @summary Tests element + * @author Sergey Malenkov + */ + +import java.beans.XMLDecoder; + +public final class TestFloat extends AbstractTest { + public static final String XML + = "\n" + + " 0\n" + + " 100\n" + + " -1e15\n" + + " 100e-20\n" + + ""; + + public static void main(String[] args) { + new TestFloat().test(true); + } + + @Override + protected void validate(XMLDecoder decoder) { + validate(0.0f, decoder.readObject()); + validate(100.0f, decoder.readObject()); + validate(-1e15f, decoder.readObject()); + validate(100e-20f, decoder.readObject()); + } + + private static void validate(float value, Object object) { + if (!object.equals(Float.valueOf(value))) { + throw new Error("float " + value + " expected"); + } + } +} diff --git a/jdk/test/java/beans/XMLDecoder/spec/TestInt.java b/jdk/test/java/beans/XMLDecoder/spec/TestInt.java new file mode 100644 index 00000000000..531c9447b64 --- /dev/null +++ b/jdk/test/java/beans/XMLDecoder/spec/TestInt.java @@ -0,0 +1,64 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. 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. + * + * 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @summary Tests element + * @author Sergey Malenkov + */ + +import java.beans.XMLDecoder; + +public final class TestInt extends AbstractTest { + public static final String XML + = "\n" + + " 0\n" + + " 127\n" + + " -128\n" + + " 32767\n" + + " -32768\n" + + " 2147483647\n" + + " -2147483648\n" + + ""; + + public static void main(String[] args) { + new TestInt().test(true); + } + + @Override + protected void validate(XMLDecoder decoder) { + validate(0, decoder.readObject()); + validate((int) Byte.MAX_VALUE, decoder.readObject()); + validate((int) Byte.MIN_VALUE, decoder.readObject()); + validate((int) Short.MAX_VALUE, decoder.readObject()); + validate((int) Short.MIN_VALUE, decoder.readObject()); + validate(Integer.MAX_VALUE, decoder.readObject()); + validate(Integer.MIN_VALUE, decoder.readObject()); + } + + private static void validate(int value, Object object) { + if (!object.equals(Integer.valueOf(value))) { + throw new Error("int " + value + " expected"); + } + } +} diff --git a/jdk/test/java/beans/XMLDecoder/spec/TestJava.java b/jdk/test/java/beans/XMLDecoder/spec/TestJava.java new file mode 100644 index 00000000000..5786195aaa0 --- /dev/null +++ b/jdk/test/java/beans/XMLDecoder/spec/TestJava.java @@ -0,0 +1,63 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. 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. + * + * 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @summary Tests element + * @author Sergey Malenkov + */ + +import java.beans.XMLDecoder; + +public final class TestJava extends AbstractTest { + public static final String XML + = "\n" + + " \n" + + " \n" + + " Hello, world!\n" + + " \n" + + " \n" + + " \n" + + ""; + + public static void main(String[] args) { + new TestJava().test(true); + } + + private String message; + + public void init(String message) { + this.message = message; + } + + @Override + protected void validate(XMLDecoder decoder) { + decoder.setOwner(this); + if (this != decoder.readObject()) { + throw new Error("owner should be the same"); + } + if (this.message == null) { + throw new Error("owner's method is not called"); + } + } +} diff --git a/jdk/test/java/beans/XMLDecoder/spec/TestLong.java b/jdk/test/java/beans/XMLDecoder/spec/TestLong.java new file mode 100644 index 00000000000..16a7e324014 --- /dev/null +++ b/jdk/test/java/beans/XMLDecoder/spec/TestLong.java @@ -0,0 +1,68 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. 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. + * + * 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @summary Tests element + * @author Sergey Malenkov + */ + +import java.beans.XMLDecoder; + +public final class TestLong extends AbstractTest { + public static final String XML + = "\n" + + " 0\n" + + " 127\n" + + " -128\n" + + " 32767\n" + + " -32768\n" + + " 2147483647\n" + + " -2147483648\n" + + " 9223372036854775807\n" + + " -9223372036854775808\n" + + ""; + + public static void main(String[] args) { + new TestLong().test(true); + } + + @Override + protected void validate(XMLDecoder decoder) { + validate(0L, decoder.readObject()); + validate((long) Byte.MAX_VALUE, decoder.readObject()); + validate((long) Byte.MIN_VALUE, decoder.readObject()); + validate((long) Short.MAX_VALUE, decoder.readObject()); + validate((long) Short.MIN_VALUE, decoder.readObject()); + validate((long) Integer.MAX_VALUE, decoder.readObject()); + validate((long) Integer.MIN_VALUE, decoder.readObject()); + validate(Long.MAX_VALUE, decoder.readObject()); + validate(Long.MIN_VALUE, decoder.readObject()); + } + + private static void validate(long value, Object object) { + if (!object.equals(Long.valueOf(value))) { + throw new Error("long " + value + " expected"); + } + } +} diff --git a/jdk/test/java/beans/XMLDecoder/spec/TestMethod.java b/jdk/test/java/beans/XMLDecoder/spec/TestMethod.java new file mode 100644 index 00000000000..01ee5e1cf95 --- /dev/null +++ b/jdk/test/java/beans/XMLDecoder/spec/TestMethod.java @@ -0,0 +1,178 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. 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. + * + * 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @summary Tests element + * @author Sergey Malenkov + */ + +import java.beans.XMLDecoder; + +public final class TestMethod extends AbstractTest { + public static final String XML + = "\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + ""; + + public static void main(String[] args) { + new TestMethod().test(true); + } + + private NoSuchMethodException exception; + + @Override + public void exceptionThrown(Exception exception) { + if (this.exception != null) { + // only one exception allowed + super.exceptionThrown(exception); + } else if (exception instanceof NoSuchMethodException) { + // expected exception: ambiguous methods are found + this.exception = (NoSuchMethodException) exception; + } else { + super.exceptionThrown(exception); + } + } + + @Override + protected void validate(XMLDecoder decoder) { + this.exception = null; + validate(decoder, A.class); + validate(decoder, B.class); + validate(decoder, C.class); + validate(decoder, D.class); + validate(decoder, E.class); + if (this.exception == null) { + throw new Error("NoSuchMethodException expected"); + } + } + + private static void validate(XMLDecoder decoder, Class type) { + if (!type.equals(decoder.readObject().getClass())) { + throw new Error("unexpected class"); + } + } + + /** + * All ambiguous method declarations should fail. + */ + public static class A { + public void m(X x1, X x2) { + throw new Error("A.m(X,X) should not be called"); + } + + public void m(X x1, Y y2) { + throw new Error("A.m(X,Y) should not be called"); + } + + public void m(Y y1, X x2) { + throw new Error("A.m(Y,X) should not be called"); + } + } + + /** + * The most specific method in this case would be the second declaration. + */ + public static class B { + public void m(X x1, X x2) { + throw new Error("B.m(X,X) should not be called"); + } + + public void m(X x1, Y y2) { + // expected: B.m(X,Y) should be called + } + } + + /** + * The most specific method in this case would be the first declaration. + */ + public static class C { + public void m(Y y1, Y y2) { + // expected: C.m(Y,Y) should be called + } + + public void m(X x1, X x2) { + throw new Error("C.m(X,X) should not be called"); + } + } + + /** + * Same as the previous case but flip methods. + */ + public static class D { + public void m(X x1, X x2) { + throw new Error("D.m(X,X) should not be called"); + } + + public void m(Y y1, Y y2) { + // expected: D.m(Y,Y) should be called + } + } + + /** + * The method should be called with (Z,Z). + */ + public static class E { + public void m(X x1, X x2) { + // expected: E.m(X,X) should be called + } + } + + public static class X { + } + + public static class Y extends X { + } + + public static class Z extends Y { + } +} diff --git a/jdk/test/java/beans/XMLDecoder/spec/TestNew.java b/jdk/test/java/beans/XMLDecoder/spec/TestNew.java new file mode 100644 index 00000000000..3e1e86d9951 --- /dev/null +++ b/jdk/test/java/beans/XMLDecoder/spec/TestNew.java @@ -0,0 +1,90 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. 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. + * + * 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @summary Tests element + * @author Sergey Malenkov + */ + +import java.beans.XMLDecoder; +import java.util.ArrayList; +import java.util.List; + +public final class TestNew extends AbstractTest { + public static final String XML + = "\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " single\n" + + " \n" + + " \n" + + " first\n" + + " second\n" + + " third\n" + + " \n" + + ""; + + public static void main(String[] args) { + new TestNew().test(true); + } + + private List list; + + public TestNew(String...messages) { + if (messages != null) { + this.list = new ArrayList(); + for (String message : messages) { + this.list.add(message); + } + } + } + + @Override + public boolean equals(Object object) { + if (object instanceof TestNew) { + TestNew test = (TestNew) object; + return (test.list == null) + ? this.list == null + : test.list.equals(this.list); + } + return false; + } + + @Override + protected void validate(XMLDecoder decoder) { + validate(decoder.readObject()); + validate(decoder.readObject(), null); + validate(decoder.readObject(), "single"); + validate(decoder.readObject(), "first", "second", "third"); + } + + private static void validate(Object object, String...messages) { + if (!object.equals(new TestNew(messages))) { + throw new Error("expected object"); + } + } +} diff --git a/jdk/test/java/beans/XMLDecoder/spec/TestNull.java b/jdk/test/java/beans/XMLDecoder/spec/TestNull.java new file mode 100644 index 00000000000..e14bf951e58 --- /dev/null +++ b/jdk/test/java/beans/XMLDecoder/spec/TestNull.java @@ -0,0 +1,48 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. 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. + * + * 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @summary Tests element + * @author Sergey Malenkov + */ + +import java.beans.XMLDecoder; + +public final class TestNull extends AbstractTest { + public static final String XML + = "\n" + + " \n" + + ""; + + public static void main(String[] args) { + new TestNull().test(true); + } + + @Override + protected void validate(XMLDecoder decoder) { + if (null != decoder.readObject()) { + throw new Error("null value expected"); + } + } +} diff --git a/jdk/test/java/beans/XMLDecoder/spec/TestObject.java b/jdk/test/java/beans/XMLDecoder/spec/TestObject.java new file mode 100644 index 00000000000..d9531b3d646 --- /dev/null +++ b/jdk/test/java/beans/XMLDecoder/spec/TestObject.java @@ -0,0 +1,84 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. 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. + * + * 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @summary Tests element + * @author Sergey Malenkov + */ + +import java.beans.XMLDecoder; +import javax.swing.JButton; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.SwingConstants; + +public final class TestObject extends AbstractTest { + public static final String XML // TODO + = "\n" + + " \n" + + " \n" + + " \n" + + " button\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " label\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + ""; + + public static void main(String[] args) { + new TestObject().test(true); + } + + @Override + protected void validate(XMLDecoder decoder) { + JPanel panel = (JPanel) decoder.readObject(); + if (2 != panel.getComponents().length) { + throw new Error("unexpected component count"); + } + JButton button = (JButton) panel.getComponents()[0]; + if (!button.getText().equals("button")) { // NON-NLS: hardcoded in XML + throw new Error("unexpected button text"); + } + if (SwingConstants.CENTER != button.getVerticalAlignment()) { + throw new Error("unexpected vertical alignment"); + } + JLabel label = (JLabel) panel.getComponents()[1]; + if (!label.getText().equals("label")) { // NON-NLS: hardcoded in XML + throw new Error("unexpected label text"); + } + if (button != label.getLabelFor()) { + throw new Error("unexpected component"); + } + } +} diff --git a/jdk/test/java/beans/XMLDecoder/spec/TestProperty.java b/jdk/test/java/beans/XMLDecoder/spec/TestProperty.java new file mode 100644 index 00000000000..e1f9c77e445 --- /dev/null +++ b/jdk/test/java/beans/XMLDecoder/spec/TestProperty.java @@ -0,0 +1,88 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. 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. + * + * 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @summary Tests element + * @author Sergey Malenkov + */ + +import java.beans.XMLDecoder; + +public final class TestProperty extends AbstractTest { + public static final String XML + = "\n" + + " \n" + + " \n" + + " message\n" + + " \n" + + " \n" + + " \n" + + " indexed\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + ""; + + public static void main(String[] args) { + new TestProperty().test(true); + } + + private int index; + private String message; + + public String getMessage() { + return this.message; + } + + public void setMessage(String message) { + this.message = message; + } + + public String getIndexed(int index) { + if (this.index != index) { + throw new Error("unexpected index"); + } + return this.message; + } + + public void setIndexed(int index, String message) { + this.index = index; + this.message = message; + } + + @Override + protected void validate(XMLDecoder decoder) { + decoder.setOwner(this); + validate(decoder, "message"); + validate(decoder, "indexed"); + } + + private static void validate(XMLDecoder decoder, String name) { + if (!decoder.readObject().equals(name)) { + throw new Error(name + " expected"); + } + } +} diff --git a/jdk/test/java/beans/XMLDecoder/spec/TestShort.java b/jdk/test/java/beans/XMLDecoder/spec/TestShort.java new file mode 100644 index 00000000000..99a0c57d357 --- /dev/null +++ b/jdk/test/java/beans/XMLDecoder/spec/TestShort.java @@ -0,0 +1,60 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. 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. + * + * 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @summary Tests element + * @author Sergey Malenkov + */ + +import java.beans.XMLDecoder; + +public final class TestShort extends AbstractTest { + public static final String XML + = "\n" + + " 0\n" + + " 127\n" + + " -128\n" + + " 32767\n" + + " -32768\n" + + ""; + + public static void main(String[] args) { + new TestShort().test(true); + } + + @Override + protected void validate(XMLDecoder decoder) { + validate((short) 0, decoder.readObject()); + validate((short) Byte.MAX_VALUE, decoder.readObject()); + validate((short) Byte.MIN_VALUE, decoder.readObject()); + validate(Short.MAX_VALUE, decoder.readObject()); + validate(Short.MIN_VALUE, decoder.readObject()); + } + + private static void validate(short value, Object object) { + if (!object.equals(Short.valueOf(value))) { + throw new Error("short " + value + " expected"); + } + } +} diff --git a/jdk/test/java/beans/XMLDecoder/spec/TestString.java b/jdk/test/java/beans/XMLDecoder/spec/TestString.java new file mode 100644 index 00000000000..d41b1bbce38 --- /dev/null +++ b/jdk/test/java/beans/XMLDecoder/spec/TestString.java @@ -0,0 +1,60 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. 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. + * + * 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @summary Tests element + * @author Sergey Malenkov + */ + +import java.beans.XMLDecoder; + +public final class TestString extends AbstractTest { + public static final String PREFIX = " prefix "; + public static final String POSTFIX = " postfix "; + public static final String XML + = "\n" + + " " + PREFIX + "\n" + + " " + POSTFIX + "\n" + + " " + PREFIX + POSTFIX + "\n" + + " " + PREFIX + "" + POSTFIX + "\n" + + ""; + + public static void main(String[] args) { + new TestString().test(true); + } + + @Override + protected void validate(XMLDecoder decoder) { + validate(PREFIX, decoder.readObject()); + validate(POSTFIX, decoder.readObject()); + validate(PREFIX + POSTFIX, decoder.readObject()); + validate(PREFIX + '\u0000' + POSTFIX, decoder.readObject()); + } + + private static void validate(String name, Object object) { + if (!object.equals(name)) { + throw new Error(name + " expected"); + } + } +} diff --git a/jdk/test/java/beans/XMLDecoder/spec/TestTrue.java b/jdk/test/java/beans/XMLDecoder/spec/TestTrue.java new file mode 100644 index 00000000000..934d28e4f63 --- /dev/null +++ b/jdk/test/java/beans/XMLDecoder/spec/TestTrue.java @@ -0,0 +1,48 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. 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. + * + * 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @summary Tests element + * @author Sergey Malenkov + */ + +import java.beans.XMLDecoder; + +public final class TestTrue extends AbstractTest { + public static final String XML + = "\n" + + " \n" + + ""; + + public static void main(String[] args) { + new TestTrue().test(true); + } + + @Override + protected void validate(XMLDecoder decoder) { + if (!Boolean.TRUE.equals(decoder.readObject())) { + throw new Error("true expected"); + } + } +} diff --git a/jdk/test/java/beans/XMLDecoder/spec/TestVar.java b/jdk/test/java/beans/XMLDecoder/spec/TestVar.java new file mode 100644 index 00000000000..701edad79a8 --- /dev/null +++ b/jdk/test/java/beans/XMLDecoder/spec/TestVar.java @@ -0,0 +1,54 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. 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. + * + * 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @summary Tests element + * @author Sergey Malenkov + */ + +import java.beans.XMLDecoder; + +public final class TestVar extends AbstractTest { + public static final String XML + = "\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + ""; + + public static void main(String[] args) { + new TestVar().test(true); + } + + @Override + protected void validate(XMLDecoder decoder) { + for (int i = 0; i < 3; i++) { + if (decoder != decoder.readObject()) { + throw new Error("decoder instance expected"); + } + } + } +}