View Javadoc

1   package org.apache.onami.autobind.scanner.asm;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one or more
5    * contributor license agreements.  See the NOTICE file distributed with
6    * this work for additional information regarding copyright ownership.
7    * The ASF licenses this file to You under the Apache License, Version 2.0
8    * (the "License"); you may not use this file except in compliance with
9    * the License.  You may obtain a copy of the License at
10   *
11   *  http://www.apache.org/licenses/LICENSE-2.0
12   *
13   * Unless required by applicable law or agreed to in writing, software
14   * distributed under the License is distributed on an "AS IS" BASIS,
15   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16   * See the License for the specific language governing permissions and
17   * limitations under the License.
18   */
19  
20  import static java.util.Collections.unmodifiableList;
21  import static java.util.logging.Level.WARNING;
22  import static java.util.logging.Logger.getLogger;
23  import static org.objectweb.asm.ClassReader.SKIP_CODE;
24  import static org.objectweb.asm.ClassReader.SKIP_DEBUG;
25  import static org.objectweb.asm.ClassReader.SKIP_FRAMES;
26  import static org.objectweb.asm.Opcodes.ASM4;
27  
28  import java.lang.annotation.Annotation;
29  import java.util.HashMap;
30  import java.util.LinkedList;
31  import java.util.List;
32  import java.util.Map;
33  import java.util.logging.Logger;
34  
35  import org.apache.onami.autobind.scanner.features.ScannerFeature;
36  import org.objectweb.asm.AnnotationVisitor;
37  import org.objectweb.asm.ClassVisitor;
38  
39  /**
40   * Visitor implementation to collect field annotation information from class.
41   */
42  final class AnnotationCollector
43      extends ClassVisitor
44  {
45  
46      public static final int ASM_FLAGS = SKIP_CODE | SKIP_DEBUG | SKIP_FRAMES;
47  
48      private final Logger _logger = getLogger( getClass().getName() );
49  
50      private String _name;
51  
52      private Class<?> _class;
53  
54      private boolean _ignore;
55  
56      private final Map<String, Annotation> _annotations;
57  
58      private final List<ScannerFeature> _features;
59  
60      public AnnotationCollector()
61      {
62          super( ASM4 );
63          _features = new LinkedList<ScannerFeature>();
64          _annotations = new HashMap<String, Annotation>();
65      }
66  
67      public void addScannerFeature( ScannerFeature listener )
68      {
69          _features.add( listener );
70      }
71  
72      public void removerScannerFeature( ScannerFeature listener )
73      {
74          _features.remove( listener );
75      }
76  
77      public List<ScannerFeature> getScannerFeatures()
78      {
79          return unmodifiableList( _features );
80      }
81  
82      public void destroy()
83      {
84          _annotations.clear();
85          _class = null;
86          _features.clear();
87      }
88  
89      @Override
90      public void visit( int version, int access, String name, String signature, String superName, String[] interfaces )
91      {
92          _name = name.replace( '/', '.' );
93          for ( String interf : interfaces )
94          {
95              if ( interf.equals( "java/lang/annotation/Annotation" ) )
96              {
97                  _ignore = true;
98                  return;
99              }
100         }
101     }
102 
103     @SuppressWarnings( "unchecked" )
104     public AnnotationVisitor visitAnnotation( String sig, boolean visible )
105     {
106         if ( _ignore )
107         {
108             return null;
109         }
110         String annotationClassStr = sig.replace( '/', '.' ).substring( 1, sig.length() - 1 );
111         if ( _class == null )
112         {
113             try
114             {
115                 _class = Thread.currentThread().getContextClassLoader().loadClass( _name );
116             }
117             catch ( ClassNotFoundException e )
118             {
119                 _logger.log( WARNING, "Failure while visitAnnotation. Class could not be loaded.", e );
120                 return null;
121             }
122         }
123         try
124         {
125             Class<Annotation> annotationClass =
126                 (Class<Annotation>) getClass().getClassLoader().loadClass( annotationClassStr );
127             Annotation annotation = _class.getAnnotation( annotationClass );
128             _annotations.put( annotationClassStr, annotation );
129         }
130         catch ( ClassNotFoundException e )
131         {
132             e.printStackTrace();
133             _logger.log( WARNING, "Failure while visitAnnotation. Class could not be loaded.", e );
134         }
135 
136         return null;
137     }
138 
139     @SuppressWarnings( "unchecked" )
140     @Override
141     public void visitEnd()
142     {
143         if ( !_ignore && _annotations.size() > 0 && !_annotations.containsKey( "javax.enterprise.inject.Alternative" ) )
144         {
145             for ( ScannerFeature listener : _features )
146             {
147                 listener.found( (Class<Object>) _class, _annotations );
148             }
149         }
150         _name = null;
151         _class = null;
152         _ignore = false;
153         _annotations.clear();
154     }
155 
156 }