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