summaryrefslogtreecommitdiffstats
path: root/sca-java-1.x/tags/1.6-TUSCANY-3909/implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/impl/JavaClassIntrospectorImpl.java
blob: 0bcec3c78fe318fdfa2ffcfd2b434b34c0726bb4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 * 
 *   http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.    
 */
package org.apache.tuscany.sca.implementation.java.impl;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.List;
import java.util.Set;

import org.apache.tuscany.sca.implementation.java.IntrospectionException;
import org.apache.tuscany.sca.implementation.java.JavaImplementation;
import org.apache.tuscany.sca.implementation.java.introspect.JavaClassVisitor;
import org.apache.tuscany.sca.implementation.java.introspect.impl.JavaIntrospectionHelper;

/**
 * An extensible Java class introspector implementation.
 * 
 * @version $Rev$ $Date$
 */
public class JavaClassIntrospectorImpl {
    
    private List<JavaClassVisitor> visitors;

    public JavaClassIntrospectorImpl(List<JavaClassVisitor> visitors) {
        this.visitors = visitors;
    }

    /**
     * JSR-250 PFD recommends the following guidelines for how annotations
     * interact with inheritance in order to keep the resulting complexity in
     * control:
     * <ol>
     * <li>Class-level annotations only affect the class they annotate and
     * their members, that is, its methods and fields. They never affect a
     * member declared by a superclass, even if it is not hidden or overridden
     * by the class in question.
     * <li>In addition to affecting the annotated class, class-level
     * annotations may act as a shorthand for member-level annotations. If a
     * member carries a specific member-level annotation, any annotations of the
     * same type implied by a class-level annotation are ignored. In other
     * words, explicit member-level annotations have priority over member-level
     * annotations implied by a class-level annotation.
     * <li>The interfaces implemented by a class never contribute annotations
     * to the class itself or any of its members.
     * <li>Members inherited from a superclass and which are not hidden or
     * overridden maintain the annotations they had in the class that declared
     * them, including member-level annotations implied by class-level ones.
     * <li>Member-level annotations on a hidden or overridden member are always
     * ignored.
     * </ol>
     */
    public void introspectClass(JavaImplementation type, Class<?> clazz)
        throws IntrospectionException {
        for (JavaClassVisitor extension : visitors) {
            extension.visitClass(clazz, type);
        }

        for (Constructor<?> constructor : clazz.getConstructors()) {
            for (JavaClassVisitor extension : visitors) {
                extension.visitConstructor(constructor, type);
                // Assuming the visitClass or visitConstructor will populate the
                // type.getConstructors
                JavaConstructorImpl<?> definition = type.getConstructors().get(constructor);
                if (definition != null) {
                    for (JavaParameterImpl p : definition.getParameters()) {
                        extension.visitConstructorParameter(p, type);
                    }
                }
            }
        }

        Set<Field> fields = JavaIntrospectionHelper.getAllPublicAndProtectedFields(clazz, true);
        for (Field field : fields) {
            for (JavaClassVisitor extension : visitors) {
                extension.visitField(field, type);
            }
        }

        // Check if any private fields have illegal annotations that should be raised as errors
        Set<Field> privateFields = JavaIntrospectionHelper.getPrivateFields(clazz);
        for (Field field : privateFields) {
            for (JavaClassVisitor processor : visitors) {
                processor.visitField(field, type);
            }
        }
        
        Set<Method> methods = JavaIntrospectionHelper.getAllUniquePublicProtectedMethods(clazz, true);
        for (Method method : methods) {
            for (JavaClassVisitor processor : visitors) {
                processor.visitMethod(method, type);
            }
        }

        // Check if any private methods have illegal annotations that should be raised as errors
        Set<Method> privateMethods = JavaIntrospectionHelper.getPrivateMethods(clazz);
        for (Method method : privateMethods) {
            for (JavaClassVisitor processor : visitors) {
                processor.visitMethod(method, type);
            }
        }

        Class superClass = clazz.getSuperclass();
        if (superClass != null) {
            visitSuperClass(superClass, type);
        }

        for (JavaClassVisitor extension : visitors) {
            extension.visitEnd(clazz, type);
        }
    }

    private void visitSuperClass(Class<?> clazz, JavaImplementation type) throws IntrospectionException {
        if (!Object.class.equals(clazz)) {
            for (JavaClassVisitor extension : visitors) {
                extension.visitSuperClass(clazz, type);
            }
            clazz = clazz.getSuperclass();
            if (clazz != null) {
                visitSuperClass(clazz, type);
            }
        }
    }

}