Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
package org.apache.harmony.lang.annotation;
import static org.apache.harmony.lang.annotation.AnnotationMember.ARRAY;
import static org.apache.harmony.lang.annotation.AnnotationMember.ERROR;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.Serializable;
import java.lang.annotation.Annotation;
import java.lang.annotation.IncompleteAnnotationException;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.WeakHashMap;
/**
* The annotation implementation based on dynamically generated proxy instances.
* It conforms to all requirements stated in public APIs, see in particular
* {@link java.lang.reflect.AnnotatedElement java.lang.reflect.AnnotatedElement}
* and {@link java.lang.annotation.Annotation java.lang.annotation.Annotation}.
* Namely, annotation instances are immutable and serializable; they provide
* conforming access to annotation member values and required implementations of
* methods declared in Annotation interface.
*
* @see org.apache.harmony.lang.annotation.AnnotationMember
* @see java.lang.annotation.Annotation
*
* @author Alexey V. Varlamov, Serguei S. Zapreyev
* @version $Revision$
*/
@SuppressWarnings({"serial"})
public final class AnnotationFactory implements InvocationHandler, Serializable {
private static final transient
Map, AnnotationMember[]>
cache = new WeakHashMap, AnnotationMember[]>();
/**
* Reflects specified annotation type and returns an array
* of member element definitions with default values.
* @param annotationType the annotation type definition
* @return a new annotation instance array
*/
public static AnnotationMember[] getElementsDescription(Class extends Annotation> annotationType ) {
AnnotationMember[] desc = cache.get(annotationType);
if (desc == null) {
if (!annotationType.isAnnotation()) {
throw new IllegalArgumentException("Type is not annotation: "
+ annotationType.getName());
}
Method[] m = annotationType.getDeclaredMethods();
desc = new AnnotationMember[m.length];
int idx = 0;
for(Method element : m) {
String name = element.getName();
Class> type = element.getReturnType();
try {
desc[idx] = new AnnotationMember(name,
element.getDefaultValue(), type, element);
} catch (Throwable t) {
desc[idx] = new AnnotationMember(name, t, type, element);
}
idx++;
}
cache.put(annotationType, desc);
}
return desc;
}
/**
* Provides a new annotation instance.
* @param annotationType the annotation type definition
* @param elements name-value pairs representing elements of the annotation
* @return a new annotation instance
*/
public static Annotation createAnnotation(
Class extends Annotation> annotationType,
AnnotationMember[] elements)
{
AnnotationFactory antn = new AnnotationFactory(annotationType, elements);
return (Annotation)Proxy.newProxyInstance( annotationType.getClassLoader(),
new Class[]{annotationType}, antn);
}
private final Class extends Annotation> klazz;
private AnnotationMember[] elements;
/**
* New instances should not be created directly, use factory method
* {@link #createAnnotation(Class, AnnotationMember[]) createAnnotation()}
* instead.
*
* @param klzz class defining the annotation type
* @param values actual element values
*/
public AnnotationFactory(Class extends Annotation> klzz, AnnotationMember[] values) {
klazz = klzz;
AnnotationMember[] defs = getElementsDescription(klazz);
if (values == null) {
elements = defs;
} else {
//merge default and actual values
elements = new AnnotationMember[defs.length];
next: for (int i = elements.length - 1; i >= 0; i-- ){
for (AnnotationMember val : values){
if (val.name.equals(defs[i].name)) {
elements[i] = val.setDefinition(defs[i]);
continue next;
}
}
elements[i] = defs[i];
}
}
}
/**
* Reads the object, obtains actual member definitions for the annotation type,
* and merges deserialized values with the new definitions.
* @param os ObjectInputStream
* @throws IOException if Class Not Found
* @throws ClassNotFoundException if Class Not Found
*/
private void readObject(ObjectInputStream os) throws IOException, ClassNotFoundException {
os.defaultReadObject();
// Annotation type members can be changed arbitrarily
// So there may be zombi elements from the previous life;
// they hardly fit into this new annotation's incarnation,
// as we have no defining methods for them.
// Reasonably just drop such elements,
// but seems better to keep them for compatibility
AnnotationMember[] defs = getElementsDescription(klazz);
AnnotationMember[] old = elements;
List merged = new ArrayList(
defs.length + old.length);
nextOld: for (AnnotationMember el1 : old) {
for (AnnotationMember el2 : defs) {
if (el2.name.equals(el1.name)) {
continue nextOld;
}
}
merged.add(el1); //phantom element
}
nextNew: for (AnnotationMember def : defs){
for (AnnotationMember val : old){
if (val.name.equals(def.name)) {
// nothing to do about cached errors (if any)
// anyway they remain relevant to values
merged.add(val.setDefinition(def));
continue nextNew;
}
}
merged.add(def); // brand new element
}
elements = merged.toArray(new AnnotationMember[merged.size()]);
}
/**
* Returns true if the specified object represents the same annotation instance.
* That is, if it implements the same annotation type and
* returns the same element values.
* Note, actual underlying implementation mechanism does not matter - it may
* differ completely from this class.
* @param obj Object
* @return true if the passed object is equivalent annotation instance,
* false otherwise.
* @see org.apache.harmony.lang.annotation.AnnotationMember#equals(Object)
*/
public boolean equals(Object obj) {
if (obj == this) {
return true;
}
if (!klazz.isInstance(obj)) {
return false;
}
Object handler = null;
if (Proxy.isProxyClass(obj.getClass())
&& (handler = Proxy.getInvocationHandler(obj)) instanceof AnnotationFactory ) {
AnnotationFactory other = (AnnotationFactory) handler;
if (elements.length != other.elements.length) {
return false;
}
next: for (AnnotationMember el1 : elements){
for (AnnotationMember el2 : other.elements) {
if (el1.equals(el2)) {
continue next;
}
}
return false;
}
return true;
} else {
// encountered foreign annotation implementaton
// so have to obtain element values via invocation
// of corresponding methods
for (final AnnotationMember el : elements) {
if (el.tag == ERROR) {
// undefined value is incomparable (transcendent)
return false;
}
try {
if (!el.definingMethod.isAccessible()) {
AccessController.doPrivileged(new PrivilegedAction