1 /***************************************************************************************
2 * Copyright (c) Jonas Bon?r, Alexandre Vasseur. All rights reserved. *
3 * http://aspectwerkz.codehaus.org *
4 * ---------------------------------------------------------------------------------- *
5 * The software in this package is published under the terms of the LGPL license *
6 * a copy of which has been included with this distribution in the license.txt file. *
7 **************************************************************************************/
8 package org.codehaus.aspectwerkz.annotation;
9
10 import org.codehaus.aspectwerkz.annotation.expression.AnnotationVisitor;
11 import org.codehaus.aspectwerkz.util.Strings;
12
13 import java.lang.reflect.InvocationHandler;
14 import java.lang.reflect.Method;
15 import java.io.Serializable;
16 import java.util.Map;
17 import java.util.HashMap;
18 import java.util.Iterator;
19
20 /***
21 * A Java 1.3 / 1.4 strongly typed Annotation handler.
22 * This proxy handler gets serialized alongside the annotationInfo within the AnnotationC compiled class.
23 *
24 * @author <a href="mailto:alex@gnilux.com">Alexandre Vasseur</a>
25 */
26 public class Java14AnnotationInvocationHander implements InvocationHandler, Serializable {
27
28
29 private static final long serialVersionUID = 1L;
30
31 private String m_annotationClassName;
32 private String m_rawAnnotationName;
33 private String m_rawAnnotationValue;
34 private final boolean m_isUntyped;
35 private final Map m_elements = new HashMap();
36
37 /***
38 * Constructor that will trigger the parsing if required
39 *
40 * @param annotationInterface
41 * @param rawAnnotationName
42 * @param rawAnnotationValue
43 */
44 public Java14AnnotationInvocationHander(Class annotationInterface, String rawAnnotationName,
45 String rawAnnotationValue) {
46 m_annotationClassName = annotationInterface.getName().replace('/', '.');
47 m_rawAnnotationName = rawAnnotationName;
48 m_rawAnnotationValue = rawAnnotationValue;
49
50
51 if (annotationInterface.getName().equals(UntypedAnnotation.class.getName())) {
52 m_isUntyped = true;
53 } else {
54 m_isUntyped = false;
55 }
56
57
58
59
60 if ((m_annotationClassName.equals("org.codehaus.aspectwerkz.annotation.AfterReturning")
61 || m_annotationClassName.equals("org.codehaus.aspectwerkz.annotation.AfterThrowing")
62 || m_annotationClassName.startsWith("org.codehaus.aspectwerkz.annotation.")
63 || isSingleStringValued(annotationInterface))
64 && !m_isUntyped) {
65 String trimed = m_rawAnnotationValue.trim();
66 if (!isSingleStringValued(annotationInterface) &&
67 (trimed.startsWith("type")
68 || trimed.startsWith("pointcut")
69 || trimed.startsWith("deploymentModel"))) {
70 ;
71 } else {
72 if (m_rawAnnotationValue.startsWith("\"") && m_rawAnnotationValue.endsWith("\"")) {
73 ;
74 } else {
75 m_rawAnnotationValue = "\"" + Strings.replaceSubString(m_rawAnnotationValue, "\"", "//\"") + "\"";
76 }
77 }
78 } else if (m_isUntyped) {
79 if (m_rawAnnotationValue.startsWith("\"") && m_rawAnnotationValue.endsWith("\"")) {
80 if (m_rawAnnotationValue.length()>2) {
81 m_rawAnnotationValue = m_rawAnnotationValue.substring(1, m_rawAnnotationValue.length()-1);
82 }
83 }
84 }
85
86
87 if (!m_isUntyped) {
88 StringBuffer representation = new StringBuffer("@");
89 representation.append(m_annotationClassName).append('(');
90 if (m_rawAnnotationValue != null) {
91
92
93
94 if (m_annotationClassName.equals("org.codehaus.aspectwerkz.annotation.Aspect")) {
95 if (m_rawAnnotationValue.indexOf("name") < 0) {
96 representation.append(m_rawAnnotationValue);
97 }
98 } else {
99 representation.append(m_rawAnnotationValue);
100 }
101 }
102 representation.append(')');
103
104 AnnotationVisitor.parse(m_elements, representation.toString(), annotationInterface);
105 }
106 }
107
108 private static boolean isSingleStringValued(Class annotationInterface) {
109 if (annotationInterface.getDeclaredMethods().length == 1) {
110 Method m = annotationInterface.getDeclaredMethods()[0];
111 return (m.getName().equals("value") && m.getReturnType().equals(String.class));
112 }
113 return false;
114 }
115
116 /***
117 * Raw constructor that assumes an already analysed annotation instance
118 * Used for nested annotation
119 *
120 * @param annotationInterface
121 * @param elements
122 */
123 public Java14AnnotationInvocationHander(Class annotationInterface, Map elements) {
124 m_annotationClassName = annotationInterface.getName().replace('/', '.');
125 m_rawAnnotationName = m_annotationClassName;
126 m_isUntyped = false;
127 m_rawAnnotationValue = null;
128
129 m_elements.putAll(elements);
130 }
131
132 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
133 String methodName = method.getName();
134 Object returned = null;
135 if ("toString".equals(methodName)) {
136 StringBuffer sb = new StringBuffer();
137 sb.append('@').append(m_rawAnnotationName);
138 sb.append("(");
139 String sep = "";
140 for (Iterator iterator = m_elements.keySet().iterator(); iterator.hasNext();) {
141 String elementName = (String) iterator.next();
142 AnnotationElement element = (AnnotationElement) m_elements.get(elementName);
143 sb.append(sep).append(element.name + "=" + element.toString());
144 sep = ", ";
145 }
146 sb.append(")");
147 returned = sb.toString();
148 } else if ("annotationType".equals(methodName)) {
149 return Class.forName(m_annotationClassName, false, proxy.getClass().getClassLoader());
150 } else if (m_isUntyped) {
151 if ("value".equals(methodName)) {
152 returned = m_rawAnnotationValue;
153 } else if ("name".equals(methodName)) {
154 returned = m_rawAnnotationName;
155 } else if ("annotationType".equals(methodName)) {
156 returned = Class.forName(m_annotationClassName, false, proxy.getClass().getClassLoader());
157 } else {
158 throw new RuntimeException(
159 "No such element on Annotation @" + m_annotationClassName + " : " + methodName
160 );
161 }
162 } else if (m_elements.containsKey(methodName)) {
163 AnnotationElement element = (AnnotationElement) m_elements.get(methodName);
164 Object valueHolder = element.resolveValueHolderFrom(proxy.getClass().getClassLoader());
165 returned = valueHolder;
166 } else {
167 returned = null;
168 }
169
170
171 if (returned == null && method.getReturnType().isPrimitive()) {
172 Class returnedTyped = method.getReturnType();
173 if (boolean.class.equals(returnedTyped)) {
174 return Boolean.FALSE;
175 } else {
176 short s0 = 0;
177 return new Short(s0);
178 }
179 } else {
180 return returned;
181 }
182 }
183
184
185
186
187
188
189
190 }
191