[jboss-cvs] container/src/main/org/jboss/annotation/factory ...
Kabir Khan
kkhan at jboss.com
Tue Jul 18 07:23:50 EDT 2006
User: kkhan
Date: 06/07/18 07:23:50
Added: src/main/org/jboss/annotation/factory
AnnotationProxy.java
AnnotationValidationException.java
SimpleAnnotationValidator.java
AnnotationValidator.java AnnotationCreator.java
Log:
Move annotation creator into container from aop module
Use jboss retro to create a JDK 1.4 dist and test under JDK 1,4.
Revision Changes Path
1.1 date: 2006/07/18 11:23:50; author: kkhan; state: Exp;container/src/main/org/jboss/annotation/factory/AnnotationProxy.java
Index: AnnotationProxy.java
===================================================================
/*
* JBoss, Home of Professional Open Source
* Copyright 2005, JBoss Inc., and individual contributors as indicated
* by the @authors tag. See the copyright.txt in the distribution for a
* full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.jboss.annotation.factory;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Map;
/**
* Comment
*
* @author <a href="mailto:bill at jboss.org">Bill Burke</a>
* @author <a href="mailto:kabir.khan at jboss.org">Kabir Khan</a>
* @version $Revision: 1.1 $
*/
public class AnnotationProxy implements InvocationHandler
{
Map map;
Class annotationType;
public AnnotationProxy(Class annotationType, Map valueMap)
{
this.annotationType = annotationType;
map = valueMap;
}
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable
{
if (method.getName().equals("equals"))
{
return doEquals(proxy, args[0]);
}
else if (method.getName().equals("hashCode"))
{
return doHashCode();
}
else if (method.getName().equals("toString"))
{
return map.toString();
}
else if (method.getName().equals("annotationType"))
{
return annotationType;
}
/*
Object obj = map.get(method.getName());
if (!method.getReturnType().equals(obj.getClass()))
{
System.err.println("***** " + method.toString() + " has bad return type: " + obj.getClass().getName());
}
return obj;
*/
return map.get(method.getName());
}
public Object getValue(String name)
{
return map.get(name);
}
private Object doEquals(Object proxy, Object obj)
{
if (obj == proxy) return Boolean.TRUE;
if (obj == null) return Boolean.FALSE;
Class[] intfs = proxy.getClass().getInterfaces();
if (!intfs[0].isAssignableFrom(obj.getClass()))
{
return Boolean.FALSE;
}
try
{
Proxy.getInvocationHandler(obj);
}
catch (Exception ex)
{
return Boolean.FALSE;
}
return Boolean.TRUE;
}
private Object doHashCode()
{
return new Integer(map.hashCode());
}
public static Object createProxy(Map map, Class annotation) throws Exception
{
AnnotationProxy proxyHandler = new AnnotationProxy(annotation, map);
return java.lang.reflect.Proxy.newProxyInstance(annotation.getClassLoader(), new Class[]{annotation}, proxyHandler);
}
}
1.1 date: 2006/07/18 11:23:50; author: kkhan; state: Exp;container/src/main/org/jboss/annotation/factory/AnnotationValidationException.java
Index: AnnotationValidationException.java
===================================================================
/*
* JBoss, Home of Professional Open Source
* Copyright 2005, JBoss Inc., and individual contributors as indicated
* by the @authors tag. See the copyright.txt in the distribution for a
* full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.jboss.annotation.factory;
/**
*
* @author <a href="kabir.khan at jboss.com">Kabir Khan</a>
* @version $Revision: 1.1 $
*/
public class AnnotationValidationException extends RuntimeException
{
private static final long serialVersionUID = 2710034018990217179L;
public AnnotationValidationException(String msg)
{
super(msg);
}
}
1.1 date: 2006/07/18 11:23:50; author: kkhan; state: Exp;container/src/main/org/jboss/annotation/factory/SimpleAnnotationValidator.java
Index: SimpleAnnotationValidator.java
===================================================================
/*
* JBoss, Home of Professional Open Source
* Copyright 2005, JBoss Inc., and individual contributors as indicated
* by the @authors tag. See the copyright.txt in the distribution for a
* full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.jboss.annotation.factory;
import java.lang.reflect.Method;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.ArrayList;
import java.util.Map;
/**
* Validates if all attributes have been filled in for an annotation.
* Makes no attempt to read default values
*
* @author <a href="kabir.khan at jboss.com">Kabir Khan</a>
* @version $Revision: 1.1 $
*/
public class SimpleAnnotationValidator implements AnnotationValidator
{
public void validate(Map map, Class annotation)
{
ArrayList notAssignedAttributes = null;
Method[] methods = getDeclaredMethods(annotation);
for (int i = 0 ; i < methods.length ; i++)
{
if (map.get(methods[i].getName()) == null)
{
if (notAssignedAttributes == null)
{
notAssignedAttributes = new ArrayList();
}
notAssignedAttributes.add(methods[i].getName());
}
}
if (notAssignedAttributes != null)
{
throw new AnnotationValidationException("Unable to fill in default attributes for " + annotation + " " + notAssignedAttributes);
}
}
private Method[] getDeclaredMethods(final Class clazz)
{
return (Method[])AccessController.doPrivileged(new PrivilegedAction() {
public Object run()
{
return clazz.getDeclaredMethods();
};
});
}
}
1.1 date: 2006/07/18 11:23:50; author: kkhan; state: Exp;container/src/main/org/jboss/annotation/factory/AnnotationValidator.java
Index: AnnotationValidator.java
===================================================================
/*
* JBoss, Home of Professional Open Source
* Copyright 2005, JBoss Inc., and individual contributors as indicated
* by the @authors tag. See the copyright.txt in the distribution for a
* full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.jboss.annotation.factory;
import java.util.Map;
/**
* Validates that all annotations created for a proxy have been filled in.
* Depending on the underlying implementation fills in missing attributes with default values.
*
* @author <a href="kabir.khan at jboss.com">Kabir Khan</a>
* @version $Revision: 1.1 $
*/
public interface AnnotationValidator
{
/**
* Validates that all annotations created for a proxy have been filled in.
* Depending on the underlying implementation fills in missing attributes with default values.
* @param map The annotation attribute values
* @param annotation The annotation type
* @throws AnnotationValidationException if some attributes were not filled in and no default value exists for that attribute
*/
void validate(Map map, Class annotation);
}
1.1 date: 2006/07/18 11:23:50; author: kkhan; state: Exp;container/src/main/org/jboss/annotation/factory/AnnotationCreator.java
Index: AnnotationCreator.java
===================================================================
/*
* JBoss, Home of Professional Open Source
* Copyright 2005, JBoss Inc., and individual contributors as indicated
* by the @authors tag. See the copyright.txt in the distribution for a
* full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.jboss.annotation.factory;
import org.jboss.annotation.factory.ast.ASTAnnotation;
import org.jboss.annotation.factory.ast.ASTChar;
import org.jboss.annotation.factory.ast.ASTIdentifier;
import org.jboss.annotation.factory.ast.ASTMemberValueArrayInitializer;
import org.jboss.annotation.factory.ast.ASTMemberValuePair;
import org.jboss.annotation.factory.ast.ASTMemberValuePairs;
import org.jboss.annotation.factory.ast.ASTSingleMemberValue;
import org.jboss.annotation.factory.ast.ASTStart;
import org.jboss.annotation.factory.ast.ASTString;
import org.jboss.annotation.factory.ast.AnnotationParser;
import org.jboss.annotation.factory.ast.AnnotationParserVisitor;
import org.jboss.annotation.factory.ast.Node;
import org.jboss.annotation.factory.ast.SimpleNode;
import org.jboss.annotation.factory.javassist.DefaultValueAnnotationValidator;
import java.io.StringReader;
import java.lang.annotation.Annotation;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.security.AccessController;
import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
import java.util.HashMap;
/**
* Comment
*
* @author <a href="mailto:bill at jboss.org">Bill Burke</a>
* @author <a href="mailto:kabir.khan at jboss.org">Kabir Khan</a>
* @version $Revision: 1.1 $
*/
public class AnnotationCreator implements AnnotationParserVisitor
{
private Class annotation;
private Class type;
public Object typeValue;
static final AnnotationValidator defaultAnnotationReader;
static
{
boolean haveJavassist = false;
try
{
Class clazz = Class.forName("javassist.CtClass");
haveJavassist = true;
}
catch(ClassNotFoundException ignore)
{
}
if (haveJavassist)
{
defaultAnnotationReader = new DefaultValueAnnotationValidator();
}
else
{
defaultAnnotationReader = new SimpleAnnotationValidator();
}
}
public AnnotationCreator(Class annotation, Class type)
{
this.type = type;
this.annotation = annotation;
}
public Object visit(ASTMemberValuePairs node, Object data)
{
node.childrenAccept(this, data);
return null;
}
public Object visit(ASTMemberValuePair node, Object data)
{
String name = node.getIdentifier().getValue();
node.getValue().jjtAccept(this, name);
return data;
}
public Object visit(ASTSingleMemberValue node, Object data)
{
node.getValue().jjtAccept(this, "value");
return data;
}
public Object visit(ASTIdentifier node, Object data)
{
try
{
if (type.equals(Class.class))
{
String classname = node.getValue();
if (classname.endsWith(".class"))
{
classname = classname.substring(0, classname.indexOf(".class"));
}
if (classname.equals("void"))
{
typeValue = void.class;
}
else if (classname.equals("int"))
{
typeValue = int.class;
}
else if (classname.equals("byte"))
{
typeValue = byte.class;
}
else if (classname.equals("long"))
{
typeValue = long.class;
}
else if (classname.equals("double"))
{
typeValue = double.class;
}
else if (classname.equals("float"))
{
typeValue = float.class;
}
else if (classname.equals("char"))
{
typeValue = char.class;
}
else if (classname.equals("short"))
{
typeValue = short.class;
}
else if (classname.equals("boolean"))
{
typeValue = boolean.class;
}
else
{
typeValue = Thread.currentThread().getContextClassLoader().loadClass(classname);
}
}
else if (type.isPrimitive())
{
if (type.equals(boolean.class))
{
typeValue = new Boolean(node.getValue());
}
else if (type.equals(short.class))
{
typeValue = Short.valueOf(node.getValue());
}
else if (type.equals(float.class))
{
typeValue = Float.valueOf(node.getValue());
}
else if (type.equals(double.class))
{
typeValue = Double.valueOf(node.getValue());
}
else if (type.equals(long.class))
{
typeValue = Long.valueOf(node.getValue());
}
else if (type.equals(byte.class))
{
typeValue = new Byte(node.getValue());
}
else if (type.equals(int.class))
{
typeValue = new Integer(node.getValue());
}
}
else // its an enum
{
int index = node.getValue().lastIndexOf('.');
if (index == -1) throw new RuntimeException("Enum must be fully qualified: " + node.getValue());
String className = node.getValue().substring(0, index);
String en = node.getValue().substring(index + 1);
Class enumClass = Thread.currentThread().getContextClassLoader().loadClass(className);
if (enumClass.getSuperclass().getName().equals("java.lang.Enum"))
{
Method valueOf = null;
Method[] methods = enumClass.getSuperclass().getMethods();
for (int i = 0; i < methods.length; i++)
{
if (methods[i].getName().equals("valueOf"))
{
valueOf = methods[i];
break;
}
}
Object[] args = {enumClass, en};
typeValue = valueOf.invoke(null, args);
}
else
{
Field field = enumClass.getField(en);
typeValue = field.get(null);
}
}
}
catch (ClassNotFoundException e)
{
throw new RuntimeException(e);
}
catch (IllegalAccessException e)
{
throw new RuntimeException(e);
}
catch (InvocationTargetException e)
{
throw new RuntimeException(e);
}
catch (NoSuchFieldException e)
{
throw new RuntimeException(e);
}
return null;
}
public Object visit(ASTString node, Object data)
{
if (!type.equals(String.class)) throw new RuntimeException(annotation.getName() + "." + data + " is not an String");
typeValue = node.getValue();
return null;
}
public Object visit(ASTChar node, Object data)
{
if (!type.equals(char.class)) throw new RuntimeException(annotation.getName() + "." + data + " is not an char");
typeValue = new Character(node.getValue());
return null;
}
public Object visit(ASTMemberValueArrayInitializer node, Object data)
{
if (!type.isArray()) throw new RuntimeException(annotation.getName() + "." + data + " is not an array");
Class baseType = type.getComponentType();
int size = node.jjtGetNumChildren();
typeValue = Array.newInstance(baseType, size);
for (int i = 0; i < size; i++)
{
AnnotationCreator creator = new AnnotationCreator(annotation, baseType);
node.jjtGetChild(i).jjtAccept(creator, null);
Array.set(typeValue, i, creator.typeValue);
}
return null;
}
public Object visit(ASTAnnotation node, Object data)
{
try
{
Class subAnnotation = Thread.currentThread().getContextClassLoader().loadClass(node.getIdentifier());
typeValue = createAnnotation(node, subAnnotation);
}
catch (Exception e)
{
throw new RuntimeException(e);
}
return null;
}
// Unneeded
public Object visit(SimpleNode node, Object data)
{
return null;
}
public Object visit(ASTStart node, Object data)
{
return null;
}
private static Class getMemberType(Class annotation, String member)
{
Method[] methods = annotation.getMethods();
for (int i = 0; i < methods.length; i++)
{
if (methods[i].getName().equals(member))
{
return methods[i].getReturnType();
}
}
throw new RuntimeException("unable to determine member type for annotation: " + annotation.getName() + "." + member);
}
public static Object createAnnotation(ASTAnnotation node, Class annotation) throws Exception
{
HashMap map = new HashMap();
if (node.jjtGetNumChildren() > 0)
{
Node contained = node.jjtGetChild(0);
if (contained instanceof ASTSingleMemberValue)
{
Class type = getMemberType(annotation, "value");
AnnotationCreator creator = new AnnotationCreator(annotation, type);
contained.jjtAccept(creator, "value");
map.put("value", creator.typeValue);
}
else
{
ASTMemberValuePairs pairs = (ASTMemberValuePairs) contained;
for (int i = 0; i < pairs.jjtGetNumChildren(); i++)
{
ASTMemberValuePair member = (ASTMemberValuePair) pairs.jjtGetChild(i);
Class type = getMemberType(annotation, member.getIdentifier().getValue());
AnnotationCreator creator = new AnnotationCreator(annotation, type);
member.jjtAccept(creator, null);
map.put(member.getIdentifier().getValue(), creator.typeValue);
}
}
}
defaultAnnotationReader.validate(map, annotation);
return AnnotationProxy.createProxy(map, annotation);
}
public static Object createAnnotation(final String annotationExpr, final Class annotation) throws Exception
{
try
{
Object proxy = AccessController.doPrivileged(new PrivilegedExceptionAction() {
public Object run() throws Exception{
AnnotationParser parser = new AnnotationParser(new StringReader(annotationExpr));
org.jboss.annotation.factory.ast.ASTStart start = parser.Start();
ASTAnnotation node = (ASTAnnotation) start.jjtGetChild(0);
return createAnnotation(node, annotation);
}
});
return proxy;
}
catch (PrivilegedActionException e)
{
throw new RuntimeException(e.getException());
}
}
}
More information about the jboss-cvs-commits
mailing list