View Javadoc

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 }