View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements. See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership. The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License. You may obtain a copy of the License at
9    *
10   * http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied. See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.commons.weaver;
20  
21  import java.lang.annotation.Annotation;
22  import java.util.List;
23  import java.util.Map;
24  import java.util.function.Predicate;
25  import java.util.stream.Collectors;
26  
27  import org.apache.commons.weaver.model.ScanResult;
28  import org.apache.commons.weaver.model.WeavableClass;
29  import org.apache.commons.weaver.model.WeavableConstructor;
30  import org.apache.commons.weaver.model.WeavableConstructorParameter;
31  import org.apache.commons.weaver.model.WeavableField;
32  import org.apache.commons.weaver.model.WeavableMethod;
33  import org.apache.commons.weaver.model.WeavableMethodParameter;
34  import org.apache.commons.weaver.model.WeavablePackage;
35  import org.apache.xbean.finder.AnnotationFinder.ClassInfo;
36  import org.apache.xbean.finder.AnnotationFinder.FieldInfo;
37  import org.apache.xbean.finder.AnnotationFinder.Info;
38  import org.apache.xbean.finder.AnnotationFinder.MethodInfo;
39  import org.apache.xbean.finder.AnnotationFinder.PackageInfo;
40  import org.apache.xbean.finder.AnnotationFinder.ParameterInfo;
41  import org.apache.xbean.finder.Parameter;
42  
43  /**
44   * Adds all classfile annotations to a ScanResult.
45   */
46  class Inflater {
47      private class InfoMatcher implements Predicate<Info> {
48          final Class<? extends Info> type;
49  
50          InfoMatcher(final Class<? extends Info> type) {
51              super();
52              this.type = type;
53          }
54  
55          public boolean test(final Info info) {
56              return type.isInstance(info);
57          }
58      }
59  
60      private class MethodMatcher extends InfoMatcher {
61          final boolean isCtor;
62  
63          MethodMatcher(final boolean isCtor) {
64              super(MethodInfo.class);
65              this.isCtor = isCtor;
66          }
67  
68          @Override
69          public boolean test(final Info info) {
70              return super.test(info) && ((MethodInfo) info).isConstructor() == isCtor;
71          }
72      }
73  
74      private class ParameterMatcher extends InfoMatcher {
75          final boolean isCtor;
76  
77          ParameterMatcher(final boolean isCtor) {
78              super(ParameterInfo.class);
79              this.isCtor = isCtor;
80          }
81  
82          @Override
83          public boolean test(final Info info) {
84              return super.test(info) && ((ParameterInfo) info).getDeclaringMethod().isConstructor() == isCtor;
85          }
86      }
87  
88      final Map<PackageInfo, List<Annotation>> packageAnnotations;
89      final Map<ClassInfo, List<Annotation>> classAnnotations;
90      final Map<FieldInfo, List<Annotation>> fieldAnnotations;
91      final Map<MethodInfo, List<Annotation>> ctorAnnotations;
92      final Map<MethodInfo, List<Annotation>> methodAnnotations;
93      final Map<ParameterInfo, List<Annotation>> ctorParameterAnnotations;
94      final Map<ParameterInfo, List<Annotation>> methodParameterAnnotations;
95  
96      Inflater(final Map<Info, List<Annotation>> annotationMap) {
97          super();
98  
99          this.packageAnnotations = subMap(annotationMap, new InfoMatcher(PackageInfo.class));
100         this.classAnnotations = subMap(annotationMap, new InfoMatcher(ClassInfo.class));
101         this.fieldAnnotations = subMap(annotationMap, new InfoMatcher(FieldInfo.class));
102         this.ctorAnnotations = subMap(annotationMap, new MethodMatcher(true));
103         this.methodAnnotations = subMap(annotationMap, new MethodMatcher(false));
104         this.ctorParameterAnnotations = subMap(annotationMap, new ParameterMatcher(true));
105         this.methodParameterAnnotations = subMap(annotationMap, new ParameterMatcher(false));
106     }
107 
108     static <I extends Info> Map<I, List<Annotation>> subMap(final Map<Info, List<Annotation>> source,
109         final InfoMatcher matcher) {
110         @SuppressWarnings("unchecked")
111         final Map<I, List<Annotation>> result = source.entrySet().stream().filter(e -> matcher.test(e.getKey()))
112             .collect(Collectors.toMap(t -> (I) t.getKey(), Map.Entry::getValue));
113 
114         return result;
115     }
116 
117     ScanResult inflate(final ScanResult scanResult) {
118         for (final WeavablePackage pkg : scanResult.getPackages()) {
119             packageAnnotations.forEach((k, v) -> {
120                 if (k.getName().equals(pkg.getTarget().getName())) {
121                     pkg.addAnnotations(v);
122                 }
123             });
124             for (final WeavableClass<?> cls : pkg.getClasses()) {
125                 classAnnotations.forEach((k, v) -> {
126                     if (k.getName().equals(cls.getTarget().getName())) {
127                         cls.addAnnotations(v);
128                     }
129                 });
130                 for (final WeavableField<?> fld : cls.getFields()) {
131                     fieldAnnotations.forEach((k, v) -> {
132                         try {
133                             if (k.get().equals(fld.getTarget())) {
134                                 fld.addAnnotations(v);
135                             }
136                         } catch (final ClassNotFoundException ignored) {
137                         }
138                     });
139                 }
140                 for (final WeavableConstructor<?> ctor : cls.getConstructors()) {
141                     ctorAnnotations.forEach((k, v) -> {
142                         try {
143                             if (k.get().equals(ctor.getTarget())) {
144                                 ctor.addAnnotations(v);
145                             }
146                         } catch (final ClassNotFoundException ignored) {
147                         }
148                     });
149                     for (final WeavableConstructorParameter<?> param : ctor.getParameters()) {
150                         ctorParameterAnnotations.forEach((k, v) -> {
151                             try {
152                                 final Parameter<?> parameter = k.get();
153                                 if (parameter.getDeclaringExecutable().equals(ctor.getTarget())
154                                     && param.getTarget().intValue() == parameter.getIndex()) {
155                                     param.addAnnotations(v);
156                                 }
157                             } catch (final ClassNotFoundException ignored) {
158                             }
159                         });
160                     }
161                 }
162                 for (final WeavableMethod<?> methd : cls.getMethods()) {
163                     methodAnnotations.forEach((k, v) -> {
164                         try {
165                             if (k.get().equals(methd.getTarget())) {
166                                 methd.addAnnotations(v);
167                             }
168                         } catch (final ClassNotFoundException ignored) {
169                         }
170                     });
171                     for (final WeavableMethodParameter<?> param : methd.getParameters()) {
172                         methodParameterAnnotations.forEach((k, v) -> {
173                             try {
174                                 final Parameter<?> parameter = k.get();
175                                 if (parameter.getDeclaringExecutable().equals(methd.getTarget())
176                                     && param.getTarget().intValue() == parameter.getIndex()) {
177                                     param.addAnnotations(v);
178                                 }
179                             } catch (final ClassNotFoundException ignored) {
180                             }
181                         });
182                     }
183                 }
184             }
185         }
186         return scanResult;
187     }
188 }