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.exception.WrappedRuntimeException;
11
12 import java.io.Serializable;
13 import java.lang.reflect.Array;
14
15 /***
16 * A structure for an Annotation element
17 * It wraps value behind an holder. The holder is the object itself (boxed) excepted
18 * for Class, for which it is a LazyClass.
19 *
20 * @author <a href="mailto:alex AT gnilux DOT com">Alexandre Vasseur</a>
21 */
22 public class AnnotationElement implements Serializable {
23
24
25 private static final long serialVersionUID = 1L;
26
27 /***
28 * element name
29 */
30 String name;
31
32 /***
33 * element value holder
34 */
35 private Object valueHolder;
36
37 /***
38 * true if we have a lasy class (optimization to avoid instance of at each get)
39 */
40 protected boolean isLazyClass = false;
41
42 /***
43 * true if we have a lasy class array (N-dim) (optimization to avoid instance of at each get)
44 */
45 protected boolean isLazyClassArray = false;
46
47 /***
48 * Build a new annotation element
49 * @param name
50 * @param valueHolder
51 */
52 public AnnotationElement(String name, Object valueHolder) {
53 this.name = name;
54 this.valueHolder = valueHolder;
55 if (valueHolder instanceof LazyClass) {
56 isLazyClass = true;
57 } else if (valueHolder instanceof LazyClass[]) {
58 isLazyClassArray = true;
59 }
60 }
61
62 /***
63 * Returns the actual holded element value
64 *
65 * @param loader from which to resolve LazyClass. It should be the annotated element class loader
66 * @return
67 */
68 public Object resolveValueHolderFrom(ClassLoader loader) {
69 if (isLazyClass) {
70 return ((LazyClass) valueHolder).resolveFrom(loader);
71 } else if (isLazyClassArray) {
72 Object[] annotationValueHolderArray = (Object[]) valueHolder;
73 Class[] resolved = new Class[annotationValueHolderArray.length];
74 for (int i = 0; i < annotationValueHolderArray.length; i++) {
75 resolved[i] = ((LazyClass)annotationValueHolderArray[i]).resolveFrom(loader);
76 }
77 return resolved;
78
79 } else {
80 return valueHolder;
81 }
82 }
83
84 /***
85 * Returns a string representation of the annotation element value
86 *
87 * Note that such a represention won't look like source code.
88 * (f.e. element String s() will not have quotes and escapes etc).
89 * @return
90 */
91 public String toString() {
92 if (isLazyClass) {
93 StringBuffer sb = new StringBuffer("class ");
94 sb.append(((LazyClass) valueHolder).className);
95 return sb.toString();
96 } else {
97 if (valueHolder == null) {
98 return "null";
99 } else {
100 return valueHolder.toString();
101 }
102 }
103 }
104
105 /***
106 * A wrapper for a className, that will allow late loading of the actual Class object of an annotation value
107 * For array type, className is componentClassName([])*
108 *
109 * @author <a href="mailto:alex AT gnilux DOT com">Alexandre Vasseur</a>
110 */
111 public static class LazyClass implements Serializable {
112
113
114 private static final long serialVersionUID = 1L;
115
116 public String className;
117 private String componentClassName = null;
118 private int dimemsion = 0;
119
120 public LazyClass(String className) {
121 this.className = className;
122
123 componentClassName = className;
124 while (componentClassName.endsWith("[]")) {
125 dimemsion++;
126 componentClassName = componentClassName.substring(0, componentClassName.length()-2);
127 }
128 }
129
130 public String toString() {
131 return className;
132 }
133
134 public Class resolveFrom(ClassLoader loader) {
135 try {
136 if (dimemsion <= 0) {
137 return Class.forName(className, false, loader);
138 } else {
139 Class componentClass = Class.forName(componentClassName, false, loader);
140 return (Array.newInstance(componentClass, dimemsion)).getClass();
141 }
142 } catch (ClassNotFoundException e) {
143 throw new WrappedRuntimeException(e);
144 }
145 }
146 }
147
148 }