1 package org.apache.maven.shared.dependency.analyzer.asm;
2
3 /*
4 * Licensed to the Apache Software Foundation (ASF) under one
5 * or more contributor license agreements. See the NOTICE file
6 * distributed with this work for additional information
7 * regarding copyright ownership. The ASF licenses this file
8 * to you under the Apache License, Version 2.0 (the
9 * "License"); you may not use this file except in compliance
10 * with the License. You may obtain a copy of the License at
11 *
12 * http://www.apache.org/licenses/LICENSE-2.0
13 *
14 * Unless required by applicable law or agreed to in writing,
15 * software distributed under the License is distributed on an
16 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17 * KIND, either express or implied. See the License for the
18 * specific language governing permissions and limitations
19 * under the License.
20 */
21
22 import java.util.HashSet;
23 import java.util.Set;
24
25 import org.objectweb.asm.AnnotationVisitor;
26 import org.objectweb.asm.Attribute;
27 import org.objectweb.asm.ClassVisitor;
28 import org.objectweb.asm.FieldVisitor;
29 import org.objectweb.asm.Label;
30 import org.objectweb.asm.MethodVisitor;
31 import org.objectweb.asm.Type;
32 import org.objectweb.asm.signature.SignatureReader;
33 import org.objectweb.asm.signature.SignatureVisitor;
34
35 /**
36 * Inspired by <code>org.objectweb.asm.depend.DependencyVisitor</code> in the ASM dependencies example.
37 *
38 * @author <a href="mailto:markhobson@gmail.com">Mark Hobson</a>
39 * @version $Id: DependencyVisitor.java 661727 2008-05-30 14:21:49Z bentmann $
40 */
41 public class DependencyVisitor
42 implements AnnotationVisitor, SignatureVisitor, ClassVisitor, FieldVisitor, MethodVisitor
43 {
44 // fields -----------------------------------------------------------------
45
46 private final Set classes;
47
48 // constructors -----------------------------------------------------------
49
50 public DependencyVisitor()
51 {
52 classes = new HashSet();
53 }
54
55 // ClassVisitor methods ---------------------------------------------------
56
57 /*
58 * @see org.objectweb.asm.ClassVisitor#visit(int, int, java.lang.String, java.lang.String, java.lang.String,
59 * java.lang.String[])
60 */
61 public void visit( final int version, final int access, final String name, final String signature,
62 final String superName, final String[] interfaces )
63 {
64 if ( signature == null )
65 {
66 addName( superName );
67 addNames( interfaces );
68 }
69 else
70 {
71 addSignature( signature );
72 }
73 }
74
75 /*
76 * @see org.objectweb.asm.ClassVisitor#visitSource(java.lang.String, java.lang.String)
77 */
78 public void visitSource( final String source, final String debug )
79 {
80 // no-op
81 }
82
83 /*
84 * @see org.objectweb.asm.ClassVisitor#visitOuterClass(java.lang.String, java.lang.String, java.lang.String)
85 */
86 public void visitOuterClass( final String owner, final String name, final String desc )
87 {
88 // addName(owner);
89 // addMethodDesc(desc);
90 }
91
92 /*
93 * @see org.objectweb.asm.ClassVisitor#visitAnnotation(java.lang.String, boolean)
94 */
95 public AnnotationVisitor visitAnnotation( final String desc, final boolean visible )
96 {
97 addDesc( desc );
98
99 return this;
100 }
101
102 /*
103 * @see org.objectweb.asm.ClassVisitor#visitAttribute(org.objectweb.asm.Attribute)
104 */
105 public void visitAttribute( final Attribute attr )
106 {
107 // no-op
108 }
109
110 /*
111 * @see org.objectweb.asm.ClassVisitor#visitInnerClass(java.lang.String, java.lang.String, java.lang.String, int)
112 */
113 public void visitInnerClass( final String name, final String outerName, final String innerName, final int access )
114 {
115 // addName( outerName);
116 // addName( innerName);
117 }
118
119 /*
120 * @see org.objectweb.asm.ClassVisitor#visitField(int, java.lang.String, java.lang.String, java.lang.String,
121 * java.lang.Object)
122 */
123 public FieldVisitor visitField( final int access, final String name, final String desc, final String signature,
124 final Object value )
125 {
126 if ( signature == null )
127 addDesc( desc );
128 else
129 addTypeSignature( signature );
130
131 if ( value instanceof Type )
132 addType( (Type) value );
133
134 return this;
135 }
136
137 /*
138 * @see org.objectweb.asm.ClassVisitor#visitMethod(int, java.lang.String, java.lang.String, java.lang.String,
139 * java.lang.String[])
140 */
141 public MethodVisitor visitMethod( final int access, final String name, final String desc, final String signature,
142 final String[] exceptions )
143 {
144 if ( signature == null )
145 addMethodDesc( desc );
146 else
147 addSignature( signature );
148
149 addNames( exceptions );
150
151 return this;
152 }
153
154 // MethodVisitor methods --------------------------------------------------
155
156 /*
157 * @see org.objectweb.asm.MethodVisitor#visitAnnotationDefault()
158 */
159 public AnnotationVisitor visitAnnotationDefault()
160 {
161 return this;
162 }
163
164 /*
165 * @see org.objectweb.asm.MethodVisitor#visitParameterAnnotation(int, java.lang.String, boolean)
166 */
167 public AnnotationVisitor visitParameterAnnotation( final int parameter, final String desc, final boolean visible )
168 {
169 addDesc( desc );
170
171 return this;
172 }
173
174 /*
175 * @see org.objectweb.asm.MethodVisitor#visitCode()
176 */
177 public void visitCode()
178 {
179 // no-op
180 }
181
182 /*
183 * @see org.objectweb.asm.MethodVisitor#visitFrame(int, int, java.lang.Object[], int, java.lang.Object[])
184 */
185 public void visitFrame( final int type, final int nLocal, final Object[] local, final int nStack,
186 final Object[] stack )
187 {
188 // no-op
189 }
190
191 /*
192 * @see org.objectweb.asm.MethodVisitor#visitInsn(int)
193 */
194 public void visitInsn( final int opcode )
195 {
196 // no-op
197 }
198
199 /*
200 * @see org.objectweb.asm.MethodVisitor#visitIntInsn(int, int)
201 */
202 public void visitIntInsn( final int opcode, final int operand )
203 {
204 // no-op
205 }
206
207 /*
208 * @see org.objectweb.asm.MethodVisitor#visitVarInsn(int, int)
209 */
210 public void visitVarInsn( final int opcode, final int var )
211 {
212 // no-op
213 }
214
215 /*
216 * @see org.objectweb.asm.MethodVisitor#visitTypeInsn(int, java.lang.String)
217 */
218 public void visitTypeInsn( final int opcode, final String desc )
219 {
220 if ( desc.charAt( 0 ) == '[' )
221 addDesc( desc );
222 else
223 addName( desc );
224 }
225
226 /*
227 * @see org.objectweb.asm.MethodVisitor#visitFieldInsn(int, java.lang.String, java.lang.String, java.lang.String)
228 */
229 public void visitFieldInsn( final int opcode, final String owner, final String name, final String desc )
230 {
231 addName( owner );
232 addDesc( desc );
233 }
234
235 /*
236 * @see org.objectweb.asm.MethodVisitor#visitMethodInsn(int, java.lang.String, java.lang.String, java.lang.String)
237 */
238 public void visitMethodInsn( final int opcode, final String owner, final String name, final String desc )
239 {
240 addName( owner );
241 addMethodDesc( desc );
242 }
243
244 /*
245 * @see org.objectweb.asm.MethodVisitor#visitJumpInsn(int, org.objectweb.asm.Label)
246 */
247 public void visitJumpInsn( final int opcode, final Label label )
248 {
249 // no-op
250 }
251
252 /*
253 * @see org.objectweb.asm.MethodVisitor#visitLabel(org.objectweb.asm.Label)
254 */
255 public void visitLabel( final Label label )
256 {
257 // no-op
258 }
259
260 /*
261 * @see org.objectweb.asm.MethodVisitor#visitLdcInsn(java.lang.Object)
262 */
263 public void visitLdcInsn( final Object cst )
264 {
265 if ( cst instanceof Type )
266 addType( (Type) cst );
267 }
268
269 /*
270 * @see org.objectweb.asm.MethodVisitor#visitIincInsn(int, int)
271 */
272 public void visitIincInsn( final int var, final int increment )
273 {
274 // no-op
275 }
276
277 /*
278 * @see org.objectweb.asm.MethodVisitor#visitTableSwitchInsn(int, int, org.objectweb.asm.Label,
279 * org.objectweb.asm.Label[])
280 */
281 public void visitTableSwitchInsn( final int min, final int max, final Label dflt, final Label[] labels )
282 {
283 // no-op
284 }
285
286 /*
287 * @see org.objectweb.asm.MethodVisitor#visitLookupSwitchInsn(org.objectweb.asm.Label, int[],
288 * org.objectweb.asm.Label[])
289 */
290 public void visitLookupSwitchInsn( final Label dflt, final int[] keys, final Label[] labels )
291 {
292 // no-op
293 }
294
295 /*
296 * @see org.objectweb.asm.MethodVisitor#visitMultiANewArrayInsn(java.lang.String, int)
297 */
298 public void visitMultiANewArrayInsn( final String desc, final int dims )
299 {
300 addDesc( desc );
301 }
302
303 /*
304 * @see org.objectweb.asm.MethodVisitor#visitTryCatchBlock(org.objectweb.asm.Label, org.objectweb.asm.Label,
305 * org.objectweb.asm.Label, java.lang.String)
306 */
307 public void visitTryCatchBlock( final Label start, final Label end, final Label handler, final String type )
308 {
309 addName( type );
310 }
311
312 /*
313 * @see org.objectweb.asm.MethodVisitor#visitLocalVariable(java.lang.String, java.lang.String, java.lang.String,
314 * org.objectweb.asm.Label, org.objectweb.asm.Label, int)
315 */
316 public void visitLocalVariable( final String name, final String desc, final String signature, final Label start,
317 final Label end, final int index )
318 {
319 if ( signature == null )
320 {
321 addDesc( desc );
322 }
323 else
324 {
325 addTypeSignature( signature );
326 }
327 }
328
329 /*
330 * @see org.objectweb.asm.MethodVisitor#visitLineNumber(int, org.objectweb.asm.Label)
331 */
332 public void visitLineNumber( final int line, final Label start )
333 {
334 // no-op
335 }
336
337 /*
338 * @see org.objectweb.asm.MethodVisitor#visitMaxs(int, int)
339 */
340 public void visitMaxs( final int maxStack, final int maxLocals )
341 {
342 // no-op
343 }
344
345 // AnnotationVisitor methods ----------------------------------------------
346
347 /*
348 * @see org.objectweb.asm.AnnotationVisitor#visit(java.lang.String, java.lang.Object)
349 */
350 public void visit( final String name, final Object value )
351 {
352 if ( value instanceof Type )
353 addType( (Type) value );
354 }
355
356 /*
357 * @see org.objectweb.asm.AnnotationVisitor#visitEnum(java.lang.String, java.lang.String, java.lang.String)
358 */
359 public void visitEnum( final String name, final String desc, final String value )
360 {
361 addDesc( desc );
362 }
363
364 /*
365 * @see org.objectweb.asm.AnnotationVisitor#visitAnnotation(java.lang.String, java.lang.String)
366 */
367 public AnnotationVisitor visitAnnotation( final String name, final String desc )
368 {
369 addDesc( desc );
370
371 return this;
372 }
373
374 /*
375 * @see org.objectweb.asm.AnnotationVisitor#visitArray(java.lang.String)
376 */
377 public AnnotationVisitor visitArray( final String name )
378 {
379 return this;
380 }
381
382 /*
383 * @see org.objectweb.asm.AnnotationVisitor#visitEnd()
384 */
385 public void visitEnd()
386 {
387 // no-op
388 }
389
390 // SignatureVisitor methods -----------------------------------------------
391
392 /*
393 * @see org.objectweb.asm.signature.SignatureVisitor#visitFormalTypeParameter(java.lang.String)
394 */
395 public void visitFormalTypeParameter( final String name )
396 {
397 // no-op
398 }
399
400 /*
401 * @see org.objectweb.asm.signature.SignatureVisitor#visitClassBound()
402 */
403 public SignatureVisitor visitClassBound()
404 {
405 return this;
406 }
407
408 /*
409 * @see org.objectweb.asm.signature.SignatureVisitor#visitInterfaceBound()
410 */
411 public SignatureVisitor visitInterfaceBound()
412 {
413 return this;
414 }
415
416 /*
417 * @see org.objectweb.asm.signature.SignatureVisitor#visitSuperclass()
418 */
419 public SignatureVisitor visitSuperclass()
420 {
421 return this;
422 }
423
424 /*
425 * @see org.objectweb.asm.signature.SignatureVisitor#visitInterface()
426 */
427 public SignatureVisitor visitInterface()
428 {
429 return this;
430 }
431
432 /*
433 * @see org.objectweb.asm.signature.SignatureVisitor#visitParameterType()
434 */
435 public SignatureVisitor visitParameterType()
436 {
437 return this;
438 }
439
440 /*
441 * @see org.objectweb.asm.signature.SignatureVisitor#visitReturnType()
442 */
443 public SignatureVisitor visitReturnType()
444 {
445 return this;
446 }
447
448 /*
449 * @see org.objectweb.asm.signature.SignatureVisitor#visitExceptionType()
450 */
451 public SignatureVisitor visitExceptionType()
452 {
453 return this;
454 }
455
456 /*
457 * @see org.objectweb.asm.signature.SignatureVisitor#visitBaseType(char)
458 */
459 public void visitBaseType( final char descriptor )
460 {
461 // no-op
462 }
463
464 /*
465 * @see org.objectweb.asm.signature.SignatureVisitor#visitTypeVariable(java.lang.String)
466 */
467 public void visitTypeVariable( final String name )
468 {
469 // TODO: verify
470 }
471
472 /*
473 * @see org.objectweb.asm.signature.SignatureVisitor#visitArrayType()
474 */
475 public SignatureVisitor visitArrayType()
476 {
477 return this;
478 }
479
480 /*
481 * @see org.objectweb.asm.signature.SignatureVisitor#visitClassType(java.lang.String)
482 */
483 public void visitClassType( final String name )
484 {
485 addName( name );
486 }
487
488 /*
489 * @see org.objectweb.asm.signature.SignatureVisitor#visitInnerClassType(java.lang.String)
490 */
491 public void visitInnerClassType( final String name )
492 {
493 addName( name );
494 }
495
496 /*
497 * @see org.objectweb.asm.signature.SignatureVisitor#visitTypeArgument()
498 */
499 public void visitTypeArgument()
500 {
501 // no-op
502 }
503
504 /*
505 * @see org.objectweb.asm.signature.SignatureVisitor#visitTypeArgument(char)
506 */
507 public SignatureVisitor visitTypeArgument( final char wildcard )
508 {
509 return this;
510 }
511
512 // public methods ---------------------------------------------------------
513
514 public Set getClasses()
515 {
516 return classes;
517 }
518
519 // private methods --------------------------------------------------------
520
521 private void addName( String name )
522 {
523 if ( name == null )
524 return;
525
526 // decode arrays
527 if ( name.startsWith( "[L" ) && name.endsWith( ";" ) )
528 name = name.substring( 2, name.length() - 1 );
529
530 // decode internal representation
531 name = name.replace( '/', '.' );
532
533 classes.add( name );
534 }
535
536 private void addNames( final String[] names )
537 {
538 if ( names == null )
539 return;
540
541 for ( int i = 0; i < names.length; i++ )
542 addName( names[i] );
543 }
544
545 private void addDesc( final String desc )
546 {
547 addType( Type.getType( desc ) );
548 }
549
550 private void addMethodDesc( final String desc )
551 {
552 addType( Type.getReturnType( desc ) );
553
554 Type[] types = Type.getArgumentTypes( desc );
555
556 for ( int i = 0; i < types.length; i++ )
557 addType( types[i] );
558 }
559
560 private void addType( final Type t )
561 {
562 switch ( t.getSort() )
563 {
564 case Type.ARRAY:
565 addType( t.getElementType() );
566 break;
567
568 case Type.OBJECT:
569 addName( t.getClassName().replace( '.', '/' ) );
570 break;
571 }
572 }
573
574 private void addSignature( final String signature )
575 {
576 if ( signature != null )
577 new SignatureReader( signature ).accept( this );
578 }
579
580 private void addTypeSignature( final String signature )
581 {
582 if ( signature != null )
583 new SignatureReader( signature ).acceptType( this );
584 }
585 }