1 package org.apache.maven.tools.plugin.annotations.scanner;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import org.apache.maven.artifact.Artifact;
23 import org.apache.maven.plugins.annotations.Component;
24 import org.apache.maven.plugins.annotations.Execute;
25 import org.apache.maven.plugins.annotations.Mojo;
26 import org.apache.maven.plugins.annotations.Parameter;
27 import org.apache.maven.tools.plugin.annotations.datamodel.ComponentAnnotationContent;
28 import org.apache.maven.tools.plugin.annotations.datamodel.ExecuteAnnotationContent;
29 import org.apache.maven.tools.plugin.annotations.datamodel.MojoAnnotationContent;
30 import org.apache.maven.tools.plugin.annotations.datamodel.ParameterAnnotationContent;
31 import org.apache.maven.tools.plugin.annotations.scanner.visitors.MojoAnnotationVisitor;
32 import org.apache.maven.tools.plugin.annotations.scanner.visitors.MojoClassVisitor;
33 import org.apache.maven.tools.plugin.annotations.scanner.visitors.MojoFieldVisitor;
34 import org.apache.maven.tools.plugin.extractor.ExtractionException;
35 import org.codehaus.plexus.logging.AbstractLogEnabled;
36 import org.codehaus.plexus.util.DirectoryScanner;
37 import org.codehaus.plexus.util.IOUtil;
38 import org.codehaus.plexus.util.StringUtils;
39 import org.codehaus.plexus.util.reflection.Reflector;
40 import org.objectweb.asm.ClassReader;
41 import org.objectweb.asm.Type;
42
43 import java.io.BufferedInputStream;
44 import java.io.File;
45 import java.io.FileInputStream;
46 import java.io.IOException;
47 import java.io.InputStream;
48 import java.util.Collections;
49 import java.util.HashMap;
50 import java.util.List;
51 import java.util.Map;
52 import java.util.zip.ZipEntry;
53 import java.util.zip.ZipInputStream;
54
55
56
57
58
59 @org.codehaus.plexus.component.annotations.Component( role = MojoAnnotationsScanner.class )
60 public class DefaultMojoAnnotationsScanner
61 extends AbstractLogEnabled
62 implements MojoAnnotationsScanner
63 {
64 private Reflector reflector = new Reflector();
65
66 public Map<String, MojoAnnotatedClass> scan( MojoAnnotationsScannerRequest request )
67 throws ExtractionException
68 {
69 Map<String, MojoAnnotatedClass> mojoAnnotatedClasses = new HashMap<String, MojoAnnotatedClass>();
70 try
71 {
72
73 for ( Artifact dependency : request.getDependencies() )
74 {
75 File dependencyFile = dependency.getFile();
76 if ( dependencyFile != null && dependencyFile.exists() )
77 {
78 if ( dependencyFile.isDirectory() )
79 {
80 mojoAnnotatedClasses.putAll(
81 scanDirectory( dependencyFile, request.getIncludePatterns(), dependency, true ) );
82 }
83 else
84 {
85 mojoAnnotatedClasses.putAll(
86 scanFile( dependencyFile, request.getIncludePatterns(), dependency, true ) );
87 }
88 }
89 }
90
91 for ( File classDirectory : request.getClassesDirectories() )
92 {
93 if ( classDirectory.exists() && classDirectory.isDirectory() )
94 {
95 mojoAnnotatedClasses.putAll(
96 scanDirectory( classDirectory, request.getIncludePatterns(), request.getProject().getArtifact(),
97 false ) );
98 }
99 }
100
101 return mojoAnnotatedClasses;
102 }
103 catch ( IOException e )
104 {
105 throw new ExtractionException( e.getMessage(), e );
106 }
107 }
108
109
110
111
112
113
114
115
116
117
118 protected Map<String, MojoAnnotatedClass> scanFile( File archiveFile, List<String> includePatterns,
119 Artifact artifact, boolean excludeMojo )
120 throws IOException, ExtractionException
121 {
122 if ( !archiveFile.exists() )
123 {
124 return Collections.emptyMap();
125 }
126 Map<String, MojoAnnotatedClass> mojoAnnotatedClasses = new HashMap<String, MojoAnnotatedClass>();
127 ZipInputStream archiveStream = new ZipInputStream( new FileInputStream( archiveFile ) );
128
129 try
130 {
131 for ( ZipEntry zipEntry = archiveStream.getNextEntry(); zipEntry != null;
132 zipEntry = archiveStream.getNextEntry() )
133 {
134 if ( zipEntry.getName().endsWith( ".class" ) )
135 {
136 MojoClassVisitor mojoClassVisitor = new MojoClassVisitor( getLogger() );
137
138 ClassReader rdr = new ClassReader( archiveStream );
139 rdr.accept( mojoClassVisitor,
140 ClassReader.SKIP_FRAMES | ClassReader.SKIP_CODE | ClassReader.SKIP_DEBUG );
141 analyzeVisitors( mojoClassVisitor );
142 if ( excludeMojo )
143 {
144 mojoClassVisitor.getMojoAnnotatedClass().setMojo( null );
145 }
146 if ( isStoreClass( mojoClassVisitor.getMojoAnnotatedClass() ) != null )
147 {
148 getLogger().debug(
149 "found MojoAnnotatedClass:" + mojoClassVisitor.getMojoAnnotatedClass().getClassName() + ":"
150 + mojoClassVisitor.getMojoAnnotatedClass() );
151 mojoClassVisitor.getMojoAnnotatedClass().setArtifact( artifact );
152 mojoAnnotatedClasses.put( mojoClassVisitor.getMojoAnnotatedClass().getClassName(),
153 mojoClassVisitor.getMojoAnnotatedClass() );
154 }
155 }
156 }
157 }
158 finally
159 {
160 IOUtil.close( archiveStream );
161 }
162 return mojoAnnotatedClasses;
163 }
164
165
166
167
168
169
170
171
172
173
174 protected Map<String, MojoAnnotatedClass> scanDirectory( File classDirectory, List<String> includePatterns,
175 Artifact artifact, boolean excludeMojo )
176 throws IOException, ExtractionException
177 {
178 if ( !classDirectory.exists() )
179 {
180 return Collections.emptyMap();
181 }
182 Map<String, MojoAnnotatedClass> mojoAnnotatedClasses = new HashMap<String, MojoAnnotatedClass>();
183 DirectoryScanner scanner = new DirectoryScanner();
184 scanner.setBasedir( classDirectory );
185 scanner.addDefaultExcludes();
186 if ( includePatterns != null )
187 {
188 scanner.setIncludes( includePatterns.toArray( new String[includePatterns.size()] ) );
189 }
190 scanner.scan();
191 String[] classFiles = scanner.getIncludedFiles();
192
193 for ( String classFile : classFiles )
194 {
195 InputStream is = new BufferedInputStream( new FileInputStream( new File( classDirectory, classFile ) ) );
196 try
197 {
198
199 if ( classFile.endsWith( ".class" ) )
200 {
201 MojoClassVisitor mojoClassVisitor = new MojoClassVisitor( getLogger() );
202 ClassReader rdr = new ClassReader( is );
203 rdr.accept( mojoClassVisitor,
204 ClassReader.SKIP_FRAMES | ClassReader.SKIP_CODE | ClassReader.SKIP_DEBUG );
205 analyzeVisitors( mojoClassVisitor );
206 if ( excludeMojo )
207 {
208 mojoClassVisitor.getMojoAnnotatedClass().setMojo( null );
209 }
210 if ( isStoreClass( mojoClassVisitor.getMojoAnnotatedClass() ) != null )
211 {
212 getLogger().debug(
213 "found MojoAnnotatedClass:" + mojoClassVisitor.getMojoAnnotatedClass().getClassName() + ":"
214 + mojoClassVisitor.getMojoAnnotatedClass() );
215 mojoClassVisitor.getMojoAnnotatedClass().setArtifact( artifact );
216 mojoAnnotatedClasses.put( mojoClassVisitor.getMojoAnnotatedClass().getClassName(),
217 mojoClassVisitor.getMojoAnnotatedClass() );
218 }
219
220 }
221 }
222 finally
223 {
224 IOUtil.close( is );
225 }
226
227 }
228 return mojoAnnotatedClasses;
229 }
230
231 private MojoAnnotatedClass isStoreClass( MojoAnnotatedClass mojoAnnotatedClass )
232 {
233
234 if ( mojoAnnotatedClass == null )
235 {
236 return null;
237 }
238 return mojoAnnotatedClass;
239
240
241
242
243
244
245
246
247 }
248
249
250 protected void analyzeVisitors( MojoClassVisitor mojoClassVisitor )
251 throws ExtractionException
252 {
253
254 try
255 {
256 MojoAnnotationVisitor mojoAnnotationVisitor =
257 mojoClassVisitor.getAnnotationVisitorMap().get( Mojo.class.getName() );
258 if ( mojoAnnotationVisitor != null )
259 {
260 MojoAnnotationContent mojoAnnotationContent = new MojoAnnotationContent();
261 for ( Map.Entry<String, Object> entry : mojoAnnotationVisitor.getAnnotationValues().entrySet() )
262 {
263 reflector.invoke( mojoAnnotationContent, entry.getKey(), new Object[]{ entry.getValue() } );
264 }
265 mojoClassVisitor.getMojoAnnotatedClass().setMojo( mojoAnnotationContent );
266 }
267
268 mojoAnnotationVisitor = mojoClassVisitor.getAnnotationVisitorMap().get( Execute.class.getName() );
269 if ( mojoAnnotationVisitor != null )
270 {
271 ExecuteAnnotationContent executeAnnotationContent = new ExecuteAnnotationContent();
272
273 for ( Map.Entry<String, Object> entry : mojoAnnotationVisitor.getAnnotationValues().entrySet() )
274 {
275 reflector.invoke( executeAnnotationContent, entry.getKey(), new Object[]{ entry.getValue() } );
276 }
277 mojoClassVisitor.getMojoAnnotatedClass().setExecute( executeAnnotationContent );
278 }
279
280 List<MojoFieldVisitor> mojoFieldVisitors =
281 mojoClassVisitor.findFieldWithAnnotationClass( Parameter.class.getName() );
282
283 for ( MojoFieldVisitor mojoFieldVisitor : mojoFieldVisitors )
284 {
285 ParameterAnnotationContent parameterAnnotationContent =
286 new ParameterAnnotationContent( mojoFieldVisitor.getFieldName(), mojoFieldVisitor.getClassName() );
287 if ( mojoFieldVisitor.getMojoAnnotationVisitor() != null )
288 {
289 for ( Map.Entry<String, Object> entry : mojoFieldVisitor.getMojoAnnotationVisitor().getAnnotationValues().entrySet() )
290 {
291 reflector.invoke( parameterAnnotationContent, entry.getKey(),
292 new Object[]{ entry.getValue() } );
293 }
294
295 }
296 mojoClassVisitor.getMojoAnnotatedClass().getParameters().put( parameterAnnotationContent.getFieldName(),
297 parameterAnnotationContent );
298 }
299
300 mojoFieldVisitors = mojoClassVisitor.findFieldWithAnnotationClass( Component.class.getName() );
301
302 for ( MojoFieldVisitor mojoFieldVisitor : mojoFieldVisitors )
303 {
304 ComponentAnnotationContent componentAnnotationContent =
305 new ComponentAnnotationContent( mojoFieldVisitor.getFieldName() );
306
307 if ( mojoFieldVisitor.getMojoAnnotationVisitor() != null )
308 {
309 for ( Map.Entry<String, Object> entry : mojoFieldVisitor.getMojoAnnotationVisitor().getAnnotationValues().entrySet() )
310 {
311 String methodName = entry.getKey();
312 if ( StringUtils.equals( "role", methodName ) )
313 {
314 Type type = (Type) entry.getValue();
315 componentAnnotationContent.setRoleClassName( type.getClassName() );
316 }
317 else
318 {
319 reflector.invoke( componentAnnotationContent, entry.getKey(),
320 new Object[]{ entry.getValue() } );
321 }
322 }
323 if ( StringUtils.isEmpty( componentAnnotationContent.getRoleClassName() ) )
324 {
325 componentAnnotationContent.setRoleClassName( mojoFieldVisitor.getClassName() );
326 }
327 }
328 mojoClassVisitor.getMojoAnnotatedClass().getComponents().put( componentAnnotationContent.getFieldName(),
329 componentAnnotationContent );
330 }
331
332 }
333 catch ( Exception e )
334 {
335 throw new ExtractionException( e.getMessage(), e );
336 }
337 }
338 }