feat(jdk8): move files to new folder to avoid resources compiled.

This commit is contained in:
2025-09-07 15:25:52 +08:00
parent 3f0047bf6f
commit 8c35cfb1c0
17415 changed files with 217 additions and 213 deletions

View File

@@ -0,0 +1,378 @@
/*
* Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.beans;
import java.lang.reflect.Array;
import java.lang.reflect.GenericArrayType;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.lang.reflect.WildcardType;
import java.util.HashMap;
import java.util.Map;
import sun.reflect.generics.reflectiveObjects.GenericArrayTypeImpl;
import sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl;
/**
* This is utility class to resolve types.
*
* @since 1.7
*
* @author Eamonn McManus
* @author Sergey Malenkov
*/
public final class TypeResolver {
private static final WeakCache<Type, Map<Type, Type>> CACHE = new WeakCache<>();
/**
* Replaces the given {@code type} in an inherited method
* with the actual type it has in the given {@code inClass}.
*
* <p>Although type parameters are not inherited by subclasses in the Java
* language, they <em>are</em> effectively inherited when using reflection.
* For example, if you declare an interface like this...</p>
*
* <pre>
* public interface StringToIntMap extends Map&lt;String,Integer> {}
* </pre>
*
* <p>...then StringToIntMap.class.getMethods() will show that it has methods
* like put(K,V) even though StringToIntMap has no type parameters. The K
* and V variables are the ones declared by Map, so
* {@link TypeVariable#getGenericDeclaration()} will return Map.class.</p>
*
* <p>The purpose of this method is to take a Type from a possibly-inherited
* method and replace it with the correct Type for the inheriting class.
* So given parameters of K and StringToIntMap.class in the above example,
* this method will return String.</p>
*
* @param inClass the base class used to resolve
* @param type the type to resolve
* @return a resolved type
*
* @see #getActualType(Class)
* @see #resolve(Type,Type)
*/
public static Type resolveInClass(Class<?> inClass, Type type) {
return resolve(getActualType(inClass), type);
}
/**
* Replaces all {@code types} in the given array
* with the actual types they have in the given {@code inClass}.
*
* @param inClass the base class used to resolve
* @param types the array of types to resolve
* @return an array of resolved types
*
* @see #getActualType(Class)
* @see #resolve(Type,Type[])
*/
public static Type[] resolveInClass(Class<?> inClass, Type[] types) {
return resolve(getActualType(inClass), types);
}
/**
* Replaces type variables of the given {@code formal} type
* with the types they stand for in the given {@code actual} type.
*
* <p>A ParameterizedType is a class with type parameters, and the values
* of those parameters. For example, Map&lt;K,V> is a generic class, and
* a corresponding ParameterizedType might look like
* Map&lt;K=String,V=Integer>. Given such a ParameterizedType, this method
* will replace K with String, or List&lt;K> with List&ltString;, or
* List&lt;? super K> with List&lt;? super String>.</p>
*
* <p>The {@code actual} argument to this method can also be a Class.
* In this case, either it is equivalent to a ParameterizedType with
* no parameters (for example, Integer.class), or it is equivalent to
* a "raw" ParameterizedType (for example, Map.class). In the latter
* case, every type parameter declared or inherited by the class is replaced
* by its "erasure". For a type parameter declared as &lt;T>, the erasure
* is Object. For a type parameter declared as &lt;T extends Number>,
* the erasure is Number.</p>
*
* <p>Although type parameters are not inherited by subclasses in the Java
* language, they <em>are</em> effectively inherited when using reflection.
* For example, if you declare an interface like this...</p>
*
* <pre>
* public interface StringToIntMap extends Map&lt;String,Integer> {}
* </pre>
*
* <p>...then StringToIntMap.class.getMethods() will show that it has methods
* like put(K,V) even though StringToIntMap has no type parameters. The K
* and V variables are the ones declared by Map, so
* {@link TypeVariable#getGenericDeclaration()} will return {@link Map Map.class}.</p>
*
* <p>For this reason, this method replaces inherited type parameters too.
* Therefore if this method is called with {@code actual} being
* StringToIntMap.class and {@code formal} being the K from Map,
* it will return {@link String String.class}.</p>
*
* <p>In the case where {@code actual} is a "raw" ParameterizedType, the
* inherited type parameters will also be replaced by their erasures.
* The erasure of a Class is the Class itself, so a "raw" subinterface of
* StringToIntMap will still show the K from Map as String.class. But
* in a case like this...
*
* <pre>
* public interface StringToIntListMap extends Map&lt;String,List&lt;Integer>> {}
* public interface RawStringToIntListMap extends StringToIntListMap {}
* </pre>
*
* <p>...the V inherited from Map will show up as List&lt;Integer> in
* StringToIntListMap, but as plain List in RawStringToIntListMap.</p>
*
* @param actual the type that supplies bindings for type variables
* @param formal the type where occurrences of the variables
* in {@code actual} will be replaced by the corresponding bound values
* @return a resolved type
*/
public static Type resolve(Type actual, Type formal) {
if (formal instanceof Class) {
return formal;
}
if (formal instanceof GenericArrayType) {
Type comp = ((GenericArrayType) formal).getGenericComponentType();
comp = resolve(actual, comp);
return (comp instanceof Class)
? Array.newInstance((Class<?>) comp, 0).getClass()
: GenericArrayTypeImpl.make(comp);
}
if (formal instanceof ParameterizedType) {
ParameterizedType fpt = (ParameterizedType) formal;
Type[] actuals = resolve(actual, fpt.getActualTypeArguments());
return ParameterizedTypeImpl.make(
(Class<?>) fpt.getRawType(), actuals, fpt.getOwnerType());
}
if (formal instanceof WildcardType) {
WildcardType fwt = (WildcardType) formal;
Type[] upper = resolve(actual, fwt.getUpperBounds());
Type[] lower = resolve(actual, fwt.getLowerBounds());
return new WildcardTypeImpl(upper, lower);
}
if (formal instanceof TypeVariable) {
Map<Type, Type> map;
synchronized (CACHE) {
map = CACHE.get(actual);
if (map == null) {
map = new HashMap<>();
prepare(map, actual);
CACHE.put(actual, map);
}
}
Type result = map.get(formal);
if (result == null || result.equals(formal)) {
return formal;
}
result = fixGenericArray(result);
// A variable can be bound to another variable that is itself bound
// to something. For example, given:
// class Super<T> {...}
// class Mid<X> extends Super<T> {...}
// class Sub extends Mid<String>
// the variable T is bound to X, which is in turn bound to String.
// So if we have to resolve T, we need the tail recursion here.
return resolve(actual, result);
}
throw new IllegalArgumentException("Bad Type kind: " + formal.getClass());
}
/**
* Replaces type variables of all formal types in the given array
* with the types they stand for in the given {@code actual} type.
*
* @param actual the type that supplies bindings for type variables
* @param formals the array of types to resolve
* @return an array of resolved types
*/
public static Type[] resolve(Type actual, Type[] formals) {
int length = formals.length;
Type[] actuals = new Type[length];
for (int i = 0; i < length; i++) {
actuals[i] = resolve(actual, formals[i]);
}
return actuals;
}
/**
* Converts the given {@code type} to the corresponding class.
* This method implements the concept of type erasure,
* that is described in section 4.6 of
* <cite>The Java&trade; Language Specification</cite>.
*
* @param type the array of types to convert
* @return a corresponding class
*/
public static Class<?> erase(Type type) {
if (type instanceof Class) {
return (Class<?>) type;
}
if (type instanceof ParameterizedType) {
ParameterizedType pt = (ParameterizedType) type;
return (Class<?>) pt.getRawType();
}
if (type instanceof TypeVariable) {
TypeVariable tv = (TypeVariable)type;
Type[] bounds = tv.getBounds();
return (0 < bounds.length)
? erase(bounds[0])
: Object.class;
}
if (type instanceof WildcardType) {
WildcardType wt = (WildcardType)type;
Type[] bounds = wt.getUpperBounds();
return (0 < bounds.length)
? erase(bounds[0])
: Object.class;
}
if (type instanceof GenericArrayType) {
GenericArrayType gat = (GenericArrayType)type;
return Array.newInstance(erase(gat.getGenericComponentType()), 0).getClass();
}
throw new IllegalArgumentException("Unknown Type kind: " + type.getClass());
}
/**
* Converts all {@code types} in the given array
* to the corresponding classes.
*
* @param types the array of types to convert
* @return an array of corresponding classes
*
* @see #erase(Type)
*/
public static Class[] erase(Type[] types) {
int length = types.length;
Class[] classes = new Class[length];
for (int i = 0; i < length; i++) {
classes[i] = TypeResolver.erase(types[i]);
}
return classes;
}
/**
* Fills the map from type parameters
* to types as seen by the given {@code type}.
* The method is recursive because the {@code type}
* inherits mappings from its parent classes and interfaces.
* The {@code type} can be either a {@link Class Class}
* or a {@link ParameterizedType ParameterizedType}.
* If it is a {@link Class Class}, it is either equivalent
* to a {@link ParameterizedType ParameterizedType} with no parameters,
* or it represents the erasure of a {@link ParameterizedType ParameterizedType}.
*
* @param map the mappings of all type variables
* @param type the next type in the hierarchy
*/
private static void prepare(Map<Type, Type> map, Type type) {
Class<?> raw = (Class<?>)((type instanceof Class<?>)
? type
: ((ParameterizedType)type).getRawType());
TypeVariable<?>[] formals = raw.getTypeParameters();
Type[] actuals = (type instanceof Class<?>)
? formals
: ((ParameterizedType)type).getActualTypeArguments();
assert formals.length == actuals.length;
for (int i = 0; i < formals.length; i++) {
map.put(formals[i], actuals[i]);
}
Type gSuperclass = raw.getGenericSuperclass();
if (gSuperclass != null) {
prepare(map, gSuperclass);
}
for (Type gInterface : raw.getGenericInterfaces()) {
prepare(map, gInterface);
}
// If type is the raw version of a parameterized class, we type-erase
// all of its type variables, including inherited ones.
if (type instanceof Class<?> && formals.length > 0) {
for (Map.Entry<Type, Type> entry : map.entrySet()) {
entry.setValue(erase(entry.getValue()));
}
}
}
/**
* Replaces a {@link GenericArrayType GenericArrayType}
* with plain array class where it is possible.
* Bug <a href="http://bugs.sun.com/view_bug.do?bug_id=5041784">5041784</a>
* is that arrays of non-generic type sometimes show up
* as {@link GenericArrayType GenericArrayType} when using reflection.
* For example, a {@code String[]} might show up
* as a {@link GenericArrayType GenericArrayType}
* where {@link GenericArrayType#getGenericComponentType getGenericComponentType}
* is {@code String.class}. This violates the specification,
* which says that {@link GenericArrayType GenericArrayType}
* is used when the component type is a type variable or parameterized type.
* We fit the specification here.
*
* @param type the type to fix
* @return a corresponding type for the generic array type,
* or the same type as {@code type}
*/
private static Type fixGenericArray(Type type) {
if (type instanceof GenericArrayType) {
Type comp = ((GenericArrayType)type).getGenericComponentType();
comp = fixGenericArray(comp);
if (comp instanceof Class) {
return Array.newInstance((Class<?>)comp, 0).getClass();
}
}
return type;
}
/**
* Replaces a {@link Class Class} with type parameters
* with a {@link ParameterizedType ParameterizedType}
* where every parameter is bound to itself.
* When calling {@link #resolveInClass} in the context of {@code inClass},
* we can't just pass {@code inClass} as the {@code actual} parameter,
* because if {@code inClass} has type parameters
* that would be interpreted as accessing the raw type,
* so we would get unwanted erasure.
* This is why we bind each parameter to itself.
* If {@code inClass} does have type parameters and has methods
* where those parameters appear in the return type or argument types,
* we will correctly leave those types alone.
*
* @param inClass the base class used to resolve
* @return a parameterized type for the class,
* or the same class as {@code inClass}
*/
private static Type getActualType(Class<?> inClass) {
Type[] params = inClass.getTypeParameters();
return (params.length == 0)
? inClass
: ParameterizedTypeImpl.make(
inClass, params, inClass.getEnclosingClass());
}
}

View File

@@ -0,0 +1,91 @@
/*
* Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.beans;
import java.lang.ref.Reference;
import java.lang.ref.WeakReference;
import java.util.Map;
import java.util.WeakHashMap;
/**
* A hashtable-based cache with weak keys and weak values.
* An entry in the map will be automatically removed
* when its key is no longer in the ordinary use.
* A value will be automatically removed as well
* when it is no longer in the ordinary use.
*
* @since 1.7
*
* @author Sergey A. Malenkov
*/
public final class WeakCache<K, V> {
private final Map<K, Reference<V>> map = new WeakHashMap<K, Reference<V>>();
/**
* Returns a value to which the specified {@code key} is mapped,
* or {@code null} if this map contains no mapping for the {@code key}.
*
* @param key the key whose associated value is returned
* @return a value to which the specified {@code key} is mapped
*/
public V get(K key) {
Reference<V> reference = this.map.get(key);
if (reference == null) {
return null;
}
V value = reference.get();
if (value == null) {
this.map.remove(key);
}
return value;
}
/**
* Associates the specified {@code value} with the specified {@code key}.
* Removes the mapping for the specified {@code key} from this cache
* if it is present and the specified {@code value} is {@code null}.
* If the cache previously contained a mapping for the {@code key},
* the old value is replaced by the specified {@code value}.
*
* @param key the key with which the specified value is associated
* @param value the value to be associated with the specified key
*/
public void put(K key, V value) {
if (value != null) {
this.map.put(key, new WeakReference<V>(value));
}
else {
this.map.remove(key);
}
}
/**
* Removes all of the mappings from this cache.
*/
public void clear() {
this.map.clear();
}
}

View File

@@ -0,0 +1,161 @@
/*
* Copyright (c) 2003, 2006, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.beans;
import java.lang.reflect.Type;
import java.lang.reflect.WildcardType;
import java.util.Arrays;
/**
* This class implements {@link WildcardType WildcardType} compatibly with the JDK's
* {@link sun.reflect.generics.reflectiveObjects.WildcardTypeImpl WildcardTypeImpl}.
* Unfortunately we can't use the JDK's
* {@link sun.reflect.generics.reflectiveObjects.WildcardTypeImpl WildcardTypeImpl} here as we do for
* {@link sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl ParameterizedTypeImpl} and
* {@link sun.reflect.generics.reflectiveObjects.GenericArrayTypeImpl GenericArrayTypeImpl},
* because {@link sun.reflect.generics.reflectiveObjects.WildcardTypeImpl WildcardTypeImpl}'s
* constructor takes parameters representing intermediate structures obtained during class-file parsing.
* We could reconstruct versions of those structures but it would be more trouble than it's worth.
*
* @since 1.7
*
* @author Eamonn McManus
* @author Sergey Malenkov
*/
final class WildcardTypeImpl implements WildcardType {
private final Type[] upperBounds;
private final Type[] lowerBounds;
/**
* Creates a wildcard type with the requested bounds.
* Note that the array arguments are not cloned
* because instances of this class are never constructed
* from outside the containing package.
*
* @param upperBounds the array of types representing
* the upper bound(s) of this type variable
* @param lowerBounds the array of types representing
* the lower bound(s) of this type variable
*/
WildcardTypeImpl(Type[] upperBounds, Type[] lowerBounds) {
this.upperBounds = upperBounds;
this.lowerBounds = lowerBounds;
}
/**
* Returns an array of {@link Type Type} objects
* representing the upper bound(s) of this type variable.
* Note that if no upper bound is explicitly declared,
* the upper bound is {@link Object Object}.
*
* @return an array of types representing
* the upper bound(s) of this type variable
*/
public Type[] getUpperBounds() {
return this.upperBounds.clone();
}
/**
* Returns an array of {@link Type Type} objects
* representing the lower bound(s) of this type variable.
* Note that if no lower bound is explicitly declared,
* the lower bound is the type of {@code null}.
* In this case, a zero length array is returned.
*
* @return an array of types representing
* the lower bound(s) of this type variable
*/
public Type[] getLowerBounds() {
return this.lowerBounds.clone();
}
/**
* Indicates whether some other object is "equal to" this one.
* It is implemented compatibly with the JDK's
* {@link sun.reflect.generics.reflectiveObjects.WildcardTypeImpl WildcardTypeImpl}.
*
* @param object the reference object with which to compare
* @return {@code true} if this object is the same as the object argument;
* {@code false} otherwise
* @see sun.reflect.generics.reflectiveObjects.WildcardTypeImpl#equals
*/
@Override
public boolean equals(Object object) {
if (object instanceof WildcardType) {
WildcardType type = (WildcardType) object;
return Arrays.equals(this.upperBounds, type.getUpperBounds())
&& Arrays.equals(this.lowerBounds, type.getLowerBounds());
}
return false;
}
/**
* Returns a hash code value for the object.
* It is implemented compatibly with the JDK's
* {@link sun.reflect.generics.reflectiveObjects.WildcardTypeImpl WildcardTypeImpl}.
*
* @return a hash code value for this object
* @see sun.reflect.generics.reflectiveObjects.WildcardTypeImpl#hashCode
*/
@Override
public int hashCode() {
return Arrays.hashCode(this.upperBounds)
^ Arrays.hashCode(this.lowerBounds);
}
/**
* Returns a string representation of the object.
* It is implemented compatibly with the JDK's
* {@link sun.reflect.generics.reflectiveObjects.WildcardTypeImpl WildcardTypeImpl}.
*
* @return a string representation of the object
* @see sun.reflect.generics.reflectiveObjects.WildcardTypeImpl#toString
*/
@Override
public String toString() {
StringBuilder sb;
Type[] bounds;
if (this.lowerBounds.length == 0) {
if (this.upperBounds.length == 0 || Object.class == this.upperBounds[0]) {
return "?";
}
bounds = this.upperBounds;
sb = new StringBuilder("? extends ");
}
else {
bounds = this.lowerBounds;
sb = new StringBuilder("? super ");
}
for (int i = 0; i < bounds.length; i++) {
if (i > 0) {
sb.append(" & ");
}
sb.append((bounds[i] instanceof Class)
? ((Class) bounds[i]).getName()
: bounds[i].toString());
}
return sb.toString();
}
}

View File

@@ -0,0 +1,105 @@
/*
* Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.beans.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 attributes 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,147 @@
/*
* Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.beans.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 attributes 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 attributes 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();
}
}
/**
* 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 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 (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.beans.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 attribute 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 (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.beans.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 attribute 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 (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.beans.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 attributes 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 attributes 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 (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.beans.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 attribute 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,411 @@
/*
* Copyright (c) 2008, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.beans.decoder;
import com.sun.beans.finder.ClassFinder;
import java.beans.ExceptionListener;
import java.io.IOException;
import java.io.StringReader;
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 java.security.AccessControlContext;
import java.security.AccessController;
import java.security.PrivilegedAction;
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;
import sun.misc.SharedSecrets;
/**
* 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 AccessControlContext acc = AccessController.getContext();
private final Map<String, Class<? extends ElementHandler>> handlers = new HashMap<>();
private final Map<String, Object> environment = new HashMap<>();
private final List<Object> objects = new ArrayList<>();
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);
}
/**
* Disables any external entities.
*/
@Override
public InputSource resolveEntity(String publicId, String systemId) {
return new InputSource(new StringReader(""));
}
/**
* 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(final InputSource input) {
if ((this.acc == null) && (null != System.getSecurityManager())) {
throw new SecurityException("AccessControlContext is not set");
}
AccessControlContext stack = AccessController.getContext();
SharedSecrets.getJavaSecurityAccess().doIntersectionPrivilege(new PrivilegedAction<Void>() {
public Void run() {
try {
SAXParserFactory.newInstance().newSAXParser().parse(input, DocumentHandler.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);
}
return null;
}
}, stack, this.acc);
}
/**
* 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 (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.beans.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 attribute 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 (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.beans.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 attribute 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 (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.beans.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 attribute 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 (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.beans.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 attributes 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 attributes 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 (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.beans.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 attribute 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 (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.beans.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 attribute 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 (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.beans.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 attributes 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 attributes 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 (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.beans.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 attribute 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,111 @@
/*
* Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.beans.decoder;
import com.sun.beans.finder.MethodFinder;
import java.lang.reflect.Method;
import sun.reflect.misc.MethodUtil;
/**
* 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 attributes 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 attributes 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 = MethodUtil.invoke(method, bean, args);
return method.getReturnType().equals(void.class)
? ValueObjectImpl.VOID
: ValueObjectImpl.create(value);
}
}

View File

@@ -0,0 +1,205 @@
/*
* Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.beans.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 attributes 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 attributes 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 (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.beans.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 attribute 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 (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.beans.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 attributes 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 attributes 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,289 @@
/*
* Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.beans.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;
import sun.reflect.misc.MethodUtil;
/**
* 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 attributes 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 attributes 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 MethodUtil.invoke(findGetter(type, name), bean, new Object[] {});
} else if (type.isArray() && (name == null)) {
return Array.get(bean, index);
} else {
return MethodUtil.invoke(findGetter(type, name, int.class), bean, new Object[] {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) {
MethodUtil.invoke(findSetter(type, name, param), bean, new Object[] {value});
} else if (type.isArray() && (name == null)) {
Array.set(bean, index, value);
} else {
MethodUtil.invoke(findSetter(type, name, int.class, param), bean, new Object[] {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 (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.beans.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 attribute 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 (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.beans.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 attribute 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 (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.beans.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 attribute 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 (c) 2008, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.beans.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 (c) 2008, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.beans.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 (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.beans.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 attributes 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 attributes 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 (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.beans.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 attributes 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,76 @@
/*
* Copyright (c) 2006, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.beans.editors;
/**
* Property editor for a java builtin "boolean" type.
*/
import java.beans.*;
public class BooleanEditor extends PropertyEditorSupport {
public String getJavaInitializationString() {
Object value = getValue();
return (value != null)
? value.toString()
: "null";
}
public String getAsText() {
Object value = getValue();
return (value instanceof Boolean)
? getValidName((Boolean) value)
: null;
}
public void setAsText(String text) throws java.lang.IllegalArgumentException {
if (text == null) {
setValue(null);
} else if (isValidName(true, text)) {
setValue(Boolean.TRUE);
} else if (isValidName(false, text)) {
setValue(Boolean.FALSE);
} else {
throw new java.lang.IllegalArgumentException(text);
}
}
public String[] getTags() {
return new String[] {getValidName(true), getValidName(false)};
}
// the following method should be localized (4890258)
private String getValidName(boolean value) {
return value ? "True" : "False";
}
private boolean isValidName(boolean value, String name) {
return getValidName(value).equalsIgnoreCase(name);
}
}

View File

@@ -0,0 +1,48 @@
/*
* Copyright (c) 1996, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.beans.editors;
/**
* Property editor for a java builtin "byte" type.
*
*/
import java.beans.*;
public class ByteEditor extends NumberEditor {
public String getJavaInitializationString() {
Object value = getValue();
return (value != null)
? "((byte)" + value + ")"
: "null";
}
public void setAsText(String text) throws IllegalArgumentException {
setValue((text == null) ? null : Byte.decode(text));
}
}

View File

@@ -0,0 +1,214 @@
/*
* Copyright (c) 1996, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.beans.editors;
import java.awt.*;
import java.beans.*;
public class ColorEditor extends Panel implements PropertyEditor {
private static final long serialVersionUID = 1781257185164716054L;
public ColorEditor() {
setLayout(null);
ourWidth = hPad;
// Create a sample color block bordered in black
Panel p = new Panel();
p.setLayout(null);
p.setBackground(Color.black);
sample = new Canvas();
p.add(sample);
sample.reshape(2, 2, sampleWidth, sampleHeight);
add(p);
p.reshape(ourWidth, 2, sampleWidth+4, sampleHeight+4);
ourWidth += sampleWidth + 4 + hPad;
text = new TextField("", 14);
add(text);
text.reshape(ourWidth,0,100,30);
ourWidth += 100 + hPad;
choser = new Choice();
int active = 0;
for (int i = 0; i < colorNames.length; i++) {
choser.addItem(colorNames[i]);
}
add(choser);
choser.reshape(ourWidth,0,100,30);
ourWidth += 100 + hPad;
resize(ourWidth,40);
}
public void setValue(Object o) {
Color c = (Color)o;
changeColor(c);
}
public Dimension preferredSize() {
return new Dimension(ourWidth, 40);
}
public boolean keyUp(Event e, int key) {
if (e.target == text) {
try {
setAsText(text.getText());
} catch (IllegalArgumentException ex) {
// Quietly ignore.
}
}
return (false);
}
public void setAsText(String s) throws java.lang.IllegalArgumentException {
if (s == null) {
changeColor(null);
return;
}
int c1 = s.indexOf(',');
int c2 = s.indexOf(',', c1+1);
if (c1 < 0 || c2 < 0) {
// Invalid string.
throw new IllegalArgumentException(s);
}
try {
int r = Integer.parseInt(s.substring(0,c1));
int g = Integer.parseInt(s.substring(c1+1, c2));
int b = Integer.parseInt(s.substring(c2+1));
Color c = new Color(r,g,b);
changeColor(c);
} catch (Exception ex) {
throw new IllegalArgumentException(s);
}
}
public boolean action(Event e, Object arg) {
if (e.target == choser) {
changeColor(colors[choser.getSelectedIndex()]);
}
return false;
}
public String getJavaInitializationString() {
return (this.color != null)
? "new java.awt.Color(" + this.color.getRGB() + ",true)"
: "null";
}
private void changeColor(Color c) {
if (c == null) {
this.color = null;
this.text.setText("");
return;
}
color = c;
text.setText("" + c.getRed() + "," + c.getGreen() + "," + c.getBlue());
int active = 0;
for (int i = 0; i < colorNames.length; i++) {
if (color.equals(colors[i])) {
active = i;
}
}
choser.select(active);
sample.setBackground(color);
sample.repaint();
support.firePropertyChange("", null, null);
}
public Object getValue() {
return color;
}
public boolean isPaintable() {
return true;
}
public void paintValue(java.awt.Graphics gfx, java.awt.Rectangle box) {
Color oldColor = gfx.getColor();
gfx.setColor(Color.black);
gfx.drawRect(box.x, box.y, box.width-3, box.height-3);
gfx.setColor(color);
gfx.fillRect(box.x+1, box.y+1, box.width-4, box.height-4);
gfx.setColor(oldColor);
}
public String getAsText() {
return (this.color != null)
? this.color.getRed() + "," + this.color.getGreen() + "," + this.color.getBlue()
: null;
}
public String[] getTags() {
return null;
}
public java.awt.Component getCustomEditor() {
return this;
}
public boolean supportsCustomEditor() {
return true;
}
public void addPropertyChangeListener(PropertyChangeListener l) {
support.addPropertyChangeListener(l);
}
public void removePropertyChangeListener(PropertyChangeListener l) {
support.removePropertyChangeListener(l);
}
private String colorNames[] = { " ", "white", "lightGray", "gray", "darkGray",
"black", "red", "pink", "orange",
"yellow", "green", "magenta", "cyan",
"blue"};
private Color colors[] = { null, Color.white, Color.lightGray, Color.gray, Color.darkGray,
Color.black, Color.red, Color.pink, Color.orange,
Color.yellow, Color.green, Color.magenta, Color.cyan,
Color.blue};
private Canvas sample;
private int sampleHeight = 20;
private int sampleWidth = 40;
private int hPad = 5;
private int ourWidth;
private Color color;
private TextField text;
private Choice choser;
private PropertyChangeSupport support = new PropertyChangeSupport(this);
}

View File

@@ -0,0 +1,41 @@
/*
* Copyright (c) 1996, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.beans.editors;
/**
* Property editor for a java builtin "double" type.
*
*/
import java.beans.*;
public class DoubleEditor extends NumberEditor {
public void setAsText(String text) throws IllegalArgumentException {
setValue((text == null) ? null : Double.valueOf(text));
}
}

View File

@@ -0,0 +1,143 @@
/*
* Copyright (c) 2006, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.beans.editors;
import java.awt.Component;
import java.awt.Graphics;
import java.awt.Rectangle;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.beans.PropertyEditor;
import java.util.ArrayList;
import java.util.List;
/**
* Property editor for java.lang.Enum subclasses.
*
* @see PropertyEditor
*
* @since 1.7
*
* @author Sergey A. Malenkov
*/
public final class EnumEditor implements PropertyEditor {
private final List<PropertyChangeListener> listeners = new ArrayList<PropertyChangeListener>();
private final Class type;
private final String[] tags;
private Object value;
public EnumEditor( Class type ) {
Object[] values = type.getEnumConstants();
if ( values == null ) {
throw new IllegalArgumentException( "Unsupported " + type );
}
this.type = type;
this.tags = new String[values.length];
for ( int i = 0; i < values.length; i++ ) {
this.tags[i] = ( ( Enum )values[i] ).name();
}
}
public Object getValue() {
return this.value;
}
public void setValue( Object value ) {
if ( ( value != null ) && !this.type.isInstance( value ) ) {
throw new IllegalArgumentException( "Unsupported value: " + value );
}
Object oldValue;
PropertyChangeListener[] listeners;
synchronized ( this.listeners ) {
oldValue = this.value;
this.value = value;
if ( ( value == null ) ? oldValue == null : value.equals( oldValue ) ) {
return; // do not fire event if value is not changed
}
int size = this.listeners.size();
if ( size == 0 ) {
return; // do not fire event if there are no any listener
}
listeners = this.listeners.toArray( new PropertyChangeListener[size] );
}
PropertyChangeEvent event = new PropertyChangeEvent( this, null, oldValue, value );
for ( PropertyChangeListener listener : listeners ) {
listener.propertyChange( event );
}
}
public String getAsText() {
return ( this.value != null )
? ( ( Enum )this.value ).name()
: null;
}
public void setAsText( String text ) {
setValue( ( text != null )
? Enum.valueOf( this.type, text )
: null );
}
public String[] getTags() {
return this.tags.clone();
}
public String getJavaInitializationString() {
String name = getAsText();
return ( name != null )
? this.type.getName() + '.' + name
: "null";
}
public boolean isPaintable() {
return false;
}
public void paintValue( Graphics gfx, Rectangle box ) {
}
public boolean supportsCustomEditor() {
return false;
}
public Component getCustomEditor() {
return null;
}
public void addPropertyChangeListener( PropertyChangeListener listener ) {
synchronized ( this.listeners ) {
this.listeners.add( listener );
}
}
public void removePropertyChangeListener( PropertyChangeListener listener ) {
synchronized ( this.listeners ) {
this.listeners.remove( listener );
}
}
}

View File

@@ -0,0 +1,48 @@
/*
* Copyright (c) 1996, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.beans.editors;
/**
* Property editor for a java builtin "float" type.
*
*/
import java.beans.*;
public class FloatEditor extends NumberEditor {
public String getJavaInitializationString() {
Object value = getValue();
return (value != null)
? value + "F"
: "null";
}
public void setAsText(String text) throws IllegalArgumentException {
setValue((text == null) ? null : Float.valueOf(text));
}
}

View File

@@ -0,0 +1,219 @@
/*
* Copyright (c) 1996, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.beans.editors;
import java.awt.*;
import java.beans.*;
public class FontEditor extends Panel implements java.beans.PropertyEditor {
private static final long serialVersionUID = 6732704486002715933L;
public FontEditor() {
setLayout(null);
toolkit = Toolkit.getDefaultToolkit();
fonts = toolkit.getFontList();
familyChoser = new Choice();
for (int i = 0; i < fonts.length; i++) {
familyChoser.addItem(fonts[i]);
}
add(familyChoser);
familyChoser.reshape(20, 5, 100, 30);
styleChoser = new Choice();
for (int i = 0; i < styleNames.length; i++) {
styleChoser.addItem(styleNames[i]);
}
add(styleChoser);
styleChoser.reshape(145, 5, 70, 30);
sizeChoser = new Choice();
for (int i = 0; i < pointSizes.length; i++) {
sizeChoser.addItem("" + pointSizes[i]);
}
add(sizeChoser);
sizeChoser.reshape(220, 5, 70, 30);
resize(300,40);
}
public Dimension preferredSize() {
return new Dimension(300, 40);
}
public void setValue(Object o) {
font = (Font) o;
if (this.font == null)
return;
changeFont(font);
// Update the current GUI choices.
for (int i = 0; i < fonts.length; i++) {
if (fonts[i].equals(font.getFamily())) {
familyChoser.select(i);
break;
}
}
for (int i = 0; i < styleNames.length; i++) {
if (font.getStyle() == styles[i]) {
styleChoser.select(i);
break;
}
}
for (int i = 0; i < pointSizes.length; i++) {
if (font.getSize() <= pointSizes[i]) {
sizeChoser.select(i);
break;
}
}
}
private void changeFont(Font f) {
font = f;
if (sample != null) {
remove(sample);
}
sample = new Label(sampleText);
sample.setFont(font);
add(sample);
Component p = getParent();
if (p != null) {
p.invalidate();
p.layout();
}
invalidate();
layout();
repaint();
support.firePropertyChange("", null, null);
}
public Object getValue() {
return (font);
}
public String getJavaInitializationString() {
if (this.font == null)
return "null";
return "new java.awt.Font(\"" + font.getName() + "\", " +
font.getStyle() + ", " + font.getSize() + ")";
}
public boolean action(Event e, Object arg) {
String family = familyChoser.getSelectedItem();
int style = styles[styleChoser.getSelectedIndex()];
int size = pointSizes[sizeChoser.getSelectedIndex()];
try {
Font f = new Font(family, style, size);
changeFont(f);
} catch (Exception ex) {
System.err.println("Couldn't create font " + family + "-" +
styleNames[style] + "-" + size);
}
return (false);
}
public boolean isPaintable() {
return true;
}
public void paintValue(java.awt.Graphics gfx, java.awt.Rectangle box) {
// Silent noop.
Font oldFont = gfx.getFont();
gfx.setFont(font);
FontMetrics fm = gfx.getFontMetrics();
int vpad = (box.height - fm.getAscent())/2;
gfx.drawString(sampleText, 0, box.height-vpad);
gfx.setFont(oldFont);
}
public String getAsText() {
if (this.font == null) {
return null;
}
StringBuilder sb = new StringBuilder();
sb.append(this.font.getName());
sb.append(' ');
boolean b = this.font.isBold();
if (b) {
sb.append("BOLD");
}
boolean i = this.font.isItalic();
if (i) {
sb.append("ITALIC");
}
if (b || i) {
sb.append(' ');
}
sb.append(this.font.getSize());
return sb.toString();
}
public void setAsText(String text) throws IllegalArgumentException {
setValue((text == null) ? null : Font.decode(text));
}
public String[] getTags() {
return null;
}
public java.awt.Component getCustomEditor() {
return this;
}
public boolean supportsCustomEditor() {
return true;
}
public void addPropertyChangeListener(PropertyChangeListener l) {
support.addPropertyChangeListener(l);
}
public void removePropertyChangeListener(PropertyChangeListener l) {
support.removePropertyChangeListener(l);
}
private Font font;
private Toolkit toolkit;
private String sampleText = "Abcde...";
private Label sample;
private Choice familyChoser;
private Choice styleChoser;
private Choice sizeChoser;
private String fonts[];
private String[] styleNames = { "plain", "bold", "italic" };
private int[] styles = { Font.PLAIN, Font.BOLD, Font.ITALIC };
private int[] pointSizes = { 3, 5, 8, 10, 12, 14, 18, 24, 36, 48 };
private PropertyChangeSupport support = new PropertyChangeSupport(this);
}

View File

@@ -0,0 +1,42 @@
/*
* Copyright (c) 2006, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.beans.editors;
/**
* Property editor for a java builtin "int" type.
*
*/
import java.beans.*;
public class IntegerEditor extends NumberEditor {
public void setAsText(String text) throws IllegalArgumentException {
setValue((text == null) ? null : Integer.decode(text));
}
}

View File

@@ -0,0 +1,48 @@
/*
* Copyright (c) 1996, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.beans.editors;
/**
* Property editor for a java builtin "long" type.
*
*/
import java.beans.*;
public class LongEditor extends NumberEditor {
public String getJavaInitializationString() {
Object value = getValue();
return (value != null)
? value + "L"
: "null";
}
public void setAsText(String text) throws IllegalArgumentException {
setValue((text == null) ? null : Long.decode(text));
}
}

View File

@@ -0,0 +1,44 @@
/*
* Copyright (c) 1996, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.beans.editors;
/**
* Abstract Property editor for a java builtin number types.
*
*/
import java.beans.*;
abstract public class NumberEditor extends PropertyEditorSupport {
public String getJavaInitializationString() {
Object value = getValue();
return (value != null)
? value.toString()
: "null";
}
}

View File

@@ -0,0 +1,49 @@
/*
* Copyright (c) 1996, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.beans.editors;
/**
* Property editor for a java builtin "short" type.
*
*/
import java.beans.*;
public class ShortEditor extends NumberEditor {
public String getJavaInitializationString() {
Object value = getValue();
return (value != null)
? "((short)" + value + ")"
: "null";
}
public void setAsText(String text) throws IllegalArgumentException {
setValue((text == null) ? null : Short.decode(text));
}
}

View File

@@ -0,0 +1,74 @@
/*
* Copyright (c) 1996, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.beans.editors;
import java.beans.*;
public class StringEditor extends PropertyEditorSupport {
public String getJavaInitializationString() {
Object value = getValue();
if (value == null)
return "null";
String str = value.toString();
int length = str.length();
StringBuilder sb = new StringBuilder(length + 2);
sb.append('"');
for (int i = 0; i < length; i++) {
char ch = str.charAt(i);
switch (ch) {
case '\b': sb.append("\\b"); break;
case '\t': sb.append("\\t"); break;
case '\n': sb.append("\\n"); break;
case '\f': sb.append("\\f"); break;
case '\r': sb.append("\\r"); break;
case '\"': sb.append("\\\""); break;
case '\\': sb.append("\\\\"); break;
default:
if ((ch < ' ') || (ch > '~')) {
sb.append("\\u");
String hex = Integer.toHexString((int) ch);
for (int len = hex.length(); len < 4; len++) {
sb.append('0');
}
sb.append(hex);
} else {
sb.append(ch);
}
break;
}
}
sb.append('"');
return sb.toString();
}
public void setAsText(String text) {
setValue(text);
}
}

View File

@@ -0,0 +1,207 @@
/*
* Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.beans.finder;
import java.lang.reflect.Executable;
import java.lang.reflect.Modifier;
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 extends Executable> {
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;
}
/**
* 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 boolean isValid(T method) {
return Modifier.isPublic(method.getModifiers());
}
/**
* 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 = newMethod.getParameterTypes();
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) {
// only if parameters are equal
useNew = !newMethod.isSynthetic();
useOld = !oldMethod.isSynthetic();
}
if (useOld == useNew) {
ambiguous = true;
} else if (useNew) {
oldMethod = newMethod;
oldParams = newParams;
ambiguous = false;
}
}
}
}
if (newMethod.isVarArgs()) {
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) {
// only if parameters are equal
useNew = !newMethod.isSynthetic();
useOld = !oldMethod.isSynthetic();
}
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

@@ -0,0 +1,102 @@
/*
* Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.beans.finder;
import java.beans.BeanDescriptor;
import java.beans.BeanInfo;
import java.beans.MethodDescriptor;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;
/**
* This is utility class that provides functionality
* to find a {@link BeanInfo} for a JavaBean specified by its type.
*
* @since 1.7
*
* @author Sergey A. Malenkov
*/
public final class BeanInfoFinder
extends InstanceFinder<BeanInfo> {
private static final String DEFAULT = "sun.beans.infos";
private static final String DEFAULT_NEW = "com.sun.beans.infos";
public BeanInfoFinder() {
super(BeanInfo.class, true, "BeanInfo", DEFAULT);
}
private static boolean isValid(Class<?> type, Method method) {
return (method != null) && method.getDeclaringClass().isAssignableFrom(type);
}
@Override
protected BeanInfo instantiate(Class<?> type, String prefix, String name) {
if (DEFAULT.equals(prefix)) {
prefix = DEFAULT_NEW;
}
// this optimization will only use the BeanInfo search path
// if is has changed from the original
// or trying to get the ComponentBeanInfo
BeanInfo info = !DEFAULT_NEW.equals(prefix) || "ComponentBeanInfo".equals(name)
? super.instantiate(type, prefix, name)
: null;
if (info != null) {
// make sure that the returned BeanInfo matches the class
BeanDescriptor bd = info.getBeanDescriptor();
if (bd != null) {
if (type.equals(bd.getBeanClass())) {
return info;
}
}
else {
PropertyDescriptor[] pds = info.getPropertyDescriptors();
if (pds != null) {
for (PropertyDescriptor pd : pds) {
Method method = pd.getReadMethod();
if (method == null) {
method = pd.getWriteMethod();
}
if (isValid(type, method)) {
return info;
}
}
}
else {
MethodDescriptor[] mds = info.getMethodDescriptors();
if (mds != null) {
for (MethodDescriptor md : mds) {
if (isValid(type, md.getMethod())) {
return info;
}
}
}
}
}
}
return null;
}
}

View File

@@ -0,0 +1,180 @@
/*
* Copyright (c) 2006, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.beans.finder;
import static sun.reflect.misc.ReflectUtil.checkPackageAccess;
/**
* 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
*
* @author Sergey A. Malenkov
*/
public final class ClassFinder {
/**
* 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} 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
*
* @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 {
checkPackageAccess(name);
try {
ClassLoader loader = Thread.currentThread().getContextClassLoader();
if (loader == null) {
// can be null in IE (see 6204697)
loader = ClassLoader.getSystemClassLoader();
}
if (loader != null) {
return Class.forName(name, false, loader);
}
} catch (ClassNotFoundException exception) {
// use current class loader instead
} catch (SecurityException exception) {
// use current class loader instead
}
return Class.forName(name);
}
/**
* 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} can denote an array class
* (see {@link Class#getName} for details).
* <p>
* 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
*
* @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 {
checkPackageAccess(name);
if (loader != null) {
try {
return Class.forName(name, false, loader);
} catch (ClassNotFoundException exception) {
// use default class loader instead
} catch (SecurityException exception) {
// use default class loader instead
}
}
return findClass(name);
}
/**
* 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} can denote an array class
* (see {@link Class#getName} for details).
* <p>
* This method can be used to obtain
* 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
*
* @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);
}
/**
* 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} can denote an array class
* (see {@link Class#getName} for details).
* <p>
* 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} 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
*
* @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)
: type;
}
/**
* Disable instantiation.
*/
private ClassFinder() {
}
}

View File

@@ -0,0 +1,100 @@
/*
* Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.beans.finder;
import com.sun.beans.util.Cache;
import java.lang.reflect.Constructor;
import java.lang.reflect.Modifier;
import static com.sun.beans.util.Cache.Kind.SOFT;
import static sun.reflect.misc.ReflectUtil.isPackageAccessible;
/**
* 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 Cache<Signature, Constructor<?>> CACHE = new Cache<Signature, Constructor<?>>(SOFT, SOFT) {
@Override
public Constructor create(Signature signature) {
try {
ConstructorFinder finder = new ConstructorFinder(signature.getArgs());
return finder.find(signature.getType().getConstructors());
}
catch (Exception exception) {
throw new SignatureException(exception);
}
}
};
/**
* 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()) || !isPackageAccessible(type)) {
throw new NoSuchMethodException("Class is not accessible");
}
PrimitiveWrapperMap.replacePrimitivesWithWrappers(args);
Signature signature = new Signature(type, args);
try {
return CACHE.get(signature);
}
catch (SignatureException exception) {
throw exception.toNoSuchMethodException("Constructor is not found");
}
}
/**
* Creates constructor finder with specified array of parameter types.
*
* @param args the array of parameter types
*/
private ConstructorFinder(Class<?>[] args) {
super(args);
}
}

View File

@@ -0,0 +1,109 @@
/*
* Copyright (c) 2008, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.beans.finder;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import static sun.reflect.misc.ReflectUtil.isPackageAccessible;
/**
* 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");
}
type = field.getDeclaringClass();
if (!Modifier.isPublic(type.getModifiers()) || !isPackageAccessible(type)) {
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,109 @@
/*
* Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.beans.finder;
/**
* This is utility class that provides basic functionality
* to find an auxiliary class for a JavaBean specified by its type.
*
* @since 1.7
*
* @author Sergey A. Malenkov
*/
class InstanceFinder<T> {
private static final String[] EMPTY = { };
private final Class<? extends T> type;
private final boolean allow;
private final String suffix;
private volatile String[] packages;
InstanceFinder(Class<? extends T> type, boolean allow, String suffix, String... packages) {
this.type = type;
this.allow = allow;
this.suffix = suffix;
this.packages = packages.clone();
}
public String[] getPackages() {
return this.packages.clone();
}
public void setPackages(String... packages) {
this.packages = (packages != null) && (packages.length > 0)
? packages.clone()
: EMPTY;
}
public T find(Class<?> type) {
if (type == null) {
return null;
}
String name = type.getName() + this.suffix;
T object = instantiate(type, name);
if (object != null) {
return object;
}
if (this.allow) {
object = instantiate(type, null);
if (object != null) {
return object;
}
}
int index = name.lastIndexOf('.') + 1;
if (index > 0) {
name = name.substring(index);
}
for (String prefix : this.packages) {
object = instantiate(type, prefix, name);
if (object != null) {
return object;
}
}
return null;
}
protected T instantiate(Class<?> type, String name) {
if (type != null) {
try {
if (name != null) {
type = ClassFinder.findClass(name, type.getClassLoader());
}
if (this.type.isAssignableFrom(type)) {
return (T) type.newInstance();
}
}
catch (Exception exception) {
// ignore any exceptions
}
}
return null;
}
protected T instantiate(Class<?> type, String prefix, String name) {
return instantiate(type, prefix + '.' + name);
}
}

View File

@@ -0,0 +1,220 @@
/*
* Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.beans.finder;
import com.sun.beans.TypeResolver;
import com.sun.beans.util.Cache;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Arrays;
import static com.sun.beans.util.Cache.Kind.SOFT;
import static sun.reflect.misc.ReflectUtil.isPackageAccessible;
/**
* 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 Cache<Signature, Method> CACHE = new Cache<Signature, Method>(SOFT, SOFT) {
@Override
public Method create(Signature signature) {
try {
MethodFinder finder = new MethodFinder(signature.getName(), signature.getArgs());
return findAccessibleMethod(finder.find(signature.getType().getMethods()));
}
catch (Exception exception) {
throw new SignatureException(exception);
}
}
};
/**
* 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);
try {
Method method = CACHE.get(signature);
return (method == null) || isPackageAccessible(method.getDeclaringClass()) ? method : CACHE.create(signature);
}
catch (SignatureException exception) {
throw exception.toNoSuchMethodException("Method '" + name + "' is not found");
}
}
/**
* 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
*/
public static Method findAccessibleMethod(Method method) throws NoSuchMethodException {
Class<?> type = method.getDeclaringClass();
if (Modifier.isPublic(type.getModifiers()) && isPackageAccessible(type)) {
return method;
}
if (Modifier.isStatic(method.getModifiers())) {
throw new NoSuchMethodException("Method '" + method.getName() + "' is not accessible");
}
for (Type generic : type.getGenericInterfaces()) {
try {
return findAccessibleMethod(method, generic);
}
catch (NoSuchMethodException exception) {
// try to find in superclass or another interface
}
}
return findAccessibleMethod(method, type.getGenericSuperclass());
}
/**
* Finds method that accessible from specified class.
*
* @param method object that represents found method
* @param generic generic type 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, Type generic) throws NoSuchMethodException {
String name = method.getName();
Class<?>[] params = method.getParameterTypes();
if (generic instanceof Class) {
Class<?> type = (Class<?>) generic;
return findAccessibleMethod(type.getMethod(name, params));
}
if (generic instanceof ParameterizedType) {
ParameterizedType pt = (ParameterizedType) generic;
Class<?> type = (Class<?>) pt.getRawType();
for (Method m : type.getMethods()) {
if (m.getName().equals(name)) {
Class<?>[] pts = m.getParameterTypes();
if (pts.length == params.length) {
if (Arrays.equals(params, pts)) {
return findAccessibleMethod(m);
}
Type[] gpts = m.getGenericParameterTypes();
if (params.length == gpts.length) {
if (Arrays.equals(params, TypeResolver.erase(TypeResolver.resolve(pt, gpts)))) {
return findAccessibleMethod(m);
}
}
}
}
}
}
throw new NoSuchMethodException("Method '" + name + "' is not accessible");
}
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;
}
/**
* 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 super.isValid(method) && method.getName().equals(this.name);
}
}

View File

@@ -0,0 +1,68 @@
/*
* Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.beans.finder;
import java.beans.PersistenceDelegate;
import java.util.HashMap;
import java.util.Map;
/**
* This is utility class that provides functionality
* to find a {@link PersistenceDelegate} for a JavaBean specified by its type.
*
* @since 1.7
*
* @author Sergey A. Malenkov
*/
public final class PersistenceDelegateFinder
extends InstanceFinder<PersistenceDelegate> {
private final Map<Class<?>, PersistenceDelegate> registry;
public PersistenceDelegateFinder() {
super(PersistenceDelegate.class, true, "PersistenceDelegate");
this.registry = new HashMap<Class<?>, PersistenceDelegate>();
}
public void register(Class<?> type, PersistenceDelegate delegate) {
synchronized (this.registry) {
if (delegate != null) {
this.registry.put(type, delegate);
}
else {
this.registry.remove(type);
}
}
}
@Override
public PersistenceDelegate find(Class<?> type) {
PersistenceDelegate delegate;
synchronized (this.registry) {
delegate = this.registry.get(type);
}
return (delegate != null) ? delegate : super.find(type);
}
}

View File

@@ -0,0 +1,70 @@
/*
* Copyright (c) 2006, 2008, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.beans.finder;
import java.util.HashMap;
import java.util.Map;
/**
* This utility class associates
* name of primitive type with appropriate class.
*
* @since 1.7
*
* @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} if not found
*/
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.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);
}
/**
* Disable instantiation.
*/
private PrimitiveTypeMap() {
}
}

View File

@@ -0,0 +1,86 @@
/*
* Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.beans.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,95 @@
/*
* Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.beans.finder;
import com.sun.beans.WeakCache;
import java.beans.PropertyEditor;
import com.sun.beans.editors.BooleanEditor;
import com.sun.beans.editors.ByteEditor;
import com.sun.beans.editors.DoubleEditor;
import com.sun.beans.editors.EnumEditor;
import com.sun.beans.editors.FloatEditor;
import com.sun.beans.editors.IntegerEditor;
import com.sun.beans.editors.LongEditor;
import com.sun.beans.editors.ShortEditor;
/**
* This is utility class that provides functionality
* to find a {@link PropertyEditor} for a JavaBean specified by its type.
*
* @since 1.7
*
* @author Sergey A. Malenkov
*/
public final class PropertyEditorFinder
extends InstanceFinder<PropertyEditor> {
private static final String DEFAULT = "sun.beans.editors";
private static final String DEFAULT_NEW = "com.sun.beans.editors";
private final WeakCache<Class<?>, Class<?>> registry;
public PropertyEditorFinder() {
super(PropertyEditor.class, false, "Editor", DEFAULT);
this.registry = new WeakCache<Class<?>, Class<?>>();
this.registry.put(Byte.TYPE, ByteEditor.class);
this.registry.put(Short.TYPE, ShortEditor.class);
this.registry.put(Integer.TYPE, IntegerEditor.class);
this.registry.put(Long.TYPE, LongEditor.class);
this.registry.put(Boolean.TYPE, BooleanEditor.class);
this.registry.put(Float.TYPE, FloatEditor.class);
this.registry.put(Double.TYPE, DoubleEditor.class);
}
public void register(Class<?> type, Class<?> editor) {
synchronized (this.registry) {
this.registry.put(type, editor);
}
}
@Override
public PropertyEditor find(Class<?> type) {
Class<?> predefined;
synchronized (this.registry) {
predefined = this.registry.get(type);
}
PropertyEditor editor = instantiate(predefined, null);
if (editor == null) {
editor = super.find(type);
if ((editor == null) && (null != type.getEnumConstants())) {
editor = new EnumEditor(type);
}
}
return editor;
}
@Override
protected PropertyEditor instantiate(Class<?> type, String prefix, String name) {
return super.instantiate(type, DEFAULT.equals(prefix) ? DEFAULT_NEW : prefix, name);
}
}

View File

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

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

View File

@@ -0,0 +1,62 @@
/*
* Copyright (c) 1996, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.beans.infos;
import java.beans.*;
/**
* BeanInfo descriptor for a standard AWT component.
*/
public class ComponentBeanInfo extends SimpleBeanInfo {
private static final Class<java.awt.Component> beanClass = java.awt.Component.class;
public PropertyDescriptor[] getPropertyDescriptors() {
try {
PropertyDescriptor
name = new PropertyDescriptor("name", beanClass),
background = new PropertyDescriptor("background", beanClass),
foreground = new PropertyDescriptor("foreground", beanClass),
font = new PropertyDescriptor("font", beanClass),
enabled = new PropertyDescriptor("enabled", beanClass),
visible = new PropertyDescriptor("visible", beanClass),
focusable = new PropertyDescriptor("focusable", beanClass);
enabled.setExpert(true);
visible.setHidden(true);
background.setBound(true);
foreground.setBound(true);
font.setBound(true);
focusable.setBound(true);
PropertyDescriptor[] rv = {name, background, foreground, font, enabled, visible, focusable };
return rv;
} catch (IntrospectionException e) {
throw new Error(e.toString());
}
}
}

View File

@@ -0,0 +1,613 @@
/*
* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.beans.util;
import java.lang.ref.ReferenceQueue;
import java.lang.ref.SoftReference;
import java.lang.ref.WeakReference;
import java.util.Objects;
/**
* Hash table based implementation of the cache,
* which allows to use weak or soft references for keys and values.
* An entry in a {@code Cache} will automatically be removed
* when its key or value is no longer in ordinary use.
*
* @author Sergey Malenkov
* @since 1.8
*/
public abstract class Cache<K,V> {
private static final int MAXIMUM_CAPACITY = 1 << 30; // maximum capacity MUST be a power of two <= 1<<30
private final boolean identity; // defines whether the identity comparison is used
private final Kind keyKind; // a reference kind for the cache keys
private final Kind valueKind; // a reference kind for the cache values
private final ReferenceQueue<Object> queue = new ReferenceQueue<>(); // queue for references to remove
private volatile CacheEntry<K,V>[] table = newTable(1 << 3); // table's length MUST be a power of two
private int threshold = 6; // the next size value at which to resize
private int size; // the number of key-value mappings contained in this map
/**
* Creates a corresponding value for the specified key.
*
* @param key a key that can be used to create a value
* @return a corresponding value for the specified key
*/
public abstract V create(K key);
/**
* Constructs an empty {@code Cache}.
* The default initial capacity is 8.
* The default load factor is 0.75.
*
* @param keyKind a reference kind for keys
* @param valueKind a reference kind for values
*
* @throws NullPointerException if {@code keyKind} or {@code valueKind} are {@code null}
*/
public Cache(Kind keyKind, Kind valueKind) {
this(keyKind, valueKind, false);
}
/**
* Constructs an empty {@code Cache}
* with the specified comparison method.
* The default initial capacity is 8.
* The default load factor is 0.75.
*
* @param keyKind a reference kind for keys
* @param valueKind a reference kind for values
* @param identity defines whether reference-equality
* is used in place of object-equality
*
* @throws NullPointerException if {@code keyKind} or {@code valueKind} are {@code null}
*/
public Cache(Kind keyKind, Kind valueKind, boolean identity) {
Objects.requireNonNull(keyKind, "keyKind");
Objects.requireNonNull(valueKind, "valueKind");
this.keyKind = keyKind;
this.valueKind = valueKind;
this.identity = identity;
}
/**
* Returns the value to which the specified key is mapped,
* or {@code null} if there is no mapping for the key.
*
* @param key the key whose cached value is to be returned
* @return a value to which the specified key is mapped,
* or {@code null} if there is no mapping for {@code key}
*
* @throws NullPointerException if {@code key} is {@code null}
* or corresponding value is {@code null}
*/
public final V get(K key) {
Objects.requireNonNull(key, "key");
removeStaleEntries();
int hash = hash(key);
// unsynchronized search improves performance
// the null value does not mean that there are no needed entry
CacheEntry<K,V>[] table = this.table; // unsynchronized access
V current = getEntryValue(key, hash, table[index(hash, table)]);
if (current != null) {
return current;
}
synchronized (this.queue) {
// synchronized search improves stability
// we must create and add new value if there are no needed entry
current = getEntryValue(key, hash, this.table[index(hash, this.table)]);
if (current != null) {
return current;
}
V value = create(key);
Objects.requireNonNull(value, "value");
int index = index(hash, this.table);
this.table[index] = new CacheEntry<>(hash, key, value, this.table[index]);
if (++this.size >= this.threshold) {
if (this.table.length == MAXIMUM_CAPACITY) {
this.threshold = Integer.MAX_VALUE;
} else {
removeStaleEntries();
table = newTable(this.table.length << 1);
transfer(this.table, table);
// If ignoring null elements and processing ref queue caused massive
// shrinkage, then restore old table. This should be rare, but avoids
// unbounded expansion of garbage-filled tables.
if (this.size >= this.threshold / 2) {
this.table = table;
this.threshold <<= 1;
} else {
transfer(table, this.table);
}
removeStaleEntries();
}
}
return value;
}
}
/**
* Removes the cached value that corresponds to the specified key.
*
* @param key the key whose mapping is to be removed from this cache
*/
public final void remove(K key) {
if (key != null) {
synchronized (this.queue) {
removeStaleEntries();
int hash = hash(key);
int index = index(hash, this.table);
CacheEntry<K,V> prev = this.table[index];
CacheEntry<K,V> entry = prev;
while (entry != null) {
CacheEntry<K,V> next = entry.next;
if (entry.matches(hash, key)) {
if (entry == prev) {
this.table[index] = next;
} else {
prev.next = next;
}
entry.unlink();
break;
}
prev = entry;
entry = next;
}
}
}
}
/**
* Removes all of the mappings from this cache.
* It will be empty after this call returns.
*/
public final void clear() {
synchronized (this.queue) {
int index = this.table.length;
while (0 < index--) {
CacheEntry<K,V> entry = this.table[index];
while (entry != null) {
CacheEntry<K,V> next = entry.next;
entry.unlink();
entry = next;
}
this.table[index] = null;
}
while (null != this.queue.poll()) {
// Clear out the reference queue.
}
}
}
/**
* Retrieves object hash code and applies a supplemental hash function
* to the result hash, which defends against poor quality hash functions.
* This is critical because {@code Cache} uses power-of-two length hash tables,
* that otherwise encounter collisions for hashCodes that do not differ
* in lower bits.
*
* @param key the object which hash code is to be calculated
* @return a hash code value for the specified object
*/
private int hash(Object key) {
if (this.identity) {
int hash = System.identityHashCode(key);
return (hash << 1) - (hash << 8);
}
int hash = key.hashCode();
// This function ensures that hashCodes that differ only by
// constant multiples at each bit position have a bounded
// number of collisions (approximately 8 at default load factor).
hash ^= (hash >>> 20) ^ (hash >>> 12);
return hash ^ (hash >>> 7) ^ (hash >>> 4);
}
/**
* Returns index of the specified hash code in the given table.
* Note that the table size must be a power of two.
*
* @param hash the hash code
* @param table the table
* @return an index of the specified hash code in the given table
*/
private static int index(int hash, Object[] table) {
return hash & (table.length - 1);
}
/**
* Creates a new array for the cache entries.
*
* @param size requested capacity MUST be a power of two
* @return a new array for the cache entries
*/
@SuppressWarnings("unchecked")
private CacheEntry<K,V>[] newTable(int size) {
return (CacheEntry<K,V>[]) new CacheEntry[size];
}
private V getEntryValue(K key, int hash, CacheEntry<K,V> entry) {
while (entry != null) {
if (entry.matches(hash, key)) {
return entry.value.getReferent();
}
entry = entry.next;
}
return null;
}
private void removeStaleEntries() {
Object reference = this.queue.poll();
if (reference != null) {
synchronized (this.queue) {
do {
if (reference instanceof Ref) {
Ref ref = (Ref) reference;
@SuppressWarnings("unchecked")
CacheEntry<K,V> owner = (CacheEntry<K,V>) ref.getOwner();
if (owner != null) {
int index = index(owner.hash, this.table);
CacheEntry<K,V> prev = this.table[index];
CacheEntry<K,V> entry = prev;
while (entry != null) {
CacheEntry<K,V> next = entry.next;
if (entry == owner) {
if (entry == prev) {
this.table[index] = next;
} else {
prev.next = next;
}
entry.unlink();
break;
}
prev = entry;
entry = next;
}
}
}
reference = this.queue.poll();
}
while (reference != null);
}
}
}
private void transfer(CacheEntry<K,V>[] oldTable, CacheEntry<K,V>[] newTable) {
int oldIndex = oldTable.length;
while (0 < oldIndex--) {
CacheEntry<K,V> entry = oldTable[oldIndex];
oldTable[oldIndex] = null;
while (entry != null) {
CacheEntry<K,V> next = entry.next;
if (entry.key.isStale() || entry.value.isStale()) {
entry.unlink();
} else {
int newIndex = index(entry.hash, newTable);
entry.next = newTable[newIndex];
newTable[newIndex] = entry;
}
entry = next;
}
}
}
/**
* Represents a cache entry (key-value pair).
*/
private final class CacheEntry<K,V> {
private final int hash;
private final Ref<K> key;
private final Ref<V> value;
private volatile CacheEntry<K,V> next;
/**
* Constructs an entry for the cache.
*
* @param hash the hash code calculated for the entry key
* @param key the entry key
* @param value the initial value of the entry
* @param next the next entry in a chain
*/
private CacheEntry(int hash, K key, V value, CacheEntry<K,V> next) {
this.hash = hash;
this.key = Cache.this.keyKind.create(this, key, Cache.this.queue);
this.value = Cache.this.valueKind.create(this, value, Cache.this.queue);
this.next = next;
}
/**
* Determines whether the entry has the given key with the given hash code.
*
* @param hash an expected hash code
* @param object an object to be compared with the entry key
* @return {@code true} if the entry has the given key with the given hash code;
* {@code false} otherwise
*/
private boolean matches(int hash, Object object) {
if (this.hash != hash) {
return false;
}
Object key = this.key.getReferent();
return (key == object) || !Cache.this.identity && (key != null) && key.equals(object);
}
/**
* Marks the entry as actually removed from the cache.
*/
private void unlink() {
this.next = null;
this.key.removeOwner();
this.value.removeOwner();
Cache.this.size--;
}
}
/**
* Basic interface for references.
* It defines the operations common for the all kind of references.
*
* @param <T> the type of object to refer
*/
private static interface Ref<T> {
/**
* Returns the object that possesses information about the reference.
*
* @return the owner of the reference or {@code null} if the owner is unknown
*/
Object getOwner();
/**
* Returns the object to refer.
*
* @return the referred object or {@code null} if it was collected
*/
T getReferent();
/**
* Determines whether the referred object was taken by the garbage collector or not.
*
* @return {@code true} if the referred object was collected
*/
boolean isStale();
/**
* Marks this reference as removed from the cache.
*/
void removeOwner();
}
/**
* Represents a reference kind.
*/
public static enum Kind {
STRONG {
<T> Ref<T> create(Object owner, T value, ReferenceQueue<? super T> queue) {
return new Strong<>(owner, value);
}
},
SOFT {
<T> Ref<T> create(Object owner, T referent, ReferenceQueue<? super T> queue) {
return (referent == null)
? new Strong<>(owner, referent)
: new Soft<>(owner, referent, queue);
}
},
WEAK {
<T> Ref<T> create(Object owner, T referent, ReferenceQueue<? super T> queue) {
return (referent == null)
? new Strong<>(owner, referent)
: new Weak<>(owner, referent, queue);
}
};
/**
* Creates a reference to the specified object.
*
* @param <T> the type of object to refer
* @param owner the owner of the reference, if needed
* @param referent the object to refer
* @param queue the queue to register the reference with,
* or {@code null} if registration is not required
* @return the reference to the specified object
*/
abstract <T> Ref<T> create(Object owner, T referent, ReferenceQueue<? super T> queue);
/**
* This is an implementation of the {@link Cache.Ref} interface
* that uses the strong references that prevent their referents
* from being made finalizable, finalized, and then reclaimed.
*
* @param <T> the type of object to refer
*/
private static final class Strong<T> implements Ref<T> {
private Object owner;
private final T referent;
/**
* Creates a strong reference to the specified object.
*
* @param owner the owner of the reference, if needed
* @param referent the non-null object to refer
*/
private Strong(Object owner, T referent) {
this.owner = owner;
this.referent = referent;
}
/**
* Returns the object that possesses information about the reference.
*
* @return the owner of the reference or {@code null} if the owner is unknown
*/
public Object getOwner() {
return this.owner;
}
/**
* Returns the object to refer.
*
* @return the referred object
*/
public T getReferent() {
return this.referent;
}
/**
* Determines whether the referred object was taken by the garbage collector or not.
*
* @return {@code true} if the referred object was collected
*/
public boolean isStale() {
return false;
}
/**
* Marks this reference as removed from the cache.
*/
public void removeOwner() {
this.owner = null;
}
}
/**
* This is an implementation of the {@link Cache.Ref} interface
* that uses the soft references that are cleared at the discretion
* of the garbage collector in response to a memory request.
*
* @param <T> the type of object to refer
* @see java.lang.ref.SoftReference
*/
private static final class Soft<T> extends SoftReference<T> implements Ref<T> {
private Object owner;
/**
* Creates a soft reference to the specified object.
*
* @param owner the owner of the reference, if needed
* @param referent the non-null object to refer
* @param queue the queue to register the reference with,
* or {@code null} if registration is not required
*/
private Soft(Object owner, T referent, ReferenceQueue<? super T> queue) {
super(referent, queue);
this.owner = owner;
}
/**
* Returns the object that possesses information about the reference.
*
* @return the owner of the reference or {@code null} if the owner is unknown
*/
public Object getOwner() {
return this.owner;
}
/**
* Returns the object to refer.
*
* @return the referred object or {@code null} if it was collected
*/
public T getReferent() {
return get();
}
/**
* Determines whether the referred object was taken by the garbage collector or not.
*
* @return {@code true} if the referred object was collected
*/
public boolean isStale() {
return null == get();
}
/**
* Marks this reference as removed from the cache.
*/
public void removeOwner() {
this.owner = null;
}
}
/**
* This is an implementation of the {@link Cache.Ref} interface
* that uses the weak references that do not prevent their referents
* from being made finalizable, finalized, and then reclaimed.
*
* @param <T> the type of object to refer
* @see java.lang.ref.WeakReference
*/
private static final class Weak<T> extends WeakReference<T> implements Ref<T> {
private Object owner;
/**
* Creates a weak reference to the specified object.
*
* @param owner the owner of the reference, if needed
* @param referent the non-null object to refer
* @param queue the queue to register the reference with,
* or {@code null} if registration is not required
*/
private Weak(Object owner, T referent, ReferenceQueue<? super T> queue) {
super(referent, queue);
this.owner = owner;
}
/**
* Returns the object that possesses information about the reference.
*
* @return the owner of the reference or {@code null} if the owner is unknown
*/
public Object getOwner() {
return this.owner;
}
/**
* Returns the object to refer.
*
* @return the referred object or {@code null} if it was collected
*/
public T getReferent() {
return get();
}
/**
* Determines whether the referred object was taken by the garbage collector or not.
*
* @return {@code true} if the referred object was collected
*/
public boolean isStale() {
return null == get();
}
/**
* Marks this reference as removed from the cache.
*/
public void removeOwner() {
this.owner = null;
}
}
}
}