1 package org.apache.beehive.controls.runtime.generator.apt; 2 3 20 21 import com.sun.mirror.apt.AnnotationProcessorEnvironment; 22 import com.sun.mirror.declaration.AnnotationTypeDeclaration; 23 import com.sun.mirror.declaration.FieldDeclaration; 24 import com.sun.mirror.declaration.TypeDeclaration; 25 import com.sun.mirror.declaration.*; 26 import com.sun.mirror.apt.*; 27 import com.sun.mirror.type.*; 28 29 import java.util.*; 30 31 import org.apache.beehive.controls.runtime.bean.ControlBeanContext; 32 import org.apache.beehive.controls.runtime.generator.*; 33 import org.apache.beehive.controls.api.bean.*; 34 import org.apache.beehive.controls.api.versioning.Version; 35 import org.apache.beehive.controls.api.versioning.VersionRequired; 36 37 import java.util.Set ; 38 import java.io.File ; 39 import java.io.IOException ; 40 41 public class ControlClientAnnotationProcessor extends TwoPhaseAnnotationProcessor 42 { 43 44 public ControlClientAnnotationProcessor( 45 Set <AnnotationTypeDeclaration> atds, AnnotationProcessorEnvironment env ) 46 { 47 super( atds,env ); 48 } 49 50 @Override 51 public void check( Declaration d ) 52 { 53 if ( d instanceof FieldDeclaration ) 54 checkControlField( (FieldDeclaration)d ); 55 56 59 if ( d instanceof TypeDeclaration ) 60 checkControlClientType( (TypeDeclaration)d ); 61 62 try 67 { 68 AnnotationConstraintAptValidator.validate(d); 69 } 70 catch (IllegalArgumentException iae) 71 { 72 printError(d, "propertyset.illegal.argument.error", iae.getMessage()); 73 } 74 } 75 76 private static void addControlType(Map<TypeDeclaration,Set <TypeMirror>> clientsMap, TypeDeclaration clientType, 77 TypeMirror controlFieldType) 78 { 79 Set <TypeMirror> controlTypes = clientsMap.get( clientType ); 80 81 if ( controlTypes == null ) 82 { 83 controlTypes = new HashSet<TypeMirror>(); 84 clientsMap.put( clientType, controlTypes ); 85 } 86 87 controlTypes.add( controlFieldType ); 88 } 89 90 95 @Override 96 public void generate() throws CodeGenerationException 97 { 98 super.generate(); 99 100 103 Map<TypeDeclaration,Set <TypeMirror>> clientsMap = new HashMap<TypeDeclaration,Set <TypeMirror>>(); 104 105 for (AnnotationTypeDeclaration atd : _atds) 106 { 107 if (atd.getSimpleName().equals("Control") ) 108 { 109 AnnotationProcessorEnvironment env = getAnnotationProcessorEnvironment(); 110 Collection<Declaration> decls = env.getDeclarationsAnnotatedWith(atd); 111 for (Declaration decl : decls) 112 { 113 if ( decl instanceof FieldDeclaration ) 114 { 115 FieldDeclaration fd = (FieldDeclaration)decl; 116 TypeDeclaration clientType = fd.getDeclaringType(); 117 TypeMirror controlFieldType = fd.getType(); 118 addControlType( clientsMap, clientType, controlFieldType ); 119 120 Collection<Modifier> modifiers = fd.getModifiers(); 124 if ( modifiers.contains( Modifier.PUBLIC ) || modifiers.contains( Modifier.PROTECTED ) ) 125 { 126 Collection<TypeDeclaration> specifiedTypeDeclartions = env.getSpecifiedTypeDeclarations(); 127 for (TypeDeclaration td : specifiedTypeDeclartions) 128 { 129 if ( td instanceof ClassDeclaration ) 130 { 131 ClassType superclass = ( ( ClassDeclaration ) td ).getSuperclass(); 132 133 while ( superclass != null ) 134 { 135 if ( superclass.getDeclaration().equals( clientType ) ) 136 { 137 addControlType( clientsMap, td, controlFieldType ); 138 break; 139 } 140 141 superclass = superclass.getSuperclass(); 142 } 143 } 144 } 145 } 146 } 147 } 148 } 149 else if (atd.getSimpleName().equals("ControlReferences")) 150 { 151 Collection<Declaration> decls = getAnnotationProcessorEnvironment().getDeclarationsAnnotatedWith(atd); 152 for (Declaration decl : decls) 153 { 154 if ( decl instanceof TypeDeclaration ) 155 { 156 TypeDeclaration clientType = (TypeDeclaration)decl; 157 Set <TypeMirror> controlTypes = clientsMap.get( clientType ); 158 if ( controlTypes == null ) 159 { 160 controlTypes = new HashSet<TypeMirror>(); 161 clientsMap.put( clientType, controlTypes ); 162 } 163 164 AnnotationMirror controlMirror = null; 166 for (AnnotationMirror annot : clientType.getAnnotationMirrors()) 167 { 168 if (annot.getAnnotationType().getDeclaration().getQualifiedName().equals( 169 "org.apache.beehive.controls.api.bean.ControlReferences")) 170 { 171 controlMirror = annot; 172 break; 173 } 174 } 175 176 assert( controlMirror != null ); 177 178 AptAnnotationHelper controlAnnot = new AptAnnotationHelper(controlMirror); 180 Collection<AnnotationValue> references = (Collection<AnnotationValue>)controlAnnot.getObjectValue("value"); 181 if ( references != null ) 182 { 183 for ( AnnotationValue av : references ) 184 { 185 TypeMirror crType = (TypeMirror)av.getValue(); 186 controlTypes.add( crType ); 187 } 188 } 189 } 190 } 191 } 192 } 193 194 198 Filer f = getAnnotationProcessorEnvironment().getFiler(); 199 Set <TypeDeclaration> clientTypes = clientsMap.keySet(); 200 for ( TypeDeclaration clientType : clientTypes ) 201 { 202 204 String clientPkg = clientType.getPackage().getQualifiedName(); 205 File clientManifestName = 206 new File ( clientType.getSimpleName() + ControlClientManifest.FILE_EXTENSION ); 207 208 ControlClientManifest mf = new ControlClientManifest( clientType.getQualifiedName() ); 209 210 try 211 { 212 Set <TypeMirror> controlTypes = clientsMap.get( clientType ); 213 for ( TypeMirror controlType : controlTypes ) 214 { 215 InterfaceDeclaration controlIntfOrExt = getControlInterfaceOrExtension(controlType); 216 InterfaceDeclaration controlIntf = getMostDerivedControlInterface( controlIntfOrExt ); 217 218 assert controlIntf != null : "Can't find most derived control intf for=" + controlIntfOrExt; 219 220 ControlInterface annot = controlIntf.getAnnotation(ControlInterface.class); 221 String defBinding = annot.defaultBinding(); 222 223 defBinding = ControlBeanContext.resolveDefaultBinding( defBinding, controlIntf.getQualifiedName() ); 224 225 mf.addControlType( controlIntfOrExt.getQualifiedName(), defBinding ); 226 } 227 228 mf.emit( f, clientPkg, clientManifestName, null ); 229 } 230 catch ( IOException ie ) 231 { 232 printError( clientType, "controls.client.manifest.ioerror" ); 233 ie.printStackTrace( ); 234 } 235 236 238 AnnotationProcessorEnvironment env = getAnnotationProcessorEnvironment(); 239 Generator genClass = new AptControlClient( clientType, this ); 240 241 if ( genClass != null ) 242 { 243 try 244 { 245 List<GeneratorOutput> genList = genClass.getGenerateOutput(env.getFiler()); 246 if (genList == null || genList.size() == 0) 247 return; 248 249 for (GeneratorOutput genOut : genList) 250 { 251 getGenerator().generate(genOut); 252 } 253 } 254 catch (IOException ioe) 255 { 256 throw new CodeGenerationException("Code generation failure: ", ioe); 257 } 258 } 259 } 260 } 261 262 @Override 263 public void generate(Declaration decl) 264 { 265 } 266 267 private void checkControlField( FieldDeclaration f ) 268 { 269 TypeMirror fieldType = f.getType(); 270 271 String fieldName = f.getSimpleName(); 273 TypeDeclaration declaringType = f.getDeclaringType(); 274 275 if ( declaringType instanceof ClassDeclaration ) 276 { 277 for ( ClassType i = ( ( ClassDeclaration ) declaringType ).getSuperclass(); i != null; i = i.getSuperclass() ) 278 { 279 ClassDeclaration decl = i.getDeclaration(); 280 281 if ( decl != null ) 282 { 283 for ( FieldDeclaration baseClassField : decl.getFields() ) 284 { 285 if ( fieldName.equals( baseClassField.getSimpleName() ) ) 286 { 287 Collection<Modifier> modifiers = baseClassField.getModifiers(); 288 289 if ( modifiers.contains( Modifier.PROTECTED ) || modifiers.contains( Modifier.PUBLIC ) ) 290 { 291 printError( f, "control.field.override", decl.getQualifiedName() ); 292 } 293 } 294 } 295 } 296 } 297 } 298 299 if ( fieldType instanceof InterfaceType ) 302 { 303 Declaration fieldTypeDecl = ((InterfaceType)fieldType).getDeclaration(); 306 if ( fieldTypeDecl.getAnnotation(ControlInterface.class) == null && 307 fieldTypeDecl.getAnnotation(ControlExtension.class) == null ) 308 printError( f, "control.field.bad.interfacetype" ); 309 } 310 else if ( fieldType instanceof ClassType ) 311 { 312 314 boolean foundControlBean = false; 321 ClassType classType = (ClassType)fieldType; 322 323 if (classType.getDeclaration() != null) 324 { 325 outer: while ( classType != null ) 326 { 327 Collection<InterfaceType> intfs = classType.getSuperinterfaces(); 328 for ( InterfaceType intfType : intfs ) 329 { 330 if ( intfType.getDeclaration().getQualifiedName().equals( "org.apache.beehive.controls.api.bean.ControlBean" ) ) 331 { 332 foundControlBean = true; 333 break outer; 334 } 335 } 336 classType = classType.getSuperclass(); 337 } 338 if ( !foundControlBean ) 339 printError( f, "control.field.bad.classtype" ); 340 341 classType = (ClassType)fieldType; 343 Collection<InterfaceType> intfs = classType.getSuperinterfaces(); 344 if ( intfs.size() != 1 ) 345 { 346 printError( f, "control.field.bad.classtype.badinterface" ); 347 } 348 349 for ( InterfaceType intfType : intfs ) 350 { 351 if ( intfType.getDeclaration().getAnnotation(ControlExtension.class) == null && 352 intfType.getDeclaration().getAnnotation(ControlInterface.class) == null) 353 { 354 printError( f, "control.field.bad.classtype.badinterface"); 355 } 356 } 357 } 358 else 359 { 360 } 367 } 368 else 369 { 370 printError( f, "control.field.bad.type" ); 371 } 372 373 try 379 { 380 InterfaceDeclaration controlIntfOrExt = getControlInterfaceOrExtension(fieldType); 381 InterfaceDeclaration controlIntf = getMostDerivedControlInterface( controlIntfOrExt ); 382 383 if ( controlIntf != null ) 384 { 385 enforceVersionRequired( f, controlIntf ); 386 } 387 else 388 { 389 printError( f, "control.field.type.malformed" ); 390 } 391 } 392 catch ( CodeGenerationException cge ) 393 { 394 printError( f, "control.field.type.malformed" ); 395 } 396 397 assert declaringType != null : "Field " + f + " has no declaring type!"; 398 399 if ( declaringType.getDeclaringType() != null ) 400 printError( f, "control.field.in.inner.class" ); 401 402 Collection<Modifier> mods = f.getModifiers(); 403 404 if ( mods.contains( Modifier.TRANSIENT )) 405 printError( f, "transient.control.field" ); 406 407 if ( mods.contains( Modifier.STATIC )) 408 printError( f, "static.control.field" ); 409 410 } 411 412 private void checkControlClientType( TypeDeclaration t ) 413 { 414 AnnotationMirror controlMirror = null; 416 417 for (AnnotationMirror annot : t.getAnnotationMirrors()) 418 { 419 if (annot.getAnnotationType().getDeclaration().getQualifiedName().equals( 420 "org.apache.beehive.controls.api.bean.ControlReferences")) 421 { 422 controlMirror = annot; 423 break; 424 } 425 } 426 427 if ( controlMirror == null ) 429 return; 430 431 AptAnnotationHelper controlAnnot = new AptAnnotationHelper(controlMirror); 432 433 438 Collection<AnnotationValue> references = (Collection<AnnotationValue>)controlAnnot.getObjectValue("value"); 439 440 if ( references != null ) 441 { 442 for ( AnnotationValue av : references ) 443 { 444 DeclaredType crType = (DeclaredType)av.getValue(); 445 if ( crType instanceof InterfaceType ) 446 { 447 Declaration typeDecl = crType.getDeclaration(); 450 if ( typeDecl.getAnnotation(ControlInterface.class) == null && 451 typeDecl.getAnnotation(ControlExtension.class) == null ) 452 printError( t, "control.reference.bad.interfacetype" ); 453 } 454 } 455 } 456 } 457 458 464 private InterfaceDeclaration getControlInterfaceOrExtension( TypeMirror intfOrBeanClass ) 465 { 466 if (intfOrBeanClass instanceof InterfaceType) 467 { 468 return ((InterfaceType)intfOrBeanClass).getDeclaration(); 469 } 470 else if (intfOrBeanClass instanceof ClassType) 471 { 472 ClassType classType = (ClassType)intfOrBeanClass; 473 474 if (classType.getDeclaration() == null) 478 { 479 String className = classType.toString(); 484 String intfName = className.substring(0, className.length() - 4); 485 AnnotationProcessorEnvironment ape = getAnnotationProcessorEnvironment(); 486 InterfaceDeclaration id = (InterfaceDeclaration)ape.getTypeDeclaration(intfName); 487 if (id == null) 488 { 489 for (TypeDeclaration td :ape.getSpecifiedTypeDeclarations()) 492 { 493 if (td instanceof InterfaceDeclaration && 494 td.getSimpleName().equals(intfName)) 495 { 496 return (InterfaceDeclaration)td; 497 } 498 } 499 } 500 return id; 501 } 502 else 503 { 504 Collection<InterfaceType> intfs = classType.getSuperinterfaces(); 506 507 assert ( intfs.size() == 1 ); 510 for ( InterfaceType intfType : intfs ) 511 return intfType.getDeclaration(); 512 } 513 } 514 else 515 { 516 throw new CodeGenerationException( "Param not a interface or class type"); 517 } 518 519 return null; 520 } 521 522 531 private InterfaceDeclaration getMostDerivedControlInterface( InterfaceDeclaration controlIntfOrExt ) 532 { 533 Queue<InterfaceDeclaration> q = new LinkedList<InterfaceDeclaration>(); 534 535 InterfaceDeclaration id = controlIntfOrExt; 536 while ( id != null ) 537 { 538 if ( id.getAnnotation(ControlInterface.class) != null ) 539 break; 540 541 Collection<InterfaceType> supers = id.getSuperinterfaces(); 542 for ( InterfaceType s : supers ) 543 q.offer( s.getDeclaration() ); 544 545 id = q.poll(); 546 } 547 548 return id; 549 } 550 551 554 private void enforceVersionRequired( FieldDeclaration f, InterfaceDeclaration controlIntf ) 555 { 556 VersionRequired versionRequired = f.getAnnotation(VersionRequired.class); 557 Version versionPresent = controlIntf.getAnnotation(Version.class); 558 559 if ( versionRequired != null ) 560 { 561 int majorRequired = versionRequired.major(); 562 int minorRequired = versionRequired.minor(); 563 564 if ( majorRequired < 0 ) return; 566 567 int majorPresent = -1; 568 int minorPresent = -1; 569 if ( versionPresent != null ) 570 { 571 majorPresent = versionPresent.major(); 572 minorPresent = versionPresent.minor(); 573 574 if ( majorRequired <= majorPresent && 575 (minorRequired < 0 || minorRequired <= minorPresent) ) 576 { 577 return; 579 } 580 } 581 582 printError( f, "control.field.bad.version", f.getSimpleName(), majorRequired, minorRequired, 586 majorPresent, minorPresent ); 587 } 588 } 589 590 594 protected CodeGenerator getGenerator() 595 { 596 if (_generator == null) 597 { 598 AnnotationProcessorEnvironment env = getAnnotationProcessorEnvironment(); 602 603 try 604 { 605 _generator = new VelocityGenerator(env); 606 } 607 catch (Exception e) 608 { 609 throw new CodeGenerationException("Unable to create code generator", e); 610 } 611 } 612 return _generator; 613 } 614 615 CodeGenerator _generator; 616 } 617 | Popular Tags |