4864117: RFE: Make XMLDecoder API more reusable

Reviewed-by: peterz, loneid
This commit is contained in:
Sergey Malenkov 2008-12-22 17:42:49 +03:00
parent 8242c2b3b6
commit 9330abadea
64 changed files with 5946 additions and 673 deletions

View File

@ -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;
/**
* <b>WARNING</b>: This class is an implementation detail and only meant
* for use within the core platform. You should NOT depend upon it! This
* API may change drastically between dot dot release, and it may even be
* removed.
*
* @see java.beans.XMLEncoder
* @see java.io.ObjectInputStream
*
* @since 1.4
*
* @author Philip Milne
*/
public class ObjectHandler extends HandlerBase {
public static Class typeNameToClass(String typeName) {
typeName = typeName.intern();
if (typeName == "boolean") return Boolean.class;
if (typeName == "byte") return Byte.class;
if (typeName == "char") return Character.class;
if (typeName == "short") return Short.class;
if (typeName == "int") return Integer.class;
if (typeName == "long") return Long.class;
if (typeName == "float") return Float.class;
if (typeName == "double") return Double.class;
if (typeName == "void") return Void.class;
return null;
}
public static Class typeNameToPrimitiveClass(String typeName) {
typeName = typeName.intern();
if (typeName == "boolean") return boolean.class;
if (typeName == "byte") return byte.class;
if (typeName == "char") return char.class;
if (typeName == "short") return short.class;
if (typeName == "int") return int.class;
if (typeName == "long") return long.class;
if (typeName == "float") return float.class;
if (typeName == "double") return double.class;
if (typeName == "void") return void.class;
return null;
}
/**
* Returns the <code>Class</code> object associated with
* the class or interface with the given string name,
* using the default class loader.
*
* @param name fully qualified name of the desired class
* @param cl class loader from which the class must be loaded
* @return class object representing the desired class
*
* @exception ClassNotFoundException if the class cannot be located
* by the specified class loader
*
* @deprecated As of JDK version 7, replaced by
* {@link ClassFinder#resolveClass(String)}.
*/
@Deprecated
public static Class classForName(String name) throws ClassNotFoundException {
return ClassFinder.resolveClass(name);
}
/**
* Returns the <code>Class</code> object associated with
* the class or interface with the given string name,
* using the given class loader.
*
* @param name fully qualified name of the desired class
* @param cl class loader from which the class must be loaded
* @return class object representing the desired class
*
* @exception ClassNotFoundException if the class cannot be located
* by the specified class loader
*
* @deprecated As of JDK version 7, replaced by
* {@link ClassFinder#resolveClass(String,ClassLoader)}.
*/
@Deprecated
public static Class classForName(String name, ClassLoader cl)
throws ClassNotFoundException {
return ClassFinder.resolveClass(name, cl);
}
private Hashtable environment;
private Vector expStack;
private StringBuffer chars;
private XMLDecoder is;
private ClassLoader ldr;
private int itemsRead = 0;
private boolean isString;
public ObjectHandler() {
environment = new Hashtable();
expStack = new Vector();
chars = new StringBuffer();
}
public ObjectHandler(XMLDecoder is) {
this();
this.is = is;
}
/* loader can be null */
public ObjectHandler(XMLDecoder is, ClassLoader loader) {
this(is);
this.ldr = loader;
}
public void reset() {
expStack.clear();
chars.setLength(0);
MutableExpression e = new MutableExpression();
e.setTarget(classForName2("java.lang.Object"));
e.setMethodName("null");
expStack.add(e);
}
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();
}
}

View File

@ -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:
* <dl>
* <dt>name
* <dd>the name of the accessible entity
* <dt>id
* <dd>the identifier of the variable that is intended to store the result
* </dl>
*
* @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);
}

View File

@ -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 &lt;array&gt; 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:<pre>
* &lt;array length="10"/&gt;</pre>
* 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:<pre>
* &lt;array length="3" class="java.lang.String"&gt;
* &lt;void index="1"&gt;
* &lt;string&gt;Hello, world&lt;/string&gt;
* &lt;/void&gt;
* &lt;/array&gt;</pre>
* is equivalent to the following Java code:<pre>
* String[] s = new String[3];
* s[1] = "Hello, world";</pre>
* 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:<pre>
* &lt;array id="array" class="int"&gt;
* &lt;int&gt;123&lt;/int&gt;
* &lt;int&gt;456&lt;/int&gt;
* &lt;/array&gt;</pre>
* is equivalent to {@code int[] array = {123, 456}} in Java code.
* <p>The following atributes are supported:
* <dl>
* <dt>length
* <dd>the array length
* <dt>class
* <dd>the type of object for instantiation
* <dt>id
* <dd>the identifier of the variable that is intended to store the result
* </dl>
*
* @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:
* <dl>
* <dt>length
* <dd>the array length
* <dt>class
* <dd>the type of object for instantiation
* <dt>id
* <dd>the identifier of the variable that is intended to store the result
* </dl>
*
* @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);
}
}

View File

@ -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 &lt;boolean&gt; 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:<pre>
* &lt;boolean&gt;true&lt;/boolean&gt;</pre>
* is shortcut to<pre>
* &lt;method name="valueOf" class="java.lang.Boolean"&gt;
* &lt;string&gt;true&lt;/string&gt;
* &lt;/method&gt;</pre>
* which is equivalent to {@code Boolean.valueOf("true")} in Java code.
* <p>The following atribute is supported:
* <dl>
* <dt>id
* <dd>the identifier of the variable that is intended to store the result
* </dl>
*
* @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);
}
}

View File

@ -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 &lt;byte&gt; 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:<pre>
* &lt;byte&gt;127&lt;/byte&gt;</pre>
* is shortcut to<pre>
* &lt;method name="decode" class="java.lang.Byte"&gt;
* &lt;string&gt;127&lt;/string&gt;
* &lt;/method&gt;</pre>
* which is equivalent to {@code Byte.decode("127")} in Java code.
* <p>The following atribute is supported:
* <dl>
* <dt>id
* <dd>the identifier of the variable that is intended to store the result
* </dl>
*
* @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);
}
}

View File

@ -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 &lt;char&gt; 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:<pre>
* &lt;char&gt;X&lt;/char&gt;</pre>
* which is equivalent to {@code Character.valueOf('X')} in Java code.
* <p>The following atributes are supported:
* <dl>
* <dt>code
* <dd>this attribute specifies character code
* <dt>id
* <dd>the identifier of the variable that is intended to store the result
* </dl>
* The {@code code} attribute can be used for characters
* that are illegal in XML document, for example:<pre>
* &lt;char code="0"/&gt;</pre>
*
* @since 1.7
*
* @author Sergey A. Malenkov
*/
final class CharElementHandler extends StringElementHandler {
/**
* Parses attributes of the element.
* The following atributes are supported:
* <dl>
* <dt>code
* <dd>this attribute specifies character code
* <dt>id
* <dd>the identifier of the variable that is intended to store the result
* </dl>
*
* @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));
}
}

View File

@ -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 &lt;class&gt; 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:<pre>
* &lt;class&gt;java.lang.Class&lt;/class&gt;</pre>
* is shortcut to<pre>
* &lt;method name="forName" class="java.lang.Class"&gt;
* &lt;string&gt;java.lang.Class&lt;/string&gt;
* &lt;/method&gt;</pre>
* which is equivalent to {@code Class.forName("java.lang.Class")} in Java code.
* <p>The following atribute is supported:
* <dl>
* <dt>id
* <dd>the identifier of the variable that is intended to store the result
* </dl>
*
* @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);
}
}

View File

@ -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<String, Class<? extends ElementHandler>> handlers = new HashMap<String, Class<? extends ElementHandler>>();
private final Map<String, Object> environment = new HashMap<String, Object>();
private final List<Object> objects = new ArrayList<Object>();
private Reference<ClassLoader> 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<ClassLoader>(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<? extends ElementHandler> getElementHandler(String name) {
Class<? extends ElementHandler> 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<? extends ElementHandler> 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;
}
}
}

View File

@ -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 &lt;double&gt; 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:<pre>
* &lt;double&gt;1.23e45&lt;/double&gt;</pre>
* is shortcut to<pre>
* &lt;method name="valueOf" class="java.lang.Double"&gt;
* &lt;string&gt;1.23e45&lt;/string&gt;
* &lt;/method&gt;</pre>
* which is equivalent to {@code Double.valueOf("1.23e45")} in Java code.
* <p>The following atribute is supported:
* <dl>
* <dt>id
* <dd>the identifier of the variable that is intended to store the result
* </dl>
*
* @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);
}
}

View File

@ -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:
* <dl>
* <dt>id
* <dd>the identifier of the variable that is intended to store the result
* </dl>
*
* @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:
* <ol>
* <li>If the {@code id} attribute is set
* the value of the variable with the specified identifier
* is set to the value of this element.</li>
* <li>This element is used as an argument of parent element if it is possible.</li>
* </ol>
*
* @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();
}

View File

@ -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 &lt;false&gt; element.
* This element specifies {@code false} value.
* It should not contain body or inner elements.
* For example:<pre>
* &lt;false/&gt;</pre>
* is equivalent to {@code false} in Java code.
* <p>The following atribute is supported:
* <dl>
* <dt>id
* <dd>the identifier of the variable that is intended to store the result
* </dl>
*
* @since 1.7
*
* @author Sergey A. Malenkov
*/
final class FalseElementHandler extends NullElementHandler {
/**
* Returns {@code Boolean.FALSE}
* as a value of &lt;false&gt; element.
*
* @return {@code Boolean.FALSE} by default
*/
@Override
public Object getValue() {
return Boolean.FALSE;
}
}

View File

@ -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 &lt;field&gt; 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:<pre>
* &lt;field name="TYPE" class="java.lang.Long"/&gt;</pre>
* 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:<pre>
* &lt;field name="id"&gt;&lt;int&gt;0&lt;/int&gt;&lt;/field&gt;</pre>
* is equivalent to {@code id = 0} in Java code.
* <p>The following atributes are supported:
* <dl>
* <dt>name
* <dd>the field name
* <dt>class
* <dd>the type is used for static fields only
* <dt>id
* <dd>the identifier of the variable that is intended to store the result
* </dl>
*
* @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:
* <dl>
* <dt>name
* <dd>the field name
* <dt>class
* <dd>the type is used for static fields only
* <dt>id
* <dd>the identifier of the variable that is intended to store the result
* </dl>
*
* @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);
}
}

View File

@ -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 &lt;float&gt; 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:<pre>
* &lt;float&gt;-1.23&lt;/float&gt;</pre>
* is shortcut to<pre>
* &lt;method name="valueOf" class="java.lang.Float"&gt;
* &lt;string&gt;-1.23&lt;/string&gt;
* &lt;/method&gt;</pre>
* which is equivalent to {@code Float.valueOf("-1.23")} in Java code.
* <p>The following atribute is supported:
* <dl>
* <dt>id
* <dd>the identifier of the variable that is intended to store the result
* </dl>
*
* @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);
}
}

View File

@ -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 &lt;int&gt; 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:<pre>
* &lt;int&gt;-1&lt;/int&gt;</pre>
* is shortcut to<pre>
* &lt;method name="decode" class="java.lang.Integer"&gt;
* &lt;string&gt;-1&lt;/string&gt;
* &lt;/method&gt;</pre>
* which is equivalent to {@code Integer.decode("-1")} in Java code.
* <p>The following atribute is supported:
* <dl>
* <dt>id
* <dd>the identifier of the variable that is intended to store the result
* </dl>
*
* @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);
}
}

View File

@ -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 &lt;java&gt; 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.
* <p>The following atributes are supported:
* <dl>
* <dt>version
* <dd>the Java version (not supported)
* <dt>class
* <dd>the type of preferable parser (not supported)
* <dt>id
* <dd>the identifier of the variable that is intended to store the result
* </dl>
*
* @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:
* <dl>
* <dt>version
* <dd>the Java version (not supported)
* <dt>class
* <dd>the type of preferable parser (not supported)
* <dt>id
* <dd>the identifier of the variable that is intended to store the result
* </dl>
*
* @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 &lt;java&gt; 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 &lt;java&gt; 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 &lt;java&gt; 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);
}
}

View File

@ -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 &lt;long&gt; 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:<pre>
* &lt;long&gt;0xFFFF&lt;/long&gt;</pre>
* is shortcut to<pre>
* &lt;method name="decode" class="java.lang.Long"&gt;
* &lt;string&gt;0xFFFF&lt;/string&gt;
* &lt;/method&gt;</pre>
* which is equivalent to {@code Long.decode("0xFFFF")} in Java code.
* <p>The following atribute is supported:
* <dl>
* <dt>id
* <dd>the identifier of the variable that is intended to store the result
* </dl>
*
* @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);
}
}

View File

@ -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 &lt;method&gt; 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:<pre>
* &lt;method name="valueOf" class="java.lang.Long"&gt;
* &lt;string&gt;10&lt;/string&gt;
* &lt;/method&gt;</pre>
* is equivalent to {@code Long.valueOf("10")} in Java code.
* <p>The following atributes are supported:
* <dl>
* <dt>name
* <dd>the method name
* <dt>class
* <dd>the type of object for instantiation
* <dt>id
* <dd>the identifier of the variable that is intended to store the result
* </dl>
*
* @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:
* <dl>
* <dt>name
* <dd>the method name
* <dt>class
* <dd>the type of object for instantiation
* <dt>id
* <dd>the identifier of the variable that is intended to store the result
* </dl>
*
* @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);
}
}

View File

@ -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 &lt;new&gt; 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:<pre>
* &lt;new class="java.lang.Long"&gt;
* &lt;string&gt;10&lt;/string&gt;
* &lt;/new&gt;</pre>
* is equivalent to {@code new Long("10")} in Java code.
* <p>The following atributes are supported:
* <dl>
* <dt>class
* <dd>the type of object for instantiation
* <dt>id
* <dd>the identifier of the variable that is intended to store the result
* </dl>
*
* @since 1.7
*
* @author Sergey A. Malenkov
*/
class NewElementHandler extends ElementHandler {
private List<Object> arguments = new ArrayList<Object>();
private ValueObject value = ValueObjectImpl.VOID;
private Class<?> type;
/**
* Parses attributes of the element.
* The following atributes are supported:
* <dl>
* <dt>class
* <dd>the type of object for instantiation
* <dt>id
* <dd>the identifier of the variable that is intended to store the result
* </dl>
*
* @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;
}
}

View File

@ -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 &lt;null&gt; element.
* This element specifies {@code null} value.
* It should not contain body or inner elements.
* For example:<pre>
* &lt;null/&gt;</pre>
* is equivalent to {@code null} in Java code.
* <p>The following atribute is supported:
* <dl>
* <dt>id
* <dd>the identifier of the variable that is intended to store the result
* </dl>
*
* @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 &lt;null&gt; 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;
}
}

View File

@ -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 &lt;object&gt; element.
* This element looks like &lt;void&gt; element,
* but its value is always used as an argument for element
* that contains this one.
* <p>The following atributes are supported:
* <dl>
* <dt>class
* <dd>the type is used for static methods and fields
* <dt>method
* <dd>the method name
* <dt>property
* <dd>the property name
* <dt>index
* <dd>the property index
* <dt>field
* <dd>the field name
* <dt>idref
* <dd>the identifier to refer to the variable
* <dt>id
* <dd>the identifier of the variable that is intended to store the result
* </dl>
*
* @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:
* <dl>
* <dt>class
* <dd>the type is used for static methods and fields
* <dt>method
* <dd>the method name
* <dt>property
* <dd>the property name
* <dt>index
* <dd>the property index
* <dt>field
* <dd>the field name
* <dt>idref
* <dd>the identifier to refer to the variable
* <dt>id
* <dd>the identifier of the variable that is intended to store the result
* </dl>
*
* @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());
}
}

View File

@ -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 &lt;property&gt; 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:<pre>
* &lt;property name="object" index="10"/&gt;</pre>
* is shortcut to<pre>
* &lt;method name="getObject"&gt;
* &lt;int&gt;10&lt;/int&gt;
* &lt;/method&gt;</pre>
* 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:<pre>
* &lt;property&gt;&lt;int&gt;0&lt;/int&gt;&lt;/property&gt;</pre>
* is shortcut to<pre>
* &lt;method name="set"&gt;
* &lt;int&gt;0&lt;/int&gt;
* &lt;/method&gt;</pre>
* which is equivalent to {@code set(0)} in Java code.
* <p>The following atributes are supported:
* <dl>
* <dt>name
* <dd>the property name
* <dt>index
* <dd>the property index
* <dt>id
* <dd>the identifier of the variable that is intended to store the result
* </dl>
*
* @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:
* <dl>
* <dt>name
* <dd>the property name
* <dt>index
* <dd>the property index
* <dt>id
* <dd>the identifier of the variable that is intended to store the result
* </dl>
*
* @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");
}
}

View File

@ -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 &lt;short&gt; 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:<pre>
* &lt;short&gt;200&lt;/short&gt;</pre>
* is shortcut to<pre>
* &lt;method name="decode" class="java.lang.Short"&gt;
* &lt;string&gt;200&lt;/string&gt;
* &lt;/method&gt;</pre>
* which is equivalent to {@code Short.decode("200")} in Java code.
* <p>The following atribute is supported:
* <dl>
* <dt>id
* <dd>the identifier of the variable that is intended to store the result
* </dl>
*
* @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);
}
}

View File

@ -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 &lt;string&gt; element.
* This element specifies {@link String} values.
* The result value is created from text of the body of this element.
* For example:<pre>
* &lt;string&gt;description&lt;/string&gt;</pre>
* 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<pre>
* &lt;string&gt&lt;true&gt&lt;/string&gt;</pre>
* is not equal to the value of the element<pre>
* &lt;string&gt;
* &lt;true&gt;
* &lt;/string&gt;</pre>
* <p>The following atribute is supported:
* <dl>
* <dt>id
* <dd>the identifier of the variable that is intended to store the result
* </dl>
*
* @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;
}
}

View File

@ -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 &lt;true&gt; element.
* This element specifies {@code true} value.
* It should not contain body or inner elements.
* For example:<pre>
* &lt;true/&gt;</pre>
* is equivalent to {@code true} in Java code.
* <p>The following atribute is supported:
* <dl>
* <dt>id
* <dd>the identifier of the variable that is intended to store the result
* </dl>
*
* @since 1.7
*
* @author Sergey A. Malenkov
*/
final class TrueElementHandler extends NullElementHandler {
/**
* Returns {@code Boolean.TRUE}
* as a value of &lt;true&gt; element.
*
* @return {@code Boolean.TRUE} by default
*/
@Override
public Object getValue() {
return Boolean.TRUE;
}
}

View File

@ -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();
}

View File

@ -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;
}
}

View File

@ -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 &lt;var&gt; element.
* This element retrieves the value of specified variable.
* For example:<pre>
* &lt;var id="id1" idref="id2"/&gt;</pre>
* is equivalent to {@code id1 = id2} in Java code.
* <p>The following atributes are supported:
* <dl>
* <dt>idref
* <dd>the identifier to refer to the variable
* <dt>id
* <dd>the identifier of the variable that is intended to store the result
* </dl>
*
* @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:
* <dl>
* <dt>idref
* <dd>the identifier to refer to the variable
* <dt>id
* <dd>the identifier of the variable that is intended to store the result
* </dl>
*
* @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;
}
}

View File

@ -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 &lt;void&gt; element.
* This element looks like &lt;object&gt; element,
* but its value is not used as an argument for element
* that contains this one.
* <p>The following atributes are supported:
* <dl>
* <dt>class
* <dd>the type is used for static methods and fields
* <dt>method
* <dd>the method name
* <dt>property
* <dd>the property name
* <dt>index
* <dd>the property index
* <dt>field
* <dd>the field name
* <dt>idref
* <dd>the identifier to refer to the variable
* <dt>id
* <dd>the identifier of the variable that is intended to store the result
* </dl>
*
* @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
}
}

View File

@ -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<T> {
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<T, Class<?>[]> map = new HashMap<T, Class<?>[]>();
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;
}
}

View File

@ -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 <code>static</code> 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 <code>Class</code> object associated
* Returns the {@code Class} object associated
* with the class or interface with the given string name,
* using the default class loader.
* <p>
* The <code>name</code> 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 <code>Class</code> object associated with
* Returns the {@code Class} object associated with
* the class or interface with the given string name,
* using the given class loader.
* <p>
* The <code>name</code> can denote an array class
* The {@code name} can denote an array class
* (see {@link Class#getName} for details).
* <p>
* If the parameter <code>loader</code> 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 <code>Class</code> object associated
* Returns the {@code Class} object associated
* with the class or interface with the given string name,
* using the default class loader.
* <p>
* The <code>name</code> can denote an array class
* The {@code name} can denote an array class
* (see {@link Class#getName} for details).
* <p>
* This method can be used to obtain
* any of the <code>Class</code> objects
* representing <code>void</code> or primitive Java types:
* <code>char</code>, <code>byte</code>, <code>short</code>,
* <code>int</code>, <code>long</code>, <code>float</code>,
* <code>double</code> and <code>boolean</code>.
* 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 <code>Class</code> object associated with
* Returns the {@code Class} object associated with
* the class or interface with the given string name,
* using the given class loader.
* <p>
* The <code>name</code> can denote an array class
* The {@code name} can denote an array class
* (see {@link Class#getName} for details).
* <p>
* If the parameter <code>loader</code> is null,
* If the parameter {@code loader} is null,
* the class is loaded through the default class loader.
* <p>
* This method can be used to obtain
* any of the <code>Class</code> objects
* representing <code>void</code> or primitive Java types:
* <code>char</code>, <code>byte</code>, <code>short</code>,
* <code>int</code>, <code>long</code>, <code>float</code>,
* <code>double</code> and <code>boolean</code>.
* 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;
}

View File

@ -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<Constructor<?>> {
private static final WeakCache<Signature, Constructor<?>> CACHE = new WeakCache<Signature, Constructor<?>>();
/**
* 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());
}
}

View File

@ -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() {
}
}

View File

@ -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<Method> {
private static final WeakCache<Signature, Method> CACHE = new WeakCache<Signature, Method>();
/**
* 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);
}
}

View File

@ -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 <code>null</code> 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<String, Class> map = new HashMap<String, Class>( 9 );
private static final Map<String, Class<?>> map = new HashMap<String, Class<?>>(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);
}
/**

View File

@ -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<String, Class<?>> map = new HashMap<String, Class<?>>(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() {
}
}

View File

@ -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;
}
}

View File

@ -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);
}

View File

@ -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++;

View File

@ -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 <code>XMLDecoder</code> 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 <code>exceptionListener</code>.
* 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 &lt;java&gt; 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 <a
* href="http://java.sun.com/products/jfc/tsc/articles/persistence3/">here</a>.
*
* @param owner the owner of the default handler
* that can be used as a value of &lt;java&gt; 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;
}
}

View File

@ -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 {

View File

@ -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
= "<test>\n"
+ " <void property=\"message\">\n"
+ " <string>Hello, world!</string>\n"
+ " </void>\n"
+ "</test>";
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());
}
}

View File

@ -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
= "<java>\n"
+ " <object class=\"TestTurkishLocale$DataBean\">\n"
+ " <object class=\"Test6341798$DataBean\">\n"
+ " <void property=\"illegal\">\n"
+ " <boolean>true</boolean>\n"
+ " </void>\n"

View File

@ -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);
}
}
}

View File

@ -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 <array> element
* @author Sergey Malenkov
*/
import java.beans.XMLDecoder;
import java.lang.reflect.Array;
public final class TestArray extends AbstractTest {
public static final String XML
= "<java>\n"
+ " <array class=\"java.lang.Number\">\n"
+ " <byte>-111</byte>\n"
+ " <long>1111</long>\n"
+ " </array>\n"
+ " <array length=\"3\">\n"
+ " <void index=\"1\">\n"
+ " <string>Hello, world!</string>\n"
+ " </void>\n"
+ " </array>\n"
+ "</java>";
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> T[] getArray(Class<T> 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;
}
}

View File

@ -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 <boolean> element
* @author Sergey Malenkov
*/
import java.beans.XMLDecoder;
public final class TestBoolean extends AbstractTest {
public static final String XML
= "<java>\n"
+ " <boolean>true</boolean>\n"
+ " <boolean>false</boolean>\n"
+ "</java>";
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");
}
}
}

View File

@ -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 <byte> element
* @author Sergey Malenkov
*/
import java.beans.XMLDecoder;
public final class TestByte extends AbstractTest {
public static final String XML
= "<java>\n"
+ " <byte>0</byte>\n"
+ " <byte>127</byte>\n"
+ " <byte>-128</byte>\n"
+ "</java>";
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");
}
}
}

View File

@ -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 <char> element
* @author Sergey Malenkov
*/
import java.beans.XMLDecoder;
public final class TestChar extends AbstractTest {
public static final String XML
= "<java>\n"
+ " <char>X</char>\n"
+ " <char code=\"#20\"/>\n"
+ "</java>";
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");
}
}
}

View File

@ -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 <class> 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
= "<java>\n"
+ " <class>" + PREFIX + INTERFACE + "</class>\n"
+ " <class>" + PREFIX + PUBLIC_CLASS + "</class>\n"
+ " <class>" + PREFIX + PRIVATE_CLASS + "</class>\n"
+ "</java>";
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");
}
}
}

View File

@ -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 <double> element
* @author Sergey Malenkov
*/
import java.beans.XMLDecoder;
public final class TestDouble extends AbstractTest {
public static final String XML
= "<java>\n"
+ " <double>0</double>\n"
+ " <double>1000</double>\n"
+ " <double>-1.1e15</double>\n"
+ " <double>10.11e-123</double>\n"
+ "</java>";
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");
}
}
}

View File

@ -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 <false> element
* @author Sergey Malenkov
*/
import java.beans.XMLDecoder;
public final class TestFalse extends AbstractTest {
public static final String XML
= "<java>\n"
+ " <false/>\n"
+ "</java>";
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");
}
}
}

View File

@ -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 <field> element
* @author Sergey Malenkov
*/
import java.beans.XMLDecoder;
public final class TestField extends AbstractTest {
public static final String XML
= "<java>\n"
+ " <field name=\"FIELD\" class=\"TestField\"/>\n"
+ " <field name=\"FIELD\" class=\"TestField\">\n"
+ " <string>static postfix</string>\n"
+ " </field>\n"
+ " <field name=\"FIELD\" class=\"TestField\"/>\n"
+ " <property name=\"owner\">\n"
+ " <field id=\"prefix\" name=\"field\"/>\n"
+ " <field name=\"field\">\n"
+ " <string>postfix</string>\n"
+ " </field>\n"
+ " <field id=\"postfix\" name=\"field\"/>\n"
+ " </property>\n"
+ " <var idref=\"prefix\"/>\n"
+ " <var idref=\"postfix\"/>\n"
+ "</java>";
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");
}
}
}

View File

@ -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 <float> element
* @author Sergey Malenkov
*/
import java.beans.XMLDecoder;
public final class TestFloat extends AbstractTest {
public static final String XML
= "<java>\n"
+ " <float>0</float>\n"
+ " <float>100</float>\n"
+ " <float>-1e15</float>\n"
+ " <float>100e-20</float>\n"
+ "</java>";
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");
}
}
}

View File

@ -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 <int> element
* @author Sergey Malenkov
*/
import java.beans.XMLDecoder;
public final class TestInt extends AbstractTest {
public static final String XML
= "<java>\n"
+ " <int>0</int>\n"
+ " <int>127</int>\n"
+ " <int>-128</int>\n"
+ " <int>32767</int>\n"
+ " <int>-32768</int>\n"
+ " <int>2147483647</int>\n"
+ " <int>-2147483648</int>\n"
+ "</java>";
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");
}
}
}

View File

@ -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 <java> element
* @author Sergey Malenkov
*/
import java.beans.XMLDecoder;
public final class TestJava extends AbstractTest {
public static final String XML
= "<java>\n"
+ " <void id=\"owner\" method=\"getOwner\">\n"
+ " <void method=\"init\">\n"
+ " <string>Hello, world!</string>\n"
+ " </void>\n"
+ " </void>\n"
+ " <object idref=\"owner\"/>\n"
+ "</java>";
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");
}
}
}

View File

@ -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 <long> element
* @author Sergey Malenkov
*/
import java.beans.XMLDecoder;
public final class TestLong extends AbstractTest {
public static final String XML
= "<java>\n"
+ " <long>0</long>\n"
+ " <long>127</long>\n"
+ " <long>-128</long>\n"
+ " <long>32767</long>\n"
+ " <long>-32768</long>\n"
+ " <long>2147483647</long>\n"
+ " <long>-2147483648</long>\n"
+ " <long>9223372036854775807</long>\n"
+ " <long>-9223372036854775808</long>\n"
+ "</java>";
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");
}
}
}

View File

@ -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 <method> element
* @author Sergey Malenkov
*/
import java.beans.XMLDecoder;
public final class TestMethod extends AbstractTest {
public static final String XML
= "<java>\n"
+ " <new class=\"TestMethod$A\">\n"
+ " <method name=\"m\">\n"
+ " <new class=\"TestMethod$Y\"/>\n"
+ " <new class=\"TestMethod$Y\"/>\n"
+ " </method>\n"
+ " </new>\n"
+ " <new class=\"TestMethod$B\">\n"
+ " <method name=\"m\">\n"
+ " <new class=\"TestMethod$Y\"/>\n"
+ " <new class=\"TestMethod$Y\"/>\n"
+ " </method>\n"
+ " </new>\n"
+ " <new class=\"TestMethod$C\">\n"
+ " <method name=\"m\">\n"
+ " <new class=\"TestMethod$Z\"/>\n"
+ " <new class=\"TestMethod$Z\"/>\n"
+ " </method>\n"
+ " </new>\n"
+ " <new class=\"TestMethod$D\">\n"
+ " <method name=\"m\">\n"
+ " <new class=\"TestMethod$Z\"/>\n"
+ " <new class=\"TestMethod$Z\"/>\n"
+ " </method>\n"
+ " </new>\n"
+ " <new class=\"TestMethod$E\">\n"
+ " <method name=\"m\">\n"
+ " <new class=\"TestMethod$Z\"/>\n"
+ " <new class=\"TestMethod$Z\"/>\n"
+ " </method>\n"
+ " </new>\n"
+ "</java>";
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 {
}
}

View File

@ -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 <new> 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
= "<java>\n"
+ " <new class=\"TestNew\"/>\n"
+ " <new class=\"TestNew\">\n"
+ " <null/>\n"
+ " </new>\n"
+ " <new class=\"TestNew\">\n"
+ " <string>single</string>\n"
+ " </new>\n"
+ " <new class=\"TestNew\">\n"
+ " <string>first</string>\n"
+ " <string>second</string>\n"
+ " <string>third</string>\n"
+ " </new>\n"
+ "</java>";
public static void main(String[] args) {
new TestNew().test(true);
}
private List<String> list;
public TestNew(String...messages) {
if (messages != null) {
this.list = new ArrayList<String>();
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");
}
}
}

View File

@ -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 <null> element
* @author Sergey Malenkov
*/
import java.beans.XMLDecoder;
public final class TestNull extends AbstractTest {
public static final String XML
= "<java>\n"
+ " <null/>\n"
+ "</java>";
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");
}
}
}

View File

@ -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 <object> 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
= "<java>\n"
+ " <object class=\"javax.swing.JPanel\">\n"
+ " <void method=\"add\">\n"
+ " <object id=\"button\" class=\"javax.swing.JButton\">\n"
+ " <string>button</string>\n"
+ " <void property=\"verticalAlignment\">\n"
+ " <object field=\"CENTER\" class=\"javax.swing.SwingConstants\"/>\n"
+ " </void>\n"
+ " </object>\n"
+ " </void>\n"
+ " <void method=\"add\">\n"
+ " <object class=\"javax.swing.JLabel\">\n"
+ " <string>label</string>\n"
+ " <void property=\"labelFor\">\n"
+ " <object idref=\"button\"/>\n"
+ " </void>\n"
+ " </object>\n"
+ " </void>\n"
+ " </object>\n"
+ "</java>";
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");
}
}
}

View File

@ -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 <property> element
* @author Sergey Malenkov
*/
import java.beans.XMLDecoder;
public final class TestProperty extends AbstractTest {
public static final String XML
= "<java>\n"
+ " <property name=\"owner\">\n"
+ " <property name=\"message\">\n"
+ " <string>message</string>\n"
+ " </property>\n"
+ " <property id=\"message\" name=\"message\"/>\n"
+ " <property name=\"indexed\" index=\"1\">\n"
+ " <string>indexed</string>\n"
+ " </property>\n"
+ " <property id=\"indexed\" name=\"indexed\" index=\"1\"/>\n"
+ " </property>\n"
+ " <var idref=\"message\"/>\n"
+ " <var idref=\"indexed\"/>\n"
+ "</java>";
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");
}
}
}

View File

@ -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 <short> element
* @author Sergey Malenkov
*/
import java.beans.XMLDecoder;
public final class TestShort extends AbstractTest {
public static final String XML
= "<java>\n"
+ " <short>0</short>\n"
+ " <short>127</short>\n"
+ " <short>-128</short>\n"
+ " <short>32767</short>\n"
+ " <short>-32768</short>\n"
+ "</java>";
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");
}
}
}

View File

@ -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 <string> 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
= "<java>\n"
+ " <string>" + PREFIX + "</string>\n"
+ " <string>" + POSTFIX + "</string>\n"
+ " <string>" + PREFIX + POSTFIX + "</string>\n"
+ " <string>" + PREFIX + "<char code=\"0\"/>" + POSTFIX + "</string>\n"
+ "</java>";
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");
}
}
}

View File

@ -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 <true> element
* @author Sergey Malenkov
*/
import java.beans.XMLDecoder;
public final class TestTrue extends AbstractTest {
public static final String XML
= "<java>\n"
+ " <true/>\n"
+ "</java>";
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");
}
}
}

View File

@ -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 <var> element
* @author Sergey Malenkov
*/
import java.beans.XMLDecoder;
public final class TestVar extends AbstractTest {
public static final String XML
= "<java id=\"decoder\">\n"
+ " <var idref=\"decoder\"/>\n"
+ " <var id=\"another\" idref=\"decoder\"/>\n"
+ " <var idref=\"another\"/>\n"
+ " <var id=\"decoder\" idref=\"another\"/>\n"
+ " <var idref=\"decoder\"/>\n"
+ "</java>";
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");
}
}
}
}