1 package org.apache.beehive.controls.runtime.generator; 2 19 20 import java.io.*; 21 import java.lang.reflect.*; 22 import java.lang.annotation.*; 23 import java.net.*; 24 import java.util.*; 25 26 import com.sun.mirror.apt.Filer; 27 import com.sun.mirror.declaration.AnnotationMirror; 28 import com.sun.mirror.declaration.AnnotationTypeDeclaration; 29 import com.sun.mirror.declaration.Declaration; 30 import com.sun.mirror.declaration.InterfaceDeclaration; 31 import com.sun.mirror.declaration.MethodDeclaration; 32 import com.sun.mirror.declaration.TypeDeclaration; 33 import com.sun.mirror.type.DeclaredType; 34 import com.sun.mirror.type.InterfaceType; 35 import com.sun.mirror.type.MirroredTypesException; 36 37 import org.apache.beehive.controls.api.bean.ControlChecker; 38 import org.apache.beehive.controls.api.bean.ControlExtension; 39 import org.apache.beehive.controls.api.bean.ControlInterface; 40 import org.apache.beehive.controls.api.bean.ExternalPropertySets; 41 import org.apache.beehive.controls.api.events.EventSet; 42 import org.apache.beehive.controls.api.packaging.FeatureInfo; 43 import org.apache.beehive.controls.api.packaging.ManifestAttribute; 44 import org.apache.beehive.controls.api.packaging.ManifestAttributes; 45 import org.apache.beehive.controls.api.properties.PropertySet; 46 import org.apache.beehive.controls.api.versioning.Version; 47 import org.apache.beehive.controls.api.versioning.VersionRequired; 48 import org.apache.beehive.controls.runtime.generator.apt.TwoPhaseAnnotationProcessor; 49 50 55 public class AptControlInterface extends AptType implements Generator 56 { 57 63 public AptControlInterface(Declaration decl, TwoPhaseAnnotationProcessor ap) 64 { 65 _ap = ap; 66 67 if (! (decl instanceof InterfaceDeclaration) && 76 (decl.getAnnotation(ControlExtension.class) != null || 77 decl.getAnnotation(ControlInterface.class) != null)) 78 { 79 _ap.printError(decl, "control.interface.annotation.badlocation" ); 80 return; 81 } 82 83 _intfDecl = (InterfaceDeclaration)decl; 84 setDeclaration(_intfDecl); 85 86 _isExtension = initIsExtension(); 87 88 _superClass = initSuperClass(); 89 90 _operations = initOperations(); 91 92 _propertySets = initPropertySets(); 93 94 _eventSets = initEventSets(); 95 96 _featureInfo = initFeatureInfo(); 97 98 _version = initVersion(); 99 _versionRequired = initVersionRequired(); 100 101 _bean = new ControlBean(this); 105 106 enforceVersionRequired(); 110 111 115 if (isExtension()) 116 { 117 check(); 122 } 123 } 124 125 129 public InterfaceType getSuperType() 130 { 131 if ( _intfDecl.getSuperinterfaces() == null ) 132 return null; 133 134 for (InterfaceType intfType : _intfDecl.getSuperinterfaces()) 135 { 136 InterfaceDeclaration superDecl = intfType.getDeclaration(); 137 if ( superDecl != null ) 138 { 139 if (superDecl.getAnnotation(ControlExtension.class) != null || 140 superDecl.getAnnotation(ControlInterface.class) != null) 141 { 142 _superDecl = superDecl; 143 return intfType; 144 } 145 } 146 } 147 148 return null; 149 } 150 151 155 private AptControlInterface initSuperClass() 156 { 157 InterfaceType superType = getSuperType(); 162 if (superType == null) 163 { 164 if ( isExtension() ) 168 { 169 _ap.printError( _intfDecl, "control.extension.badinterface"); 170 } 171 172 return null; 173 } 174 175 InterfaceDeclaration superDecl = superType.getDeclaration(); 176 if ( superDecl != null ) 177 { 178 if (superDecl.getAnnotation(ControlExtension.class) != null || 179 superDecl.getAnnotation(ControlInterface.class) != null) 180 { 181 _superDecl = superDecl; 182 AptControlInterface superIntf = new AptControlInterface(_superDecl, _ap); 183 184 if (!isExtension() && superIntf.isExtension()) 185 { 186 _ap.printError( _intfDecl, "control.interface.badinterface"); 187 } 188 return superIntf; 189 } 190 } 191 192 return null; 193 } 194 195 198 public AptControlInterface getSuperClass() { return _superClass; } 199 200 203 private AptMethodSet<AptOperation> initOperations() 204 { 205 AptMethodSet<AptOperation> operList = new AptMethodSet<AptOperation>(); 206 207 if ( _intfDecl == null ) 208 return operList; 209 210 Vector<InterfaceDeclaration> checkIntfs = new Vector<InterfaceDeclaration>(); 225 checkIntfs.add(_intfDecl); 226 227 for (int i = 0; i < checkIntfs.size(); i++) 228 { 229 InterfaceDeclaration intfDecl = checkIntfs.elementAt(i); 230 if (intfDecl.equals(_superDecl)) 231 continue; 232 233 if ( intfDecl.getMethods() == null ) 234 continue; 235 236 for (MethodDeclaration methodDecl : intfDecl.getMethods()) 238 if (!methodDecl.toString().equals("<clinit>()")) 239 operList.add(new AptOperation(this, methodDecl, _ap)); 240 241 if ( intfDecl.getSuperinterfaces() == null ) 242 continue; 243 244 for (InterfaceType superType : intfDecl.getSuperinterfaces()) 245 { 246 InterfaceDeclaration superDecl = superType.getDeclaration(); 247 if (superDecl != null && !checkIntfs.contains(superDecl)) 248 checkIntfs.add(superDecl); 249 } 250 } 251 252 return operList; 253 } 254 255 258 public Collection<AptOperation> getOperations() { return _operations.getMethods(); } 259 260 263 public int getOperationCount() 264 { 265 int count = _operations.size(); 266 if (_superClass != null) 267 count += _superClass.getOperationCount(); 268 269 return count; 270 } 271 272 275 private ArrayList<AptPropertySet> initPropertySets() 276 { 277 ArrayList<AptPropertySet> propSets = new ArrayList<AptPropertySet>(); 278 279 if ( _intfDecl == null ) 280 return propSets; 281 282 285 289 TypeDeclaration basePropsDecl = 290 _ap.getAnnotationProcessorEnvironment().getTypeDeclaration( "org.apache.beehive.controls.api.properties.BaseProperties" ); 291 if ( basePropsDecl != null ) 292 { 293 propSets.add( new AptPropertySet( null, basePropsDecl, _ap ) ); 294 } 295 296 ExternalPropertySets extPropsAnnotation = _intfDecl.getAnnotation(ExternalPropertySets.class); 300 if ( extPropsAnnotation != null ) 301 { 302 if (isExtension()) 303 { 304 _ap.printError( _intfDecl, "extpropertyset.illegal.usage" ); 305 } 306 307 try 308 { 309 Class [] extProps = extPropsAnnotation.value(); 310 } 311 catch ( MirroredTypesException mte ) 312 { 313 Collection<String > extProps = mte.getQualifiedNames(); 314 for ( String extPropName : extProps ) 315 { 316 TypeDeclaration extPropDecl = _ap.getAnnotationProcessorEnvironment().getTypeDeclaration( extPropName ); 317 if ( extPropDecl != null ) 318 { 319 AptPropertySet extPropSet = new AptPropertySet( null, extPropDecl, _ap ); 320 propSets.add( extPropSet ); 321 } 322 else 323 { 324 _ap.printError( _intfDecl, "extpropertyset.type.not.found", extPropName ); 325 } 326 } 327 } 328 } 329 330 334 if ( _intfDecl.getNestedTypes() == null ) 335 return propSets; 336 337 for (TypeDeclaration innerDecl : _intfDecl.getNestedTypes()) 338 { 339 boolean fError = false; 340 341 if (! (innerDecl instanceof AnnotationTypeDeclaration)) 346 continue; 347 348 if (innerDecl.getAnnotation(PropertySet.class) != null) 349 { 350 if (! (innerDecl instanceof AnnotationTypeDeclaration)) 351 { 352 _ap.printError( innerDecl, "propertyset.not.annotation.type" ); 353 fError = true; 354 } 355 356 Retention ret = innerDecl.getAnnotation(Retention.class); 357 if (ret == null || ret.value() != RetentionPolicy.RUNTIME) 358 { 359 _ap.printError( innerDecl, "propertyset.missing.retention" ); 360 fError = true; 361 } 362 363 if (isExtension()) 364 { 365 _ap.printError( innerDecl, "propertyset.illegal.usage.2" ); 366 fError = true; 367 } 368 369 if ( !fError ) 370 propSets.add( 371 new AptPropertySet(this, (AnnotationTypeDeclaration)innerDecl, _ap)); 372 } 373 } 374 375 380 Set<String > propertyNames = new HashSet<String >(); 381 382 for (AptPropertySet propSet : propSets) 383 { 384 for (AptProperty prop : propSet.getProperties()) 385 { 386 if (prop.isBound()) 387 _hasBoundProperties = true; 388 389 if (prop.isConstrained()) 390 _hasConstrainedProperties = true; 391 392 String propName = prop.getAccessorName(); 393 394 if ( propertyNames.contains( propName ) ) 395 { 396 _ap.printError( _intfDecl, "propertyset.duplicate.property.names", propName, propSet.getShortName() ); 397 } 398 else 399 { 400 propertyNames.add( propName ); 401 } 402 } 403 } 404 405 return propSets; 406 } 407 408 411 public Collection<AptPropertySet> getPropertySets() { return _propertySets; } 412 413 416 public int getPropertyCount() 417 { 418 int count; 419 if (_superClass == null) 420 count = 0; 421 else 422 count = _superClass.getPropertyCount(); 423 424 for (AptPropertySet propertySet : _propertySets) 425 count += propertySet.getProperties().size(); 426 427 return count; 428 } 429 430 433 public boolean hasBoundProperties() 434 { 435 if (_superClass != null && _superClass.hasBoundProperties()) 436 return true; 437 438 return _hasBoundProperties; 439 } 440 441 446 public boolean addsBoundPropertySupport() 447 { 448 if (_superClass != null && _superClass.addsBoundPropertySupport()) 452 return false; 453 454 return hasBoundProperties(); 455 } 456 457 462 public boolean hasConstrainedProperties() 463 { 464 if (_superClass != null && _superClass.hasConstrainedProperties()) 465 return true; 466 467 return _hasConstrainedProperties; 468 } 469 470 475 public boolean addsConstrainedPropertySupport() 476 { 477 if (_superClass != null && _superClass.addsConstrainedPropertySupport()) 481 return false; 482 483 return hasConstrainedProperties(); 484 } 485 486 489 private ArrayList<AptEventSet> initEventSets() 490 { 491 ArrayList<AptEventSet> eventSets = new ArrayList<AptEventSet>(); 492 493 if ( _intfDecl == null || _intfDecl.getNestedTypes() == null ) 494 return eventSets; 495 496 for (TypeDeclaration innerDecl : _intfDecl.getNestedTypes()) 497 { 498 if (! (innerDecl instanceof InterfaceDeclaration)) 503 continue; 504 505 if (innerDecl.getAnnotation(EventSet.class) != null) 506 { 507 508 if (! (innerDecl instanceof InterfaceDeclaration)) 509 { 510 _ap.printError( innerDecl, "eventset.illegal.usage" ); 511 } 512 else 513 { 514 eventSets.add( 515 new AptEventSet(this, (InterfaceDeclaration)innerDecl, _ap)); 516 } 517 } 518 } 519 return eventSets; 520 } 521 522 525 public Collection<AptEventSet> getEventSets() { return _eventSets; } 526 527 530 public int getEventSetCount() 531 { 532 int count = _eventSets.size(); 533 if (_superClass != null) 534 count += _superClass.getEventSetCount(); 535 536 return count; 537 } 538 539 542 public AptEventSet getEventSet(String name) 543 { 544 for (AptEventSet eventSet: getEventSets()) 545 if (eventSet.getClassName().equals(name)) 546 return eventSet; 547 548 if (_superClass != null) 549 return _superClass.getEventSet(name); 550 551 return null; 552 } 553 554 557 public FeatureInfo getFeatureInfo() { return _featureInfo; } 558 559 563 public String [] getGeneratedTypes() 564 { 565 return new String [] { _bean.getClassName() }; 566 } 567 568 571 public Version getVersion() 572 { 573 return _version; 574 } 575 576 579 public VersionRequired getVersionRequired() 580 { 581 return _versionRequired; 582 } 583 584 587 public List<GeneratorOutput> getCheckOutput(Filer filer) throws IOException 588 { 589 HashMap<String ,Object > map = new HashMap<String ,Object >(); 590 591 map.put("intf", this); map.put("bean", _bean); 593 594 ArrayList<GeneratorOutput> genList = new ArrayList<GeneratorOutput>(); 595 596 Writer beanWriter = new IndentingWriter(filer.createSourceFile(_bean.getClassName())); 600 GeneratorOutput beanSource = 601 new GeneratorOutput(beanWriter, 602 "org/apache/beehive/controls/runtime/generator/ControlBean.vm", map); 603 genList.add(beanSource); 604 605 Writer beanInfoWriter = new IndentingWriter(filer.createSourceFile(_bean.getBeanInfoName())); 609 GeneratorOutput beanInfoSource = 610 new GeneratorOutput(beanInfoWriter, 611 "org/apache/beehive/controls/runtime/generator/ControlBeanInfo.vm", map); 612 genList.add(beanInfoSource); 613 614 return genList; 615 } 616 617 622 public List<GeneratorOutput> getGenerateOutput(Filer filer) throws IOException 623 { 624 HashMap<String ,Object > map = new HashMap<String ,Object >(); 625 626 map.put("intf", this); map.put("bean", _bean); 628 629 ArrayList<GeneratorOutput> genList = new ArrayList<GeneratorOutput>(); 630 631 Writer manifestWriter = filer.createTextFile(Filer.Location.CLASS_TREE, _bean.getPackage(), 635 new File(_bean.getShortName() + ".class.manifest"), 636 null); 637 GeneratorOutput beanManifest = 638 new GeneratorOutput(manifestWriter, 639 "org/apache/beehive/controls/runtime/generator/ControlManifest.vm", 640 map); 641 genList.add(beanManifest); 642 643 return genList; 644 } 645 646 650 public boolean isExtension() 651 { 652 return _isExtension; 653 } 654 655 662 public AptControlInterface getMostDerivedInterface() 663 { 664 674 AptControlInterface ancestor = getSuperClass(); 675 while (ancestor != null) 676 { 677 if (!ancestor.isExtension()) 678 break; 679 680 ancestor = ancestor.getSuperClass(); 681 } 682 683 return ancestor; 684 } 685 686 689 public ClassLoader getExternalClassLoader() 690 { 691 Map<String ,String > opts = _ap.getAnnotationProcessorEnvironment().getOptions(); 692 String classpath = opts.get("-classpath"); 693 694 if ( classpath != null ) 695 { 696 String [] cpEntries = classpath.split( File.pathSeparator ); 697 ArrayList a = new ArrayList(); 698 for ( String e : cpEntries ) 699 { 700 try 701 { 702 File f = (new File(e)).getCanonicalFile(); 703 URL u = f.toURL(); 704 a.add(u); 705 } 706 catch (Exception ex) 707 { 708 System.err.println( "getExternalClassLoader(): bad cp entry=" + e ); 709 System.err.println( "Exception processing e=" + ex ); 710 } 711 } 712 URL [] urls = new URL[a.size()]; 713 urls = (URL[]) a.toArray(urls); 714 715 return new URLClassLoader( urls, ControlChecker.class.getClassLoader() ); 716 } 717 718 return null; 719 } 720 721 static final String alphaNum = "ABCDEFGHIJKLMNOPQRSUVWXYZabcdefghijklmnopqrstuvwyz0123456789"; 725 static final String headerChar = alphaNum + "_-"; 726 727 731 private boolean isValidManifestAttribute(ManifestAttribute attr) 732 { 733 String name = attr.name(); 734 String value = attr.value(); 735 boolean isValid = true; 736 if (name.length() == 0) 737 { 738 _ap.printError( _intfDecl, "manifestattribute.illegal.name.1" ); 739 isValid = false; 740 } 741 else 742 { 743 if (alphaNum.indexOf(name.charAt(0)) < 0) 744 { 745 _ap.printError( _intfDecl, "manifestattribute.illegal.name.2" ); 746 isValid = false; 747 } 748 for (int i = 1; i < name.length(); i++) 749 { 750 if (headerChar.indexOf(name.charAt(i)) < 0) 751 { 752 _ap.printError( _intfDecl, "manifestattribute.illegal.name.3", name.charAt(i) ); 753 isValid = false; 754 break; 755 } 756 } 757 } 758 759 if (value.length() == 0) 760 { 761 _ap.printError( _intfDecl, "manifestattribute.illegal.name.4" ); 762 isValid = false; 763 } 764 else 765 { 766 } 768 769 return isValid; 770 } 771 772 775 public HashMap<String , String > getManifestAttributes() 776 { 777 HashMap<String ,String > attributes = new HashMap<String ,String >(); 778 779 if ( _intfDecl == null ) 780 return attributes; 781 782 try 783 { 784 ManifestAttributes annotAttrs =_intfDecl.getAnnotation(ManifestAttributes.class); 785 if (annotAttrs != null) 786 { 787 ManifestAttribute [] attrs = (ManifestAttribute [])annotAttrs.value(); 788 for (int i = 0; i < attrs.length; i++) 789 { 790 if (isValidManifestAttribute(attrs[i])) 791 attributes.put(attrs[i].name(), attrs[i].value()); 792 } 793 } 794 ManifestAttribute annotAttr = _intfDecl.getAnnotation(ManifestAttribute.class); 795 if (annotAttr != null) 796 { 797 if (isValidManifestAttribute(annotAttr)) 798 attributes.put(annotAttr.name(), annotAttr.value()); 799 } 800 return attributes; 801 } 802 catch (Exception e) { e.printStackTrace(); return attributes; } 803 } 804 805 808 private boolean initIsExtension() 809 { 810 if ( _intfDecl == null ) 811 return false; 812 813 return _intfDecl.getAnnotation(ControlExtension.class) != null; 814 } 815 816 819 private FeatureInfo initFeatureInfo() 820 { 821 if ( _intfDecl == null ) 822 return null; 823 return _intfDecl.getAnnotation(FeatureInfo.class); 824 } 825 826 829 private Version initVersion() 830 { 831 if ( _intfDecl == null ) 832 return null; 833 return _intfDecl.getAnnotation(Version.class); 834 } 835 836 839 private VersionRequired initVersionRequired() 840 { 841 if ( _intfDecl == null ) 842 return null; 843 return _intfDecl.getAnnotation(VersionRequired.class); 844 } 845 846 849 private void enforceVersionRequired() 850 { 851 if ( _versionRequired != null ) 852 { 853 if ( !isExtension() ) 854 { 855 _ap.printError( _intfDecl, "versionrequired.illegal.usage" ); 856 return; 857 } 858 859 int majorRequired = _versionRequired.major(); 860 int minorRequired = _versionRequired.minor(); 861 862 if ( majorRequired < 0 ) return; 864 865 AptControlInterface ci = getMostDerivedInterface(); 866 if ( ci == null ) 867 return; 868 869 int majorPresent = -1; 870 int minorPresent = -1; 871 Version ciVersion = ci._version; 872 if ( ciVersion != null ) 873 { 874 majorPresent = ciVersion.major(); 875 minorPresent = ciVersion.minor(); 876 877 if ( majorRequired <= majorPresent && 878 (minorRequired < 0 || minorRequired <= minorPresent) ) 879 { 880 return; 882 } 883 } 884 885 _ap.printError( _intfDecl, "versionrequired.failed", _intfDecl.getSimpleName(), 889 majorRequired, minorRequired, majorPresent, minorPresent ); 890 } 891 } 892 893 896 public void check() 897 { 898 903 AptControlInterface mostDerived = (AptControlInterface) getMostDerivedInterface(); 904 if ( mostDerived == null ) 905 return; 906 907 InterfaceDeclaration intfDecl = mostDerived._intfDecl; 908 909 if ( intfDecl == null ) 910 return; 911 912 AnnotationMirror controlMirror = null; 913 914 for (AnnotationMirror annot : intfDecl.getAnnotationMirrors()) 915 { 916 if (annot.getAnnotationType().getDeclaration().getQualifiedName().equals( 917 "org.apache.beehive.controls.api.bean.ControlInterface")) 918 { 919 controlMirror = annot; 920 break; 921 } 922 } 923 924 assert ( controlMirror != null ) : "Found a control interface that isn't annotated properly: " + intfDecl; 925 926 AptAnnotationHelper controlAnnot = new AptAnnotationHelper(controlMirror); 927 928 933 DeclaredType checkerMirror = (DeclaredType)controlAnnot.getObjectValue("checker"); 934 if ( checkerMirror == null ) 935 { 936 checkerMirror = (DeclaredType)controlAnnot.getObjectValue("checkerClass"); 938 } 939 940 if ( checkerMirror != null && checkerMirror.getDeclaration() != null ) 941 { 942 String checkerName = checkerMirror.toString(); 944 945 try 946 { 947 ClassLoader loader = getExternalClassLoader(); 948 949 Class checkerClass = loader.loadClass( checkerName ); 950 if ( !ControlChecker.class.isAssignableFrom(checkerClass) ) 951 { 952 _ap.printError( intfDecl, "control.interface.illegal.checker", intfDecl.getSimpleName(), checkerName ); 953 } 954 else 955 { 956 957 Constructor ctor = checkerClass.getConstructor(); 958 959 ControlChecker checker = (ControlChecker) ctor.newInstance(); 960 checker.check( _intfDecl, _ap.getAnnotationProcessorEnvironment() ); 961 } 962 } 963 catch ( Exception e ) 964 { 965 e.printStackTrace(); 966 } 967 } 968 } 969 970 private AptControlInterface _superClass; 971 private AptMethodSet<AptOperation> _operations; 972 private ArrayList<AptPropertySet> _propertySets; 973 private boolean _isExtension; private boolean _hasBoundProperties; 975 private boolean _hasConstrainedProperties;; 976 private ArrayList<AptEventSet> _eventSets; 977 private ControlBean _bean; 978 private FeatureInfo _featureInfo; 979 private Version _version; 980 private VersionRequired _versionRequired; 981 private InterfaceDeclaration _intfDecl; 982 private InterfaceDeclaration _superDecl; 983 private TwoPhaseAnnotationProcessor _ap; 984 } 985 | Popular Tags |