1 18 package org.apache.beehive.netui.compiler; 19 20 import org.apache.beehive.netui.compiler.typesystem.declaration.*; 21 import org.apache.beehive.netui.compiler.typesystem.env.AnnotationProcessorEnvironment; 22 import org.apache.beehive.netui.compiler.typesystem.env.Filer; 23 import org.apache.beehive.netui.compiler.typesystem.env.Messager; 24 import org.apache.beehive.netui.compiler.typesystem.type.ArrayType; 25 import org.apache.beehive.netui.compiler.typesystem.type.ClassType; 26 import org.apache.beehive.netui.compiler.typesystem.type.DeclaredType; 27 import org.apache.beehive.netui.compiler.typesystem.type.InterfaceType; 28 import org.apache.beehive.netui.compiler.typesystem.type.ReferenceType; 29 import org.apache.beehive.netui.compiler.typesystem.type.TypeInstance; 30 import org.apache.beehive.netui.compiler.typesystem.type.TypeVariable; 31 import org.apache.beehive.netui.compiler.typesystem.util.SourcePosition; 32 33 import java.io.File ; 34 import java.net.URI ; 35 import java.net.URISyntaxException ; 36 import java.util.ArrayList ; 37 import java.util.Collection ; 38 import java.util.Collections ; 39 import java.util.Iterator ; 40 import java.util.List ; 41 import java.util.Map ; 42 import java.util.Set ; 43 import java.util.HashMap ; 44 45 46 public class CompilerUtils 47 implements JpfLanguageConstants 48 { 49 private static final String ERROR_STRING = "<error>"; 50 private static final TypeDeclaration ERROR_TYPE_DECLARATION = new ErrorTypeDeclaration(); 51 52 public static boolean isJpfAnnotation( AnnotationInstance annotation, String unqualifiedName ) 53 { 54 String annotationName = getDeclaration( annotation.getAnnotationType() ).getQualifiedName(); 55 return annotationName.equals( ANNOTATION_QUALIFIER + unqualifiedName ); 56 } 57 58 public static AnnotationInstance getAnnotation( Declaration element, String unqualifiedName ) 59 { 60 return getAnnotationFullyQualified( element, ANNOTATION_QUALIFIER + unqualifiedName ); 61 } 62 63 public static AnnotationInstance getAnnotationFullyQualified( Declaration element, String fullyQualifiedName ) 64 { 65 AnnotationInstance[] annotations = element.getAnnotationInstances(); 66 67 for ( int ii = 0; ii < annotations.length; ii++ ) 68 { 69 AnnotationInstance i = annotations[ii]; 70 String iName = getDeclaration( i.getAnnotationType() ).getQualifiedName(); 71 if ( fullyQualifiedName.equals( iName ) ) return i; 72 } 73 74 return null; 75 } 76 77 public static AnnotationValue getAnnotationValue( Declaration element, String annotationName, String valueName ) 78 { 79 AnnotationInstance ann = getAnnotation( element, annotationName ); 80 return ann != null ? getAnnotationValue( ann, valueName, true ) : null; 81 } 82 83 87 private static AnnotationValue assertAnnotationValue( Declaration element, String annotationName, String valueName, 88 boolean defaultIsNull ) 89 { 90 AnnotationInstance ann = getAnnotation( element, annotationName ); 91 92 if ( ann == null ) 93 { 94 return null; 95 } 96 else 97 { 98 return getAnnotationValue( ann, valueName, defaultIsNull ); 99 } 100 } 101 102 public static String getStringValue( Declaration element, String annotationName, String memberName, 103 boolean defaultIsNull ) 104 { 105 return ( String ) getValue( element, annotationName, memberName, defaultIsNull ); 106 } 107 108 public static AnnotationValue getAnnotationValue( AnnotationInstance annotation, String memberName, 109 boolean defaultIsNull ) 110 { 111 Map valuesPresent = annotation.getElementValues(); 112 113 for ( Iterator ii = valuesPresent.entrySet().iterator(); ii.hasNext(); ) 114 { 115 Map.Entry i = ( Map.Entry ) ii.next(); 116 if ( memberName.equals( ( ( AnnotationTypeElementDeclaration ) i.getKey() ).getSimpleName() ) ) 117 { 118 return ( AnnotationValue ) i.getValue(); 119 } 120 } 121 122 if ( defaultIsNull ) return null; 126 127 AnnotationTypeDeclaration typeDecl = annotation.getAnnotationType().getAnnotationTypeDeclaration(); 128 if ( typeDecl == null ) return null; 130 AnnotationTypeElementDeclaration[] members = typeDecl.getAnnotationMembers(); 131 for ( int i = 0; i < members.length; i++ ) 132 { 133 AnnotationTypeElementDeclaration member = members[i]; 134 if ( memberName.equals( member.getSimpleName() ) ) return member.getDefaultValue(); 135 136 } 137 138 assert false : "Member " + memberName + " not found on annotation type " + getQualifiedName( annotation ); 139 return null; 140 } 141 142 public static List getStringArrayValue( Declaration element, String annotationName, String memberName, 143 boolean defaultIsNull ) 144 { 145 AnnotationValue value = assertAnnotationValue( element, annotationName, memberName, defaultIsNull ); 146 if ( value == null ) return null; 147 ArrayList ret = new ArrayList (); 148 getValues( value, ret, false ); 149 return ret; 150 } 151 152 public static Boolean getBooleanValue( Declaration element, String annotationName, String memberName, 153 boolean defaultIsNull ) 154 { 155 AnnotationValue value = assertAnnotationValue( element, annotationName, memberName, defaultIsNull ); 156 return value != null ? ( Boolean ) value.getValue() : null; 157 } 158 159 public static String getString( AnnotationInstance annotation, String memberName, boolean defaultIsNull ) 160 { 161 AnnotationValue value = getAnnotationValue( annotation, memberName, defaultIsNull ); 162 return value != null ? ( String ) value.getValue() : ( defaultIsNull ? null : "" ); 163 } 164 165 public static TypeInstance getTypeInstance( AnnotationInstance annotation, String memberName, boolean defaultIsNull ) 166 { 167 AnnotationValue value = getAnnotationValue( annotation, memberName, defaultIsNull ); 168 return value != null ? ( TypeInstance ) value.getValue() : null; 169 } 170 171 public static String getEnumFieldName( AnnotationInstance annotation, String memberName, boolean defaultIsNull ) 172 { 173 AnnotationValue value = getAnnotationValue( annotation, memberName, defaultIsNull ); 174 return value != null ? getEnumFieldName( value ) : null; 175 } 176 177 public static List getStringArray( AnnotationInstance annotation, String memberName, boolean defaultIsNull ) 178 { 179 AnnotationValue value = getAnnotationValue( annotation, memberName, defaultIsNull ); 180 if ( value == null ) return null; 181 ArrayList ret = new ArrayList (); 182 getValues( value, ret, false ); 183 return ret; 184 } 185 186 public static DeclaredType getDeclaredType( AnnotationInstance annotation, String memberName, boolean defaultIsNull ) 187 { 188 return ( DeclaredType ) getReferenceType( annotation, memberName, defaultIsNull ); 189 } 190 191 public static ReferenceType getReferenceType( AnnotationInstance annotation, String memberName, boolean defaultIsNull ) 192 { 193 AnnotationValue value = getAnnotationValue( annotation, memberName, defaultIsNull ); 194 195 if ( value != null && isErrorString( value.getValue() ) ) return null; 197 198 return value != null ? ( ReferenceType ) value.getValue() : null; 199 } 200 201 public static Integer getInteger( AnnotationInstance annotation, String memberName, boolean defaultIsNull ) 202 { 203 AnnotationValue value = getAnnotationValue( annotation, memberName, defaultIsNull ); 204 if ( value == null ) return defaultIsNull ? null : new Integer ( 0 ); 205 Object result = value.getValue(); 206 207 if ( result instanceof String ) 208 { 209 assert isErrorString( result ) : result; 210 return new Integer ( 0 ); 211 } 212 213 return ( Integer ) value.getValue(); 214 } 215 216 public static boolean isErrorString( Object str ) 217 { 218 return ERROR_STRING.equals( str ); 219 } 220 221 public static Long getLong( AnnotationInstance annotation, String memberName, boolean defaultIsNull ) 222 { 223 AnnotationValue value = getAnnotationValue( annotation, memberName, defaultIsNull ); 224 if ( value == null ) return defaultIsNull ? null : new Long ( 0 ); 225 Object result = value.getValue(); 226 227 if ( result instanceof String ) 228 { 229 assert result.equals( ERROR_STRING ) : result; 230 return new Long ( 0 ); 231 } 232 233 return ( Long ) value.getValue(); 234 } 235 236 public static Float getFloat( AnnotationInstance annotation, String memberName, boolean defaultIsNull ) 237 { 238 AnnotationValue value = getAnnotationValue( annotation, memberName, defaultIsNull ); 239 if ( value == null ) return defaultIsNull ? null : new Float ( 0 ); 240 Object result = value.getValue(); 241 242 if ( result instanceof String ) 243 { 244 assert result.equals( ERROR_STRING ) : result; 245 return new Float ( 0 ); 246 } 247 248 return ( Float ) value.getValue(); 249 } 250 251 public static Double getDouble( AnnotationInstance annotation, String memberName, boolean defaultIsNull ) 252 { 253 AnnotationValue value = getAnnotationValue( annotation, memberName, defaultIsNull ); 254 if ( value == null ) return defaultIsNull ? null : new Double ( 0 ); 255 Object result = value.getValue(); 256 257 if ( result instanceof String ) 258 { 259 assert result.equals( ERROR_STRING ) : result; 260 return new Double ( 0 ); 261 } 262 263 return ( Double ) value.getValue(); 264 } 265 266 public static Boolean getBoolean( AnnotationInstance annotation, String memberName, boolean defaultIsNull ) 267 { 268 AnnotationValue value = getAnnotationValue( annotation, memberName, defaultIsNull ); 269 if ( value == null ) return defaultIsNull ? null : Boolean.FALSE; 270 Object result = value.getValue(); 271 272 if ( result instanceof String ) 273 { 274 assert result.equals( ERROR_STRING ) : result; 275 return Boolean.FALSE; 276 } 277 278 return ( Boolean ) value.getValue(); 279 } 280 281 public static Object getValue( Declaration element, String annotationName, String memberName, boolean defaultIsNull ) 282 { 283 AnnotationValue value = assertAnnotationValue( element, annotationName, memberName, defaultIsNull ); 284 return value != null ? value.getValue() : null; 285 } 286 287 public static List getAnnotationArrayValue( Declaration element, String annotationName, 288 String memberName, boolean defaultIsNull ) 289 { 290 AnnotationValue value = assertAnnotationValue( element, annotationName, memberName, defaultIsNull ); 291 if ( value == null ) return null; 292 ArrayList ret = new ArrayList (); 293 getValues( value, ret, true ); 294 return ret; 295 } 296 297 public static List getAnnotationArray( AnnotationInstance annotation, String memberName, 298 boolean defaultIsNull ) 299 { 300 AnnotationValue value = getAnnotationValue( annotation, memberName, defaultIsNull ); 301 return getAnnotationArray( value ); 302 } 303 304 public static List getAnnotationArray( AnnotationValue value ) 305 { 306 if ( value == null ) return null; 307 ArrayList ret = new ArrayList (); 308 getValues( value, ret, true ); 309 return ret; 310 } 311 312 private static void getValues( AnnotationValue arrayValue, List translatedValues, boolean weedOutErrorType ) 313 { 314 List values = ( List ) arrayValue.getValue(); 315 for ( Iterator ii = values.iterator(); ii.hasNext(); ) 316 { 317 Object i = ii.next(); 318 Object value = i instanceof AnnotationValue ? ( ( AnnotationValue ) i ).getValue() : i; 319 if ( ! weedOutErrorType || ! isErrorString( value ) ) translatedValues.add( value ); 320 } 321 } 322 323 public static String getQualifiedName( AnnotationInstance annotation ) 324 { 325 return getDeclaration( annotation.getAnnotationType() ).getQualifiedName(); 326 } 327 328 public static String getSimpleName( AnnotationInstance annotation ) 329 { 330 return getDeclaration( annotation.getAnnotationType() ).getSimpleName(); 331 } 332 333 public static AnnotationInstance getAnnotation( AnnotationInstance annotation, String memberName, boolean defaultIsNull ) 334 { 335 AnnotationValue value = getAnnotationValue( annotation, memberName, defaultIsNull ); 336 return value != null ? ( AnnotationInstance ) value.getValue() : null; 337 } 338 339 public static MethodDeclaration getClassMethod( TypeDeclaration jclass, String methodName, String desiredAnnotation ) 340 { 341 return getClassMethod( jclass, methodName, desiredAnnotation, false ); 342 } 343 344 private static MethodDeclaration getClassMethod( TypeDeclaration type, String methodName, String desiredAnnotation, 345 boolean onlyPublicOrProtected ) 346 { 347 if ( ! ( type instanceof ClassDeclaration ) ) return null; 348 349 ClassDeclaration jclass = ( ClassDeclaration ) type; 350 MethodDeclaration[] methods = jclass.getMethods(); 351 352 for ( int i = 0; i < methods.length; i++ ) 353 { 354 MethodDeclaration method = methods[i]; 355 if ( ! onlyPublicOrProtected || method.hasModifier( Modifier.PROTECTED ) 356 || method.hasModifier( Modifier.PUBLIC ) ) 357 { 358 if ( methodName.equals( method.getSimpleName() ) 359 && ( desiredAnnotation == null || getAnnotation( method, desiredAnnotation ) != null ) ) 360 { 361 return method; 362 } 363 } 364 } 365 366 ClassType superclass = jclass.getSuperclass(); 367 368 if ( superclass != null ) 369 { 370 return getClassMethod( getDeclaration( superclass ), methodName, desiredAnnotation, true ); 371 } 372 373 return null; 374 } 375 376 public static FieldDeclaration getClassField( TypeDeclaration jclass, String fieldName, String desiredAnnotation ) 377 { 378 return getClassField( jclass, fieldName, desiredAnnotation, false ); 379 } 380 381 private static FieldDeclaration getClassField( TypeDeclaration type, String fieldName, String desiredAnnotation, 382 boolean onlyPublicOrProtected ) 383 { 384 if ( ! ( type instanceof ClassDeclaration ) ) return null; 385 386 ClassDeclaration jclass = ( ClassDeclaration ) type; 387 FieldDeclaration[] fields = jclass.getFields(); 388 389 for ( int i = 0; i < fields.length; i++ ) 390 { 391 FieldDeclaration field = fields[i]; 392 if ( ! onlyPublicOrProtected || field.hasModifier( Modifier.PROTECTED ) 393 || field.hasModifier( Modifier.PUBLIC ) ) 394 { 395 if ( fieldName.equals( field.getSimpleName() ) 396 && ( desiredAnnotation == null || getAnnotation( field, desiredAnnotation ) != null ) ) 397 { 398 return field; 399 } 400 } 401 } 402 403 ClassType superclass = jclass.getSuperclass(); 404 405 if ( superclass != null ) 406 { 407 return getClassField( getDeclaration( superclass ), fieldName, desiredAnnotation, true ); 408 } 409 410 return null; 411 } 412 413 public static MethodDeclaration[] getClassMethods( TypeDeclaration jclass, String desiredAnnotation ) 414 { 415 Collection results = new ArrayList (); 416 getClassMethods( jclass, desiredAnnotation, false, results ); 417 return ( MethodDeclaration[] ) results.toArray( new MethodDeclaration[ results.size() ] ); 418 } 419 420 private static void getClassMethods( TypeDeclaration type, String desiredAnnotation, boolean onlyPublicOrPrivate, 421 Collection results ) 422 { 423 if ( ! ( type instanceof ClassDeclaration ) ) return; 424 425 ClassDeclaration jclass = ( ClassDeclaration ) type; 426 MethodDeclaration[] methods = jclass.getMethods(); 427 428 for ( int i = 0; i < methods.length; i++ ) 429 { 430 MethodDeclaration method = methods[i]; 431 432 if ( ! onlyPublicOrPrivate || method.hasModifier( Modifier.PROTECTED ) 433 || method.hasModifier( Modifier.PUBLIC ) ) 434 { 435 if ( desiredAnnotation == null || getAnnotation( method, desiredAnnotation ) != null ) 436 { 437 boolean isDuplicate = false; 438 439 if ( onlyPublicOrPrivate ) 443 { 444 ParameterDeclaration[] methodParams = method.getParameters(); 445 446 for ( Iterator j = results.iterator(); j.hasNext(); ) 447 { 448 MethodDeclaration existingMethod = ( MethodDeclaration ) j.next(); 449 450 if ( existingMethod.getSimpleName().equals( method.getSimpleName() ) ) 451 { 452 ParameterDeclaration[] existingMethodParams = existingMethod.getParameters(); 453 454 if ( existingMethodParams.length == methodParams.length ) 455 { 456 isDuplicate = true; 457 458 for ( int k = 0; k < existingMethodParams.length; ++k ) 459 { 460 ParameterDeclaration existingMethodParam = existingMethodParams[ k ]; 461 ParameterDeclaration methodParam = methodParams[ k ]; 462 463 if ( ! existingMethodParam.getType().equals( methodParam.getType() ) ) 464 { 465 isDuplicate = false; 466 break; 467 } 468 } 469 } 470 } 471 } 472 } 473 474 if ( ! isDuplicate ) results.add( method ); 475 } 476 } 477 } 478 479 ClassType superclass = jclass.getSuperclass(); 480 481 if ( superclass != null && ! getDeclaration( superclass ).getQualifiedName().startsWith( "java.lang." ) ) 482 { 483 getClassMethods( getDeclaration( superclass ), desiredAnnotation, true, results ); 484 } 485 } 486 487 public static Collection getClassFields( TypeDeclaration jclass ) 488 { 489 Collection results = new ArrayList (); 490 getClassFields( jclass, false, results ); 491 return results; 492 } 493 494 private static void getClassFields( TypeDeclaration type, boolean onlyPublicOrPrivate, 495 Collection results ) 496 { 497 if ( ! ( type instanceof ClassDeclaration ) ) return; 498 499 ClassDeclaration jclass = ( ClassDeclaration ) type; 500 FieldDeclaration[] fields = jclass.getFields(); 501 502 for ( int i = 0; i < fields.length; i++ ) 503 { 504 FieldDeclaration field = fields[i]; 505 if ( ! onlyPublicOrPrivate || field.hasModifier( Modifier.PROTECTED ) || field.hasModifier( Modifier.PUBLIC ) ) 506 { 507 results.add( field ); 508 } 509 } 510 511 ClassType superclass = jclass.getSuperclass(); 512 if ( superclass != null ) getClassFields( getDeclaration( superclass ), true, results ); 513 } 514 515 public static Collection getClassNestedTypes( TypeDeclaration jclass ) 516 { 517 Collection results = new ArrayList (); 518 getClassNestedTypes( jclass, false, results ); 519 return results; 520 } 521 522 private static void getClassNestedTypes( TypeDeclaration type, boolean onlyPublicOrPrivate, 523 Collection results ) 524 { 525 if ( ! ( type instanceof ClassDeclaration ) ) return; 526 527 ClassDeclaration jclass = ( ClassDeclaration ) type; 528 TypeDeclaration[] nestedTypes = jclass.getNestedTypes(); 529 530 for ( int i = 0; i < nestedTypes.length; i++ ) 531 { 532 TypeDeclaration nestedType = nestedTypes[i]; 533 if ( ! onlyPublicOrPrivate || nestedType.hasModifier( Modifier.PROTECTED ) 534 || nestedType.hasModifier( Modifier.PUBLIC ) ) 535 { 536 results.add( nestedType ); 537 } 538 } 539 540 ClassType superclass = jclass.getSuperclass(); 541 if ( superclass != null ) getClassNestedTypes( getDeclaration( superclass ), true, results ); 542 } 543 544 547 public static String getFormClassName( TypeDeclaration jclass, AnnotationProcessorEnvironment env ) 548 { 549 if ( isAssignableFrom( PAGEFLOW_FORM_CLASS_NAME, jclass, env ) ) 550 { 551 return getLoadableName( jclass ); 552 } 553 else if ( isAssignableFrom( BEA_XMLOBJECT_CLASS_NAME, jclass, env ) ) 554 { 555 return XML_FORM_CLASS_NAME; 556 } 557 else if ( isAssignableFrom( APACHE_XMLOBJECT_CLASS_NAME, jclass, env ) ) 558 { 559 return XML_FORM_CLASS_NAME; 560 } 561 else 562 { 563 return ANY_FORM_CLASS_NAME; 564 } 565 } 566 567 public static String getFormClassName( DeclaredType jclass, AnnotationProcessorEnvironment env ) 568 { 569 return getFormClassName( getDeclaration( jclass ), env ); 570 } 571 572 public static boolean isAbsoluteURL( String path ) 573 { 574 try 575 { 576 return new URI ( path ).getScheme() != null; 577 } 578 catch ( URISyntaxException e ) 579 { 580 return false; 581 } 582 } 583 584 public static boolean isAssignableFrom( String className, TypeInstance type, AnnotationProcessorEnvironment env ) 585 { 586 if ( ! ( type instanceof DeclaredType ) ) return false; 587 return isAssignableFrom( className, getDeclaration( ( DeclaredType ) type ), env ); 588 } 589 590 public static boolean isAssignableFrom( TypeDeclaration base, TypeDeclaration typeDecl ) 591 { 592 if ( base != null && typeDecl != null ) 593 { 594 if ( typesAreEqual( typeDecl, base ) ) return true; 595 596 if ( typeDecl instanceof ClassDeclaration ) 597 { 598 ClassType superclass = ( ( ClassDeclaration ) typeDecl ).getSuperclass(); 599 if ( superclass != null && isAssignableFrom( base, getDeclaration( superclass ) ) ) return true; 600 } 601 602 InterfaceType[] superInterfaces = typeDecl.getSuperinterfaces(); 603 for ( int i = 0; i < superInterfaces.length; i++ ) 604 { 605 InterfaceType superInterface = superInterfaces[i]; 606 if ( isAssignableFrom( base, getDeclaration( superInterface ) ) ) return true; 607 } 608 } 609 610 return false; 611 } 612 613 public static boolean isAssignableFrom( TypeInstance base, TypeDeclaration cl ) 614 { 615 if ( ! ( base instanceof DeclaredType ) ) return false; 616 return isAssignableFrom( getDeclaration( ( DeclaredType ) base ), cl ); 617 } 618 619 public static boolean isAssignableFrom( TypeDeclaration base, TypeInstance cl ) 620 { 621 if ( ! ( cl instanceof DeclaredType ) ) return false; 622 return isAssignableFrom( base, getDeclaration( ( DeclaredType ) cl ) ); 623 } 624 625 public static boolean isAssignableFrom( String className, TypeDeclaration cl, AnnotationProcessorEnvironment env ) 626 { 627 TypeDeclaration base = env.getTypeDeclaration( className ); 628 return isAssignableFrom( base, cl ); 629 } 630 631 public static boolean isOfClass( TypeInstance type, String className, AnnotationProcessorEnvironment env ) 632 { 633 if ( ! ( type instanceof DeclaredType ) ) return false; 634 return typesAreEqual( getDeclaration( ( DeclaredType ) type ), env.getTypeDeclaration( className ) ); 635 } 636 637 public static boolean typesAreEqual( TypeDeclaration t1, TypeDeclaration t2 ) 638 { 639 assert t1 != null; 640 if ( t2 == null ) return false; 641 return t1.getQualifiedName().equals( t2.getQualifiedName() ); 642 } 643 644 public static TypeDeclaration getOuterClass( MemberDeclaration classMember ) 645 { 646 return classMember instanceof ClassDeclaration 647 ? ( ClassDeclaration ) classMember 648 : classMember.getDeclaringType(); 649 } 650 651 public static TypeDeclaration getOutermostClass( MemberDeclaration classMember ) 652 { 653 TypeDeclaration containingClass; 654 while ( ( containingClass = classMember.getDeclaringType() ) != null ) 655 { 656 classMember = containingClass; 657 } 658 659 assert classMember instanceof ClassDeclaration : classMember.getClass().getName(); 660 return ( ClassDeclaration ) classMember; 661 } 662 663 public static boolean hasDefaultConstructor( TypeDeclaration jclass ) 664 { 665 if ( ! ( jclass instanceof ClassDeclaration ) ) return false; 666 667 ConstructorDeclaration[] constructors = ( ( ClassDeclaration ) jclass ).getConstructors(); 668 669 for ( int i = 0; i < constructors.length; i++ ) 670 { 671 ConstructorDeclaration ctor = constructors[i]; 672 if ( ctor.getParameters().length == 0 ) return true; 673 } 674 675 return false; 676 } 677 678 private static Declaration findElement( Collection elements, String elementName ) 679 { 680 for ( Iterator ii = elements.iterator(); ii.hasNext(); ) 681 { 682 Object element = ii.next(); 683 Declaration decl = ( Declaration ) element; 684 if ( decl.getSimpleName().equals( elementName ) ) return decl; 685 } 686 687 return null; 688 } 689 690 public static FieldDeclaration findField( TypeDeclaration jclass, String fieldName ) 691 { 692 return ( FieldDeclaration ) findElement( getClassFields( jclass ), fieldName ); 693 } 694 695 public static ClassDeclaration findInnerClass( TypeDeclaration jclass, String innerClassName ) 696 { 697 return ( ClassDeclaration ) findElement( getClassNestedTypes( jclass ), innerClassName ); 698 } 699 700 public static String getEnumFieldName( AnnotationValue enumMember ) 701 { 702 if ( enumMember == null || enumMember.getValue() == null ) 703 return ""; 704 else 705 return enumMember.getValue().toString(); 706 } 707 708 712 public static String getLoadableName( TypeDeclaration jclass ) 713 { 714 TypeDeclaration containingClass = jclass.getDeclaringType(); 715 716 if ( containingClass == null ) 717 { 718 return jclass.getQualifiedName(); 719 } 720 else 721 { 722 return getLoadableName( containingClass ) + '$' + jclass.getSimpleName(); 723 } 724 } 725 726 public static String getLoadableName( DeclaredType jclass ) 727 { 728 return getLoadableName( getDeclaration( jclass ) ); 729 } 730 731 public static File getSourceFile( TypeDeclaration decl, boolean mustBeNonNull ) 732 { 733 decl = getOutermostClass( decl ); 734 SourcePosition position = decl.getPosition(); 735 if ( mustBeNonNull ) assert position != null : "no source file for " + decl.toString(); 736 return position != null ? position.file() : null; 737 } 738 739 public static class ExtendedAnnotationProcessorEnvironment 740 implements AnnotationProcessorEnvironment 741 { 742 private AnnotationProcessorEnvironment _env; 743 private boolean _useEqualsToCompareAnnotations; 744 private HashMap _attributes; 745 746 public ExtendedAnnotationProcessorEnvironment( AnnotationProcessorEnvironment env, 747 boolean useEqualsToCompareAnnotations ) 748 { 749 _env = env; 750 _useEqualsToCompareAnnotations = useEqualsToCompareAnnotations; 751 } 752 753 public boolean useEqualsToCompareAnnotations() 754 { 755 return _useEqualsToCompareAnnotations; 756 } 757 758 public Map getOptions() 759 { 760 return _env.getOptions(); 761 } 762 763 public Messager getMessager() 764 { 765 return _env.getMessager(); 766 } 767 768 public Filer getFiler() 769 { 770 return _env.getFiler(); 771 } 772 773 public TypeDeclaration[] getSpecifiedTypeDeclarations() 774 { 775 return _env.getSpecifiedTypeDeclarations(); 776 } 777 778 public TypeDeclaration getTypeDeclaration( String s ) 779 { 780 return _env.getTypeDeclaration( s ); 781 } 782 783 public Declaration[] getDeclarationsAnnotatedWith( AnnotationTypeDeclaration annotationTypeDeclaration ) 784 { 785 return _env.getDeclarationsAnnotatedWith( annotationTypeDeclaration ); 786 } 787 788 public void setAttribute( String propertyName, Object value ) 789 { 790 if ( _attributes == null ) _attributes = new HashMap (); 791 _attributes.put( propertyName, value ); 792 } 793 794 public Object getAttribute( String propertyName ) 795 { 796 return _attributes != null ? _attributes.get( propertyName ) : null; 797 } 798 } 799 800 public static boolean annotationsAreEqual( AnnotationInstance a1, AnnotationInstance a2, boolean allowExactDuplicates, 801 AnnotationProcessorEnvironment env ) 802 { 803 assert a1 != null; 804 if ( a2 == null ) return false; 805 806 if ( ! allowExactDuplicates 812 && env instanceof ExtendedAnnotationProcessorEnvironment 813 && ( ( ExtendedAnnotationProcessorEnvironment ) env ).useEqualsToCompareAnnotations() ) 814 { 815 return a1.equals( a2 ); 816 } 817 818 Map vals1 = a1.getElementValues(); 819 Map vals2 = a2.getElementValues(); 820 821 if ( vals1.size() != vals2.size() ) return false; 822 823 824 Iterator ents1 = vals1.entrySet().iterator(); 825 Iterator ents2 = vals2.entrySet().iterator(); 826 while ( ents1.hasNext() ) 827 { 828 Map.Entry entry1 = ( Map.Entry ) ents1.next(); 829 Map.Entry entry2 = ( Map.Entry ) ents2.next(); 830 831 if ( ! ( ( AnnotationTypeElementDeclaration ) entry1.getKey() ).getSimpleName().equals( ( ( AnnotationTypeElementDeclaration ) entry2.getKey() ).getSimpleName() ) ) return false; 832 Object val1 = ( ( AnnotationValue ) entry1.getValue() ).getValue(); 833 Object val2 = ( ( AnnotationValue ) entry2.getValue() ).getValue(); 834 835 if ( val1 instanceof Collection ) 836 { 837 if ( ! ( val2 instanceof Collection ) ) return false; 838 Collection list1 = ( Collection ) val1; 839 Collection list2 = ( Collection ) val2; 840 if ( list1.size() != list2.size() ) return false; 841 Iterator j1 = list1.iterator(); 842 Iterator j2 = list2.iterator(); 843 844 while ( j1.hasNext() ) 845 { 846 Object o1 = ( ( AnnotationValue ) j1.next() ).getValue(); 847 Object o2 = ( ( AnnotationValue ) j2.next() ).getValue(); 848 849 if ( o1 instanceof AnnotationInstance ) 850 { 851 if ( ! ( o2 instanceof AnnotationInstance ) ) return false; 852 if ( ! annotationsAreEqual( ( AnnotationInstance ) o1, ( AnnotationInstance ) o2, allowExactDuplicates, env ) ) return false; 853 } 854 else 855 { 856 if ( ! o1.equals( o2 ) ) return false; 857 } 858 } 859 } 860 else if ( val1 instanceof AnnotationInstance ) 861 { 862 if ( ! ( val2 instanceof AnnotationInstance ) ) return false; 863 if ( ! annotationsAreEqual( ( AnnotationInstance ) val1, ( AnnotationInstance ) val2, allowExactDuplicates, env ) ) return false; 864 } 865 else if ( ! val1.equals( val2 ) ) 866 { 867 return false; 868 } 869 } 870 871 return true; 872 } 873 874 public static class BeanPropertyDescriptor 875 { 876 private String _propertyName; 877 private String _type; 878 879 public BeanPropertyDescriptor( String propertyName, String type ) 880 { 881 _propertyName = propertyName; 882 _type = type; 883 } 884 885 public String getPropertyName() 886 { 887 return _propertyName; 888 } 889 890 public String getType() 891 { 892 return _type; 893 } 894 } 895 896 public static class BeanPropertyDeclaration 897 extends BeanPropertyDescriptor 898 { 899 private MethodDeclaration _getter; 900 901 902 public BeanPropertyDeclaration( String propertyName, String type, MethodDeclaration getter ) 903 { 904 super( propertyName, type ); 905 _getter = getter; 906 } 907 908 public MethodDeclaration getGetter() 909 { 910 return _getter; 911 } 912 } 913 914 public static BeanPropertyDeclaration getBeanProperty( MethodDeclaration method ) 915 { 916 if ( method.hasModifier( Modifier.PUBLIC ) && ! method.hasModifier( Modifier.STATIC ) ) 917 { 918 String returnType = method.getReturnType().toString(); 919 920 if ( ! returnType.equals( "void" ) && method.getParameters().length == 0 ) 921 { 922 String methodName = method.getSimpleName(); 923 String propertyName = null; 924 925 if ( methodName.startsWith( GETTER_PREFIX ) && methodName.length() > GETTER_PREFIX.length() ) 926 { 927 propertyName = methodName.substring( GETTER_PREFIX.length() ); 928 } 929 else if ( methodName.startsWith( BOOLEAN_GETTER_PREFIX ) && returnType.equals( "boolean" ) 930 && methodName.length() > BOOLEAN_GETTER_PREFIX.length() ) 931 { 932 propertyName = methodName.substring( BOOLEAN_GETTER_PREFIX.length() ); 933 } 934 935 if ( propertyName != null ) 936 { 937 if ( propertyName.length() == 1 ) 942 { 943 propertyName = propertyName.toLowerCase(); 944 } 945 else if ( ! Character.isUpperCase( propertyName.charAt( 1 ) ) ) 946 { 947 propertyName = Character.toLowerCase( propertyName.charAt( 0 ) ) + propertyName.substring( 1 ); 948 } 949 950 return new BeanPropertyDeclaration( propertyName, returnType, method ); 951 } 952 } 953 } 954 955 return null; 956 } 957 958 public static Collection getBeanProperties( ClassDeclaration type, boolean getInheritedProperties ) 959 { 960 MethodDeclaration[] methods = getInheritedProperties ? getClassMethods( type, null ) : type.getMethods(); 961 ArrayList ret = new ArrayList (); 962 963 for ( int i = 0; i < methods.length; i++ ) 964 { 965 MethodDeclaration method = methods[i]; 966 967 if ( method.hasModifier( Modifier.PUBLIC ) ) 968 { 969 BeanPropertyDeclaration bpd = getBeanProperty( method ); 970 if ( bpd != null ) ret.add( bpd ); 971 } 972 } 973 974 return ret; 975 } 976 977 public static boolean isPageFlowClass( ClassDeclaration jclass, AnnotationProcessorEnvironment env ) 978 { 979 return getAnnotation( jclass, CONTROLLER_TAG_NAME ) != null && isAssignableFrom( JPF_BASE_CLASS, jclass, env ); 980 } 981 982 public static String removeFileExtension( String uri ) 983 { 984 int lastDot = uri.lastIndexOf( '.' ); 985 return uri.substring( 0, lastDot ); 986 } 987 988 public static TypeDeclaration inferTypeFromPath( String webappRelativePath, AnnotationProcessorEnvironment env ) 989 { 990 assert webappRelativePath.startsWith( "/" ) : webappRelativePath; 991 String className = removeFileExtension( webappRelativePath.substring( 1 ) ); 992 return env.getTypeDeclaration( className.replace( '/', '.' ) ); 993 } 994 995 public static TypeDeclaration getDeclaration( DeclaredType type ) 996 { 997 return type != null ? type.getDeclaration() : ERROR_TYPE_DECLARATION; 998 } 999 1000 private static class ErrorTypeDeclaration 1001 implements TypeDeclaration 1002 { 1003 private static final InterfaceType[] SUPERINTERFACES = new InterfaceType[0]; 1004 private static final FieldDeclaration[] FIELDS = new FieldDeclaration[0]; 1005 private static final MethodDeclaration[] METHODS = new MethodDeclaration[0]; 1006 private static final TypeDeclaration[] NESTED_TYPES = new TypeDeclaration[0]; 1007 private static final AnnotationInstance[] ANNOTATIONS = new AnnotationInstance[0]; 1008 1009 public PackageDeclaration getPackage() 1010 { 1011 throw new IllegalStateException ( "not implemented " ); 1012 } 1013 1014 public String getQualifiedName() 1015 { 1016 return ERROR_STRING; 1017 } 1018 1019 1025 1026 public InterfaceType[] getSuperinterfaces() 1027 { 1028 return SUPERINTERFACES; 1029 } 1030 1031 public FieldDeclaration[] getFields() 1032 { 1033 return FIELDS; 1034 } 1035 1036 public MethodDeclaration[] getMethods() 1037 { 1038 return METHODS; 1039 } 1040 1041 public TypeDeclaration[] getNestedTypes() 1042 { 1043 return NESTED_TYPES; 1044 } 1045 1046 public TypeDeclaration getDeclaringType() 1047 { 1048 return null; 1049 } 1050 1051 public String getDocComment() 1052 { 1053 throw new IllegalStateException ( "not implemented " ); 1054 } 1055 1056 public AnnotationInstance[] getAnnotationInstances() 1057 { 1058 return ANNOTATIONS; 1059 } 1060 1061 1067 1068 public Set getModifiers() 1069 { 1070 return Collections.EMPTY_SET; 1071 } 1072 1073 public String getSimpleName() 1074 { 1075 return getQualifiedName(); 1076 } 1077 1078 public SourcePosition getPosition() 1079 { 1080 throw new IllegalStateException ( "not implemented " ); 1081 } 1082 1083 public boolean hasModifier( Modifier modifier ) 1084 { 1085 return false; 1086 } 1087 1088 1094 } 1095 1096 1099 public static boolean isAbsoluteURI( String uri ) 1100 { 1101 if ( uri.length() == 0 || uri.charAt( 0 ) == '/' ) return false; 1105 1106 for ( int i = 0, len = uri.length(); i < len; ++i ) 1107 { 1108 char c = uri.charAt( i ); 1109 1110 if ( c == ':' ) 1111 { 1112 return true; 1113 } 1114 else if ( c == '/' ) 1115 { 1116 return false; 1117 } 1118 } 1119 1120 return false; 1121 } 1122 1123 public static TypeInstance getArrayBaseType( ArrayType arrayType ) 1124 { 1125 TypeInstance baseType = arrayType; 1126 1127 do 1128 { 1129 baseType = ( ( ArrayType ) baseType ).getComponentType(); 1130 } while ( baseType instanceof ArrayType ); 1131 1132 return baseType; 1133 } 1134 1135 public static final class Mutable 1136 { 1137 private Object _val = null; 1138 1139 public Mutable() 1140 { 1141 } 1142 1143 public Mutable( Object val ) 1144 { 1145 _val = val; 1146 } 1147 1148 public void set( Object val ) 1149 { 1150 _val = val; 1151 } 1152 1153 public Object get() 1154 { 1155 return _val; 1156 } 1157 } 1158 1159 public static TypeInstance getGenericBoundsType( TypeInstance type ) 1160 { 1161 if ( type instanceof TypeVariable ) 1162 { 1163 ReferenceType[] bounds = ( ( TypeVariable ) type ).getDeclaration().getBounds(); 1164 return bounds.length > 0 ? bounds[0] : type; 1165 } 1166 1167 return type; 1168 } 1169 1170 public static File getFileRelativeToSourceFile( TypeDeclaration outerClass, String relativePath, 1171 AnnotationProcessorEnvironment env ) 1172 throws FatalCompileTimeException 1173 { 1174 assert relativePath.length() > 0; 1175 1176 if ( relativePath.charAt( 0 ) == '/' ) return getWebappRelativeFile( relativePath, true, env ); 1180 1181 File sourceFile = getSourceFile( outerClass, false ); 1185 File desiredParentDir = sourceFile.getAbsoluteFile().getParentFile(); 1186 File retVal = new File ( desiredParentDir, relativePath ); 1187 1188 if ( ! retVal.exists() ) 1192 { 1193 String jpfParentRelativePath = ""; 1194 PackageDeclaration jpfPackage = outerClass.getPackage(); 1195 if ( jpfPackage != null ) jpfParentRelativePath = jpfPackage.getQualifiedName().replace( '.', '/' ); 1196 return getWebappRelativeFile( '/' + jpfParentRelativePath + '/' + relativePath, true, env ); 1197 } 1198 1199 return retVal; 1200 } 1201 1202 public static File getWebappRelativeFile( String webappRelativePath, boolean lookInSourceRoots, 1203 AnnotationProcessorEnvironment env ) 1204 throws FatalCompileTimeException 1205 { 1206 assert webappRelativePath.startsWith( "/" ) : webappRelativePath; 1210 String webContentRoot = getWebContentRoot( env ); 1211 File retVal = new File ( webContentRoot + webappRelativePath ); 1212 1213 if ( ! retVal.exists() && lookInSourceRoots ) 1217 { 1218 String [] webSourceRoots = getWebSourceRoots( env ); 1219 1220 for ( int i = 0; i < webSourceRoots.length; i++ ) 1221 { 1222 String webSourceRoot = webSourceRoots[i]; 1223 File webSourceRelativeFile = new File ( webSourceRoot + webappRelativePath ); 1224 if ( webSourceRelativeFile.exists() ) return webSourceRelativeFile; 1225 } 1226 } 1227 1228 return retVal; 1229 } 1230 1231 public static String [] getWebSourceRoots( AnnotationProcessorEnvironment env ) 1232 throws FatalCompileTimeException 1233 { 1234 return ( String [] ) getOption( "web.source.roots", true, env ); 1235 } 1236 1237 public static String getWebContentRoot( AnnotationProcessorEnvironment env ) 1238 throws FatalCompileTimeException 1239 { 1240 return ( String ) getOption( "web.content.root", false, env ); 1241 } 1242 1243 public static String getWebBuildRoot( AnnotationProcessorEnvironment env ) 1244 throws FatalCompileTimeException 1245 { 1246 return ( String ) getOption( "web.output.root", false, env ); 1247 } 1248 1249 private static Object getOption( String optionName, boolean isList, AnnotationProcessorEnvironment env ) 1250 throws MissingOptionException 1251 { 1252 Object cached = env.getAttribute( optionName ); 1253 if ( cached != null ) return cached; 1254 1255 Map options = env.getOptions(); 1256 String value = ( String ) options.get( optionName ); 1257 1258 if ( value == null ) 1259 { 1260 String aptOption = "-A" + optionName + '='; 1262 for ( Iterator i = options.keySet().iterator(); i.hasNext(); ) 1263 { 1264 String key = ( String ) i.next(); 1265 1266 if ( key.startsWith( aptOption ) ) 1267 { 1268 value = key.substring( aptOption.length() ); 1269 break; 1270 } 1271 } 1272 } 1273 1274 if ( value == null ) throw new MissingOptionException( optionName ); 1275 1276 Object retVal = value; 1277 1278 if ( isList ) 1279 { 1280 String [] values = ( ( String ) retVal ).trim().split( File.pathSeparator ); 1281 for ( int i = 0; i < values.length; i++ ) 1282 { 1283 values[i] = values[i].trim(); 1284 } 1285 retVal = values; 1286 } 1287 1288 env.setAttribute( optionName, retVal ); 1289 return retVal; 1290 } 1291} 1292 | Popular Tags |