    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    }