001 // Copyright 2010 The Apache Software Foundation
002 //
003 // Licensed under the Apache License, Version 2.0 (the "License");
004 // you may not use this file except in compliance with the License.
005 // You may obtain a copy of the License at
006 //
007 // http://www.apache.org/licenses/LICENSE-2.0
008 //
009 // Unless required by applicable law or agreed to in writing, software
010 // distributed under the License is distributed on an "AS IS" BASIS,
011 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
012 // See the License for the specific language governing permissions and
013 // limitations under the License.
014 package org.apache.tapestry5.ioc.internal.services;
015
016 import java.lang.reflect.Method;
017 import java.util.List;
018
019 import javassist.bytecode.ConstPool;
020 import javassist.bytecode.annotation.Annotation;
021 import javassist.bytecode.annotation.AnnotationMemberValue;
022 import javassist.bytecode.annotation.ArrayMemberValue;
023 import javassist.bytecode.annotation.BooleanMemberValue;
024 import javassist.bytecode.annotation.ByteMemberValue;
025 import javassist.bytecode.annotation.CharMemberValue;
026 import javassist.bytecode.annotation.ClassMemberValue;
027 import javassist.bytecode.annotation.DoubleMemberValue;
028 import javassist.bytecode.annotation.EnumMemberValue;
029 import javassist.bytecode.annotation.FloatMemberValue;
030 import javassist.bytecode.annotation.IntegerMemberValue;
031 import javassist.bytecode.annotation.LongMemberValue;
032 import javassist.bytecode.annotation.MemberValue;
033 import javassist.bytecode.annotation.MemberValueVisitor;
034 import javassist.bytecode.annotation.ShortMemberValue;
035 import javassist.bytecode.annotation.StringMemberValue;
036
037 import org.apache.tapestry5.ioc.internal.util.CollectionFactory;
038
039 public class AnnotationMemberValueVisitor implements MemberValueVisitor
040 {
041 private final ConstPool constPool;
042
043 private final CtClassSource classSource;
044
045 private final Object value;
046
047 public AnnotationMemberValueVisitor(final ConstPool constPool, final CtClassSource classSource, final Object value)
048 {
049 this.constPool = constPool;
050 this.classSource = classSource;
051 this.value = value;
052 }
053
054 public void visitAnnotationMemberValue(final AnnotationMemberValue mb)
055 {
056 Class annotationType = getClass(value);
057
058 final Method[] methods = annotationType.getDeclaredMethods();
059
060 for (final Method method : methods)
061 {
062 try
063 {
064 final Object result = method.invoke(value);
065
066 final MemberValue memberValue = Annotation.createMemberValue(
067 this.constPool,
068 this.classSource.toCtClass(result.getClass()));
069
070 memberValue.accept(new AnnotationMemberValueVisitor(this.constPool, this.classSource, result));
071
072 mb.getValue().addMemberValue(method.getName(), memberValue);
073 }
074 catch (Exception e)
075 {
076 throw new RuntimeException(e);
077 }
078 }
079
080 }
081
082 public void visitArrayMemberValue(final ArrayMemberValue mb)
083 {
084 final Object[] array = (Object[]) this.value;
085
086 final List<MemberValue> members = CollectionFactory.newList();
087
088 for (final Object object : array)
089 {
090 try
091 {
092 final MemberValue memberValue = Annotation.createMemberValue(
093 this.constPool,
094 this.classSource.toCtClass(getClass(object)));
095
096 memberValue.accept(new AnnotationMemberValueVisitor(this.constPool, this.classSource, object));
097
098 members.add(memberValue);
099 }
100 catch (final Exception e)
101 {
102 throw new RuntimeException(e);
103 }
104 }
105
106 mb.setValue(members.toArray(new MemberValue[] {}));
107 }
108
109 private Class getClass(Object object)
110 {
111 if(object instanceof java.lang.annotation.Annotation)
112 {
113 return ((java.lang.annotation.Annotation)object).annotationType();
114 }
115
116 return object.getClass();
117 }
118
119 public void visitBooleanMemberValue(final BooleanMemberValue mb)
120 {
121 mb.setValue((Boolean) this.value);
122 }
123
124 public void visitByteMemberValue(final ByteMemberValue mb)
125 {
126 mb.setValue((Byte) this.value);
127 }
128
129 public void visitCharMemberValue(final CharMemberValue mb)
130 {
131 mb.setValue((Character) this.value);
132 }
133
134 public void visitDoubleMemberValue(final DoubleMemberValue mb)
135 {
136 mb.setValue((Double) this.value);
137 }
138
139 public void visitEnumMemberValue(final EnumMemberValue mb)
140 {
141 final Enum enumeration = (Enum) this.value;
142
143 final Class type = enumeration.getDeclaringClass();
144 mb.setType(type.getName());
145 mb.setValue(enumeration.name());
146 }
147
148 public void visitFloatMemberValue(final FloatMemberValue mb)
149 {
150 mb.setValue((Float) this.value);
151 }
152
153 public void visitIntegerMemberValue(final IntegerMemberValue mb)
154 {
155 mb.setValue((Integer) this.value);
156 }
157
158 public void visitLongMemberValue(final LongMemberValue mb)
159 {
160 mb.setValue((Long) this.value);
161 }
162
163 public void visitShortMemberValue(final ShortMemberValue mb)
164 {
165 mb.setValue((Short) this.value);
166 }
167
168 public void visitStringMemberValue(final StringMemberValue mb)
169 {
170 mb.setValue((String) this.value);
171 }
172
173 public void visitClassMemberValue(final ClassMemberValue mb)
174 {
175 mb.setValue(((Class) this.value).getName());
176 }
177
178 }