KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > beehive > controls > runtime > generator > AptControlInterface


1 package org.apache.beehive.controls.runtime.generator;
2 /*
3  * Copyright 2004 The Apache Software Foundation.
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  * $Header:$
18  */

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 /**
51  * The AptControlInterface provides validation and metadata management for a ControlInterface
52  * or ControlExtension class during APT processing. It is also used to model the interface
53  * to contextual services, since they parallel the conventions of control interfaces.
54  */

55 public class AptControlInterface extends AptType implements Generator
56 {
57     /**
58      * Constructs a new AptControlInterface instance where interface information is derived
59      * from an APT interface declaration
60      * @param decl the annotated Declaration
61      * @param ap the top-level annotation processor
62      */

63     public AptControlInterface(Declaration decl, TwoPhaseAnnotationProcessor ap)
64     {
65         _ap = ap;
66
67         //
68
// Verify that the @ControlInterface/@ControlExtension annotations are only used on an
69
// interface.
70
// Note: AptControlInterface is also used to construct the operation and event model
71
// for contextual services (see AptContextField). Becaue contextual sevices can actually
72
// be classes as well as interfaces, the test below has to be specific to the annotated
73
// use cases
74
//
75
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         //
102
// Construct a bean instance for this interface
103
//
104
_bean = new ControlBean(this);
105
106         //
107
// Enforce VersionRequired semantics
108
//
109
enforceVersionRequired();
110
111         //
112
// Do work specific to control extensions
113
//
114

115         if (isExtension())
116         {
117             //
118
// If this is an control extension, run the control-author-specified
119
// checker class to perform additional validation.
120
//
121
check();
122         }
123     }
124
125     /**
126      * Returns the parent control interface or extension type from which the control
127      * interface is derived (or null, if it is at the root of the interface hierarchy)
128      */

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     /**
152      * Initializes the super interface that this ControlInterface extends (or sets it to null
153      * if a base interface)
154      */

155     private AptControlInterface initSuperClass()
156     {
157         //
158
// Look for a super interface that is either a control interface or extension.
159
// If found, return it.
160
//
161
InterfaceType superType = getSuperType();
162         if (superType == null)
163         {
164             // At this point, we're processing the root of the interface heirarchy,
165
// which is not permitted to be a ControlExtension (that would imply a
166
// ControlExtension that wasn't actually extending a ControlInterface).
167
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     /**
196      * Returns the super interface for this interface
197      */

198     public AptControlInterface getSuperClass() { return _superClass; }
199
200     /**
201      * Initializes the list of operations declared by this AptControlInterface
202      */

203     private AptMethodSet<AptOperation> initOperations()
204     {
205         AptMethodSet<AptOperation> operList = new AptMethodSet<AptOperation>();
206
207         if ( _intfDecl == null )
208             return operList;
209
210         //
211
// Add the methods from the current interface and all super interfaces *other*
212
// than the one from which control inheritance or extension is defined. These
213
// exceptions are handled on the super ControlInterface (the return value
214
// of AptControlInterface.initSuperClass())
215
//
216
// Do this by:
217
// - initially populate the check vector with the control interface
218
// - iterate through the check vector, examining each interface to:
219
// * ignore the super interface
220
// * add all declared interface methods to the operations list
221
// * add any super interfaces to the Vector (avoiding recursion)
222
// - the iteration continues until all superinterfaces have been processed
223
//
224
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             // Add all declared methods, but ignore the mystery <clinit> methods
237
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     /**
256      * Returns the list of ControlOperations declared directly by this AptControlInterface
257      */

258     public Collection<AptOperation> getOperations() { return _operations.getMethods(); }
259
260     /**
261      * Returns the total number of operations for this control interface
262      */

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     /**
273      * Initializes the list of PropertySets declared or referenced by this AptControlInterface
274      */

275     private ArrayList<AptPropertySet> initPropertySets()
276     {
277         ArrayList<AptPropertySet> propSets = new ArrayList<AptPropertySet>();
278
279         if ( _intfDecl == null )
280             return propSets;
281
282         // TODO: enforce presence of prefixes when multiple property sets w/ the same
283
// property name exist
284

285         //
286
// Add the intrinsic/base property set
287
//
288

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         //
297
// Add external property sets
298
//
299
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 JavaDoc[] extProps = extPropsAnnotation.value();
310             }
311             catch ( MirroredTypesException mte )
312             {
313                 Collection<String JavaDoc> extProps = mte.getQualifiedNames();
314                 for ( String JavaDoc 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         //
331
// Add nested property sets
332
//
333

334         if ( _intfDecl.getNestedTypes() == null )
335             return propSets;
336
337         for (TypeDeclaration innerDecl : _intfDecl.getNestedTypes())
338         {
339             boolean fError = false;
340
341             // HACKHACK: There appear to be mirror API bugs where calling getAnnotation()
342
// on certain entity types will result in an endless loop. For now, work around
343
// this by a priori filtering... but this mechanism will drop errors that appear
344
// on an inapropriate type (see check below)
345
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         //
376
// Detect the presence of locally declared bound or constrained properties
377
// Enforce property name (including prefix) uniqueness across all propertysets on this interface.
378
//
379

380         Set<String JavaDoc> propertyNames = new HashSet<String JavaDoc>();
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 JavaDoc 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     /**
409      * Returns the list of PropertySets declared directly by this AptControlInterface
410      */

411     public Collection<AptPropertySet> getPropertySets() { return _propertySets; }
412
413     /**
414      * Returns the total number of properties for this control interface
415      */

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     /**
431      * Returns true if the interface has any bound properties associated with it.
432      */

433     public boolean hasBoundProperties()
434     {
435         if (_superClass != null && _superClass.hasBoundProperties())
436             return true;
437
438         return _hasBoundProperties;
439     }
440
441     /**
442      * Returns true if this interface is the first interface in the inheritance hierarchy
443      * to declare support for bound properties. This is used to declared PropertyChangeListener
444      * registration methods for the bean once (and only once).
445      */

446     public boolean addsBoundPropertySupport()
447     {
448         //
449
// If a super interface has already added support, then not added here
450
//
451
if (_superClass != null && _superClass.addsBoundPropertySupport())
452             return false;
453
454         return hasBoundProperties();
455     }
456
457     /**
458      * Returns true if any properties declared directly by this control interface are constrained
459      * properties. This <b>will not</b> reflect the attributes of properties declared on
460      * an interface from which this interface derives.
461      */

462     public boolean hasConstrainedProperties()
463     {
464         if (_superClass != null && _superClass.hasConstrainedProperties())
465             return true;
466
467         return _hasConstrainedProperties;
468     }
469
470     /**
471      * Returns true if this interface is the first interface in the inheritance hierarchy
472      * to declare support for constrained properties. This is used to declared
473      * VetoableChangeListener registration methods for the bean once (and only once).
474      */

475     public boolean addsConstrainedPropertySupport()
476     {
477         //
478
// If a super interface has already added support, then not added here
479
//
480
if (_superClass != null && _superClass.addsConstrainedPropertySupport())
481             return false;
482
483         return hasConstrainedProperties();
484     }
485
486     /**
487      * Initializes the list of EventSets declared by this AptControlInterface
488      */

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             // HACKHACK: There appear to be mirror API bugs where calling getAnnotation()
499
// on certain entity types will result in an endless loop. For now, work around
500
// this by a priori filtering... but this mechanism will drop errors that appear
501
// on an inapropriate type (see check below)
502
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     /**
523      * Returns the list of AptEventSet declared directly by this AptControlInterface
524      */

525     public Collection<AptEventSet> getEventSets() { return _eventSets; }
526
527     /**
528      * Returns the total number of operations for this control interface
529      */

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     /**
540      * Returns the AptEventSet with the specified name
541      */

542     public AptEventSet getEventSet(String JavaDoc 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     /**
555      * Returns the FeatureInfo attributes for this control interface
556      */

557     public FeatureInfo getFeatureInfo() { return _featureInfo; }
558
559     /**
560      * Returns the list of fully qualified class names for types that are derived
561      * from this Generator
562      */

563     public String JavaDoc [] getGeneratedTypes()
564     {
565         return new String JavaDoc [] { _bean.getClassName() };
566     }
567
568     /**
569      * Returns the Version annotation, if any.
570      */

571     public Version getVersion()
572     {
573         return _version;
574     }
575
576     /**
577      * Returns the VersionRequired annotation, if any.
578      */

579     public VersionRequired getVersionRequired()
580     {
581         return _versionRequired;
582     }
583
584     /**
585      * Returns the information necessary to generate a ControlBean from this AptControlInterface
586      */

587     public List<GeneratorOutput> getCheckOutput(Filer filer) throws IOException
588     {
589         HashMap<String JavaDoc,Object JavaDoc> map = new HashMap<String JavaDoc,Object JavaDoc>();
590
591         map.put("intf", this); // the control interface
592
map.put("bean", _bean);
593
594         ArrayList<GeneratorOutput> genList = new ArrayList<GeneratorOutput>();
595
596         //
597
// the ControlBean class
598
//
599
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         //
606
// the ControlBean BeanInfo class
607
//
608
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     /**
618      * Returns the information necessary to generate a packaging information from this
619      * AptControlInterface. Since this information is not needed during type validation,
620      * it can be delated until the generate phase.
621      */

622     public List<GeneratorOutput> getGenerateOutput(Filer filer) throws IOException
623     {
624         HashMap<String JavaDoc,Object JavaDoc> map = new HashMap<String JavaDoc,Object JavaDoc>();
625
626         map.put("intf", this); // the control interface
627
map.put("bean", _bean);
628
629         ArrayList<GeneratorOutput> genList = new ArrayList<GeneratorOutput>();
630
631         //
632
// the ControlBean MANIFEST.MF section
633
//
634
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     /**
647      * Returns true if this interface is a ControlExtension (jcx) interface, false
648      * otherwise.
649      */

650     public boolean isExtension()
651     {
652         return _isExtension;
653     }
654
655     /**
656      * Returns the most-derived interface in the inheritance chain that is annotated
657      * with @ControlInterface. It represents the point in the inheritance chain
658      * where @ControlInterface becomes @ControlExtension (i.e., anything interface derived from
659      * the 'most-derived interface' is annotated with @ControlExtension). May return
660      * null if the inheritance chain is malformed.
661      */

662     public AptControlInterface getMostDerivedInterface()
663     {
664         //
665
// Walk up ControlInterface chain looking for the 1st instance annotated
666
// w/ @ControlInterface (as opposed to @ControlExtension)
667
//
668
// REVIEW: TBD rules for inheritance of @ControlInterface will affect this.
669
// Probably need to keep walking and examine each @ControlInterface in the chain.
670
// Run all checkers in chain? Make checkers responsible for invoking their base
671
// class-defined checkers?
672
//
673

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     /**
687      * Returns a classloader that can be used to load external classes
688      */

689     public ClassLoader JavaDoc getExternalClassLoader()
690     {
691         Map<String JavaDoc,String JavaDoc> opts = _ap.getAnnotationProcessorEnvironment().getOptions();
692         String JavaDoc classpath = opts.get("-classpath");
693
694         if ( classpath != null )
695         {
696             String JavaDoc [] cpEntries = classpath.split( File.pathSeparator );
697             ArrayList a = new ArrayList();
698             for ( String JavaDoc 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 JavaDoc 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     //
722
// These are defined by the JAR spec, Name-value pair section
723
//
724
static final String JavaDoc alphaNum = "ABCDEFGHIJKLMNOPQRSUVWXYZabcdefghijklmnopqrstuvwyz0123456789";
725     static final String JavaDoc headerChar = alphaNum + "_-";
726
727     /**
728      * Validates a manifest attribute. If the attribute is invalid, it will generate
729      * appropriate APT messager entries and return false, else return true.
730      */

731     private boolean isValidManifestAttribute(ManifestAttribute attr)
732     {
733         String JavaDoc name = attr.name();
734         String JavaDoc 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             // TODO: validate string contents are valid UTF-8?
767
}
768
769         return isValid;
770     }
771
772     /**
773      * Returns the array of ManifestAttributes associated with the AptControlInterface
774      */

775     public HashMap<String JavaDoc, String JavaDoc> getManifestAttributes()
776     {
777         HashMap<String JavaDoc,String JavaDoc> attributes = new HashMap<String JavaDoc,String JavaDoc>();
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 JavaDoc e) { e.printStackTrace(); return attributes; }
803     }
804
805     /**
806      * Computes whether this interface is a ControlInterface or a ControlExtension
807      */

808     private boolean initIsExtension()
809     {
810         if ( _intfDecl == null )
811             return false;
812
813         return _intfDecl.getAnnotation(ControlExtension.class) != null;
814     }
815
816     /**
817      * Returns the FeatureInfo annotation for this control interface, or null if there is none.
818      */

819     private FeatureInfo initFeatureInfo()
820     {
821         if ( _intfDecl == null )
822             return null;
823         return _intfDecl.getAnnotation(FeatureInfo.class);
824     }
825
826     /**
827      * Returns the Version annotation for this control interface, or null if there is none.
828      */

829     private Version initVersion()
830     {
831         if ( _intfDecl == null )
832             return null;
833         return _intfDecl.getAnnotation(Version.class);
834     }
835
836     /**
837      * Returns the VersionRequired annotation for this control interface, or null if there is none.
838      */

839     private VersionRequired initVersionRequired()
840     {
841         if ( _intfDecl == null )
842             return null;
843         return _intfDecl.getAnnotation(VersionRequired.class);
844     }
845
846     /**
847      * Enforces the VersionRequired annotation for control extensions.
848      */

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 ) // no real version requirement
863
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                     // Version requirement is satisfied
881
return;
882                 }
883             }
884
885             //
886
// Version requirement failed
887
//
888
_ap.printError( _intfDecl, "versionrequired.failed", _intfDecl.getSimpleName(),
889                     majorRequired, minorRequired, majorPresent, minorPresent );
890         }
891     }
892
893     /**
894      * Runs control-specific checker class (if specified)
895      */

896     public void check()
897     {
898         //
899
// Find the nearest @ControlInterface, which is where the relevant control checker
900
// annotation will be found.
901
//
902

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         //
929
// Read the name of the checker class from the @ControlInterface annotation,
930
// dynamically load and run it.
931
//
932

933         DeclaredType checkerMirror = (DeclaredType)controlAnnot.getObjectValue("checker");
934         if ( checkerMirror == null )
935         {
936             // try the deprecated 'checkerClass' attribute
937
checkerMirror = (DeclaredType)controlAnnot.getObjectValue("checkerClass");
938         }
939
940         if ( checkerMirror != null && checkerMirror.getDeclaration() != null )
941         {
942             // TODO: optimize to not invoke default checker?
943
String JavaDoc checkerName = checkerMirror.toString();
944
945             try
946             {
947                 ClassLoader JavaDoc loader = getExternalClassLoader();
948
949                 Class JavaDoc 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 JavaDoc 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; // true if ControlExtension, else ControlInterface
974
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