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 }