EMMA Coverage Report (generated Thu Dec 06 15:52:10 GMT 2007)
[all classes][com.sun.tools.javac.model]

COVERAGE SUMMARY FOR SOURCE FILE [AnnotationProxyMaker.java]

nameclass, %method, %block, %line, %
AnnotationProxyMaker.java0%   (0/5)0%   (0/29)0%   (0/491)0%   (0/105)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class AnnotationProxyMaker0%   (0/1)0%   (0/7)0%   (0/140)0%   (0/29)
AnnotationProxyMaker (Attribute$Compound, Class): void 0%   (0/1)0%   (0/9)0%   (0/4)
access$000 (AnnotationProxyMaker): Class 0%   (0/1)0%   (0/3)0%   (0/1)
generateAnnotation (): Annotation 0%   (0/1)0%   (0/6)0%   (0/1)
generateAnnotation (Attribute$Compound, Class): Annotation 0%   (0/1)0%   (0/12)0%   (0/2)
generateValue (Symbol$MethodSymbol, Attribute): Object 0%   (0/1)0%   (0/10)0%   (0/2)
getAllReflectedValues (): Map 0%   (0/1)0%   (0/39)0%   (0/8)
getAllValues (): Map 0%   (0/1)0%   (0/61)0%   (0/11)
     
class AnnotationProxyMaker$MirroredTypeExceptionProxy0%   (0/1)0%   (0/5)0%   (0/46)0%   (0/8)
AnnotationProxyMaker$MirroredTypeExceptionProxy (TypeMirror): void 0%   (0/1)0%   (0/10)0%   (0/4)
equals (Object): boolean 0%   (0/1)0%   (0/17)0%   (0/1)
generateException (): RuntimeException 0%   (0/1)0%   (0/6)0%   (0/1)
hashCode (): int 0%   (0/1)0%   (0/10)0%   (0/1)
toString (): String 0%   (0/1)0%   (0/3)0%   (0/1)
     
class AnnotationProxyMaker$MirroredTypesExceptionProxy0%   (0/1)0%   (0/5)0%   (0/46)0%   (0/8)
AnnotationProxyMaker$MirroredTypesExceptionProxy (List): void 0%   (0/1)0%   (0/10)0%   (0/4)
equals (Object): boolean 0%   (0/1)0%   (0/17)0%   (0/1)
generateException (): RuntimeException 0%   (0/1)0%   (0/6)0%   (0/1)
hashCode (): int 0%   (0/1)0%   (0/10)0%   (0/1)
toString (): String 0%   (0/1)0%   (0/3)0%   (0/1)
     
class AnnotationProxyMaker$ValueVisitor0%   (0/1)0%   (0/9)0%   (0/235)0%   (0/58)
AnnotationProxyMaker$ValueVisitor (AnnotationProxyMaker, Symbol$MethodSymbol)... 0%   (0/1)0%   (0/9)0%   (0/3)
getValue (Attribute): Object 0%   (0/1)0%   (0/40)0%   (0/9)
typeMismatch (Method, Attribute): void 0%   (0/1)0%   (0/9)0%   (0/2)
visitArray (Attribute$Array): void 0%   (0/1)0%   (0/115)0%   (0/23)
visitClass (Attribute$Class): void 0%   (0/1)0%   (0/8)0%   (0/2)
visitCompound (Attribute$Compound): void 0%   (0/1)0%   (0/16)0%   (0/6)
visitConstant (Attribute$Constant): void 0%   (0/1)0%   (0/5)0%   (0/2)
visitEnum (Attribute$Enum): void 0%   (0/1)0%   (0/29)0%   (0/9)
visitError (Attribute$Error): void 0%   (0/1)0%   (0/4)0%   (0/2)
     
class AnnotationProxyMaker$ValueVisitor$10%   (0/1)0%   (0/3)0%   (0/24)0%   (0/3)
AnnotationProxyMaker$ValueVisitor$1 (AnnotationProxyMaker$ValueVisitor, Metho... 0%   (0/1)0%   (0/12)0%   (0/1)
generateException (): RuntimeException 0%   (0/1)0%   (0/10)0%   (0/1)
toString (): String 0%   (0/1)0%   (0/2)0%   (0/1)

1/*
2 * Copyright 2005-2006 Sun Microsystems, Inc.  All Rights Reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.  Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any questions.
24 */
25 
26package com.sun.tools.javac.model;
27 
28import com.sun.tools.javac.util.*;
29import java.lang.annotation.*;
30import java.lang.reflect.Array;
31import java.lang.reflect.Method;
32import java.util.LinkedHashMap;
33import java.util.Map;
34import sun.reflect.annotation.*;
35 
36import javax.lang.model.type.TypeMirror;
37import javax.lang.model.type.MirroredTypeException;
38import javax.lang.model.type.MirroredTypesException;
39import com.sun.tools.javac.code.*;
40import com.sun.tools.javac.code.Symbol.*;
41import com.sun.tools.javac.code.Type.ArrayType;
42 
43 
44/**
45 * A generator of dynamic proxy implementations of
46 * java.lang.annotation.Annotation.
47 *
48 * <p> The "dynamic proxy return form" of an annotation element value is
49 * the form used by sun.reflect.annotation.AnnotationInvocationHandler.
50 *
51 * <p><b>This is NOT part of any API supported by Sun Microsystems.  If
52 * you write code that depends on this, you do so at your own risk.
53 * This code and its internal interfaces are subject to change or
54 * deletion without notice.</b>
55 */
56 
57public class AnnotationProxyMaker {
58 
59    private final Attribute.Compound anno;
60    private final Class<? extends Annotation> annoType;
61 
62 
63    private AnnotationProxyMaker(Attribute.Compound anno,
64                                 Class<? extends Annotation> annoType) {
65        this.anno = anno;
66        this.annoType = annoType;
67    }
68 
69 
70    /**
71     * Returns a dynamic proxy for an annotation mirror.
72     */
73    public static <A extends Annotation> A generateAnnotation(
74            Attribute.Compound anno, Class<A> annoType) {
75        AnnotationProxyMaker apm = new AnnotationProxyMaker(anno, annoType);
76        return annoType.cast(apm.generateAnnotation());
77    }
78 
79 
80    /**
81     * Returns a dynamic proxy for an annotation mirror.
82     */
83    private Annotation generateAnnotation() {
84        return AnnotationParser.annotationForMap(annoType,
85                                                 getAllReflectedValues());
86    }
87 
88    /**
89     * Returns a map from element names to their values in "dynamic
90     * proxy return form".  Includes all elements, whether explicit or
91     * defaulted.
92     */
93    private Map<String, Object> getAllReflectedValues() {
94        Map<String, Object> res = new LinkedHashMap<String, Object>();
95 
96        for (Map.Entry<MethodSymbol, Attribute> entry :
97                                                  getAllValues().entrySet()) {
98            MethodSymbol meth = entry.getKey();
99            Object value = generateValue(meth, entry.getValue());
100            if (value != null) {
101                res.put(meth.name.toString(), value);
102            } else {
103                // Ignore this element.  May (properly) lead to
104                // IncompleteAnnotationException somewhere down the line.
105            }
106        }
107        return res;
108    }
109 
110    /**
111     * Returns a map from element symbols to their values.
112     * Includes all elements, whether explicit or defaulted.
113     */
114    private Map<MethodSymbol, Attribute> getAllValues() {
115        Map<MethodSymbol, Attribute> res =
116            new LinkedHashMap<MethodSymbol, Attribute>();
117 
118        // First find the default values.
119        ClassSymbol sym = (ClassSymbol) anno.type.tsym;
120        for (Scope.Entry e = sym.members().elems; e != null; e = e.sibling) {
121            if (e.sym.kind == Kinds.MTH) {
122                MethodSymbol m = (MethodSymbol) e.sym;
123                Attribute def = m.getDefaultValue();
124                if (def != null)
125                    res.put(m, def);
126            }
127        }
128        // Next find the explicit values, possibly overriding defaults.
129        for (Pair<MethodSymbol, Attribute> p : anno.values)
130            res.put(p.fst, p.snd);
131        return res;
132    }
133 
134    /**
135     * Converts an element value to its "dynamic proxy return form".
136     * Returns an exception proxy on some errors, but may return null if
137     * a useful exception cannot or should not be generated at this point.
138     */
139    private Object generateValue(MethodSymbol meth, Attribute attr) {
140        ValueVisitor vv = new ValueVisitor(meth);
141        return vv.getValue(attr);
142    }
143 
144 
145    private class ValueVisitor implements Attribute.Visitor {
146 
147        private MethodSymbol meth;      // annotation element being visited
148        private Class<?> returnClass;   // return type of annotation element
149        private Object value;           // value in "dynamic proxy return form"
150 
151        ValueVisitor(MethodSymbol meth) {
152            this.meth = meth;
153        }
154 
155        Object getValue(Attribute attr) {
156            Method method;              // runtime method of annotation element
157            try {
158                method = annoType.getMethod(meth.name.toString());
159            } catch (NoSuchMethodException e) {
160                return null;
161            }
162            returnClass = method.getReturnType();
163            attr.accept(this);
164            if (!(value instanceof ExceptionProxy) &&
165                !AnnotationType.invocationHandlerReturnType(returnClass)
166                                                        .isInstance(value)) {
167                typeMismatch(method, attr);
168            }
169            return value;
170        }
171 
172 
173        public void visitConstant(Attribute.Constant c) {
174            value = c.getValue();
175        }
176 
177        public void visitClass(Attribute.Class c) {
178            value = new MirroredTypeExceptionProxy(c.type);
179        }
180 
181        public void visitArray(Attribute.Array a) {
182            Name elemName = ((ArrayType) a.type).elemtype.tsym.name;
183 
184            if (elemName == elemName.table.java_lang_Class) {   // Class[]
185                // Construct a proxy for a MirroredTypesException
186                List<TypeMirror> elems = List.nil();
187                for (Attribute value : a.values) {
188                    Type elem = ((Attribute.Class) value).type;
189                    elems.add(elem);
190                }
191                value = new MirroredTypesExceptionProxy(elems);
192 
193            } else {
194                int len = a.values.length;
195                Class<?> returnClassSaved = returnClass;
196                returnClass = returnClass.getComponentType();
197                try {
198                    Object res = Array.newInstance(returnClass, len);
199                    for (int i = 0; i < len; i++) {
200                        a.values[i].accept(this);
201                        if (value == null || value instanceof ExceptionProxy) {
202                            return;
203                        }
204                        try {
205                            Array.set(res, i, value);
206                        } catch (IllegalArgumentException e) {
207                            value = null;       // indicates a type mismatch
208                            return;
209                        }
210                    }
211                    value = res;
212                } finally {
213                    returnClass = returnClassSaved;
214                }
215            }
216        }
217 
218        @SuppressWarnings("unchecked")
219        public void visitEnum(Attribute.Enum e) {
220            if (returnClass.isEnum()) {
221                String constName = e.value.toString();
222                try {
223                    value = Enum.valueOf((Class) returnClass, constName);
224                } catch (IllegalArgumentException ex) {
225                    value = new EnumConstantNotPresentExceptionProxy(
226                                        (Class) returnClass, constName);
227                }
228            } else {
229                value = null;   // indicates a type mismatch
230            }
231        }
232 
233        public void visitCompound(Attribute.Compound c) {
234            try {
235                Class<? extends Annotation> nested =
236                    returnClass.asSubclass(Annotation.class);
237                value = generateAnnotation(c, nested);
238            } catch (ClassCastException ex) {
239                value = null;   // indicates a type mismatch
240            }
241        }
242 
243        public void visitError(Attribute.Error e) {
244            value = null;       // indicates a type mismatch
245        }
246 
247 
248        /**
249         * Sets "value" to an ExceptionProxy indicating a type mismatch.
250         */
251        private void typeMismatch(final Method method, final Attribute attr) {
252            value = new ExceptionProxy() {
253                static final long serialVersionUID = 269;
254                public String toString() {
255                    return "<error>";   // eg:  @Anno(value=<error>)
256                }
257                protected RuntimeException generateException() {
258                    return new AnnotationTypeMismatchException(method,
259                                attr.type.toString());
260                }
261            };
262        }
263    }
264 
265 
266    /**
267     * ExceptionProxy for MirroredTypeException.
268     * The toString, hashCode, and equals methods foward to the underlying
269     * type.
270     */
271    private static class MirroredTypeExceptionProxy extends ExceptionProxy {
272        static final long serialVersionUID = 269;
273 
274        private transient final TypeMirror type;
275        private final String typeString;
276 
277        MirroredTypeExceptionProxy(TypeMirror t) {
278            type = t;
279            typeString = t.toString();
280        }
281 
282        public String toString() {
283            return typeString;
284        }
285 
286        public int hashCode() {
287            return (type != null ? type : typeString).hashCode();
288        }
289 
290        public boolean equals(Object obj) {
291            return type != null &&
292                   obj instanceof MirroredTypeExceptionProxy &&
293                   type.equals(((MirroredTypeExceptionProxy) obj).type);
294        }
295 
296        protected RuntimeException generateException() {
297            return new MirroredTypeException(type);
298        }
299    }
300 
301 
302    /**
303     * ExceptionProxy for MirroredTypesException.
304     * The toString, hashCode, and equals methods foward to the underlying
305     * types.
306     */
307    private static class MirroredTypesExceptionProxy extends ExceptionProxy {
308        static final long serialVersionUID = 269;
309 
310        private transient final List<TypeMirror> types;
311        private final String typeStrings;
312 
313        MirroredTypesExceptionProxy(List<TypeMirror> ts) {
314            types = ts;
315            typeStrings = ts.toString();
316        }
317 
318        public String toString() {
319            return typeStrings;
320        }
321 
322        public int hashCode() {
323            return (types != null ? types : typeStrings).hashCode();
324        }
325 
326        public boolean equals(Object obj) {
327            return types != null &&
328                   obj instanceof MirroredTypesExceptionProxy &&
329                   types.equals(
330                      ((MirroredTypesExceptionProxy) obj).types);
331        }
332 
333        protected RuntimeException generateException() {
334            return new MirroredTypesException(types);
335        }
336    }
337}

[all classes][com.sun.tools.javac.model]
EMMA 2.0.5312 (C) Vladimir Roubtsov