KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > beehive > netui > compiler > CompilerUtils


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

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 JavaDoc;
34 import java.net.URI JavaDoc;
35 import java.net.URISyntaxException JavaDoc;
36 import java.util.ArrayList JavaDoc;
37 import java.util.Collection JavaDoc;
38 import java.util.Collections JavaDoc;
39 import java.util.Iterator JavaDoc;
40 import java.util.List JavaDoc;
41 import java.util.Map JavaDoc;
42 import java.util.Set JavaDoc;
43 import java.util.HashMap JavaDoc;
44
45
46 public class CompilerUtils
47         implements JpfLanguageConstants
48 {
49     private static final String JavaDoc ERROR_STRING = "<error>";
50     private static final TypeDeclaration ERROR_TYPE_DECLARATION = new ErrorTypeDeclaration();
51     
52     public static boolean isJpfAnnotation( AnnotationInstance annotation, String JavaDoc unqualifiedName )
53     {
54         String JavaDoc annotationName = getDeclaration( annotation.getAnnotationType() ).getQualifiedName();
55         return annotationName.equals( ANNOTATION_QUALIFIER + unqualifiedName );
56     }
57     
58     public static AnnotationInstance getAnnotation( Declaration element, String JavaDoc unqualifiedName )
59     {
60         return getAnnotationFullyQualified( element, ANNOTATION_QUALIFIER + unqualifiedName );
61     }
62     
63     public static AnnotationInstance getAnnotationFullyQualified( Declaration element, String JavaDoc 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 JavaDoc 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 JavaDoc annotationName, String JavaDoc valueName )
78     {
79         AnnotationInstance ann = getAnnotation( element, annotationName );
80         return ann != null ? getAnnotationValue( ann, valueName, true ) : null;
81     }
82     
83     /**
84      * If the given annotation exists, assert that the given member is not null</code>, and return it; otherwise,
85      * if the given annotation does not exist, return null</code>.
86      */

87     private static AnnotationValue assertAnnotationValue( Declaration element, String JavaDoc annotationName, String JavaDoc 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 JavaDoc getStringValue( Declaration element, String JavaDoc annotationName, String JavaDoc memberName,
103                                          boolean defaultIsNull )
104     {
105         return ( String JavaDoc ) getValue( element, annotationName, memberName, defaultIsNull );
106     }
107     
108     public static AnnotationValue getAnnotationValue( AnnotationInstance annotation, String JavaDoc memberName,
109                                                       boolean defaultIsNull )
110     {
111         Map JavaDoc valuesPresent = annotation.getElementValues();
112         
113         for ( Iterator JavaDoc ii = valuesPresent.entrySet().iterator(); ii.hasNext(); )
114         {
115             Map.Entry JavaDoc i = ( Map.Entry JavaDoc ) ii.next();
116             if ( memberName.equals( ( ( AnnotationTypeElementDeclaration ) i.getKey() ).getSimpleName() ) )
117             {
118                 return ( AnnotationValue ) i.getValue();
119             }
120         }
121         
122         //
123
// We didn't find it. If necessary, look for the default value.
124
//
125
if ( defaultIsNull ) return null;
126         
127         AnnotationTypeDeclaration typeDecl = annotation.getAnnotationType().getAnnotationTypeDeclaration();
128         if ( typeDecl == null ) return null; // type declaration is null in the case of error type
129

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 JavaDoc getStringArrayValue( Declaration element, String JavaDoc annotationName, String JavaDoc memberName,
143                                                       boolean defaultIsNull )
144     {
145         AnnotationValue value = assertAnnotationValue( element, annotationName, memberName, defaultIsNull );
146         if ( value == null ) return null;
147         ArrayList JavaDoc ret = new ArrayList JavaDoc();
148         getValues( value, ret, false );
149         return ret;
150     }
151     
152     public static Boolean JavaDoc getBooleanValue( Declaration element, String JavaDoc annotationName, String JavaDoc memberName,
153                                            boolean defaultIsNull )
154     {
155         AnnotationValue value = assertAnnotationValue( element, annotationName, memberName, defaultIsNull );
156         return value != null ? ( Boolean JavaDoc ) value.getValue() : null;
157     }
158     
159     public static String JavaDoc getString( AnnotationInstance annotation, String JavaDoc memberName, boolean defaultIsNull )
160     {
161         AnnotationValue value = getAnnotationValue( annotation, memberName, defaultIsNull );
162         return value != null ? ( String JavaDoc ) value.getValue() : ( defaultIsNull ? null : "" );
163     }
164     
165     public static TypeInstance getTypeInstance( AnnotationInstance annotation, String JavaDoc 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 JavaDoc getEnumFieldName( AnnotationInstance annotation, String JavaDoc memberName, boolean defaultIsNull )
172     {
173         AnnotationValue value = getAnnotationValue( annotation, memberName, defaultIsNull );
174         return value != null ? getEnumFieldName( value ) : null;
175     }
176     
177     public static List JavaDoc getStringArray( AnnotationInstance annotation, String JavaDoc memberName, boolean defaultIsNull )
178     {
179         AnnotationValue value = getAnnotationValue( annotation, memberName, defaultIsNull );
180         if ( value == null ) return null;
181         ArrayList JavaDoc ret = new ArrayList JavaDoc();
182         getValues( value, ret, false );
183         return ret;
184     }
185     
186     public static DeclaredType getDeclaredType( AnnotationInstance annotation, String JavaDoc memberName, boolean defaultIsNull )
187     {
188         return ( DeclaredType ) getReferenceType( annotation, memberName, defaultIsNull );
189     }
190     
191     public static ReferenceType getReferenceType( AnnotationInstance annotation, String JavaDoc memberName, boolean defaultIsNull )
192     {
193         AnnotationValue value = getAnnotationValue( annotation, memberName, defaultIsNull );
194         
195         // If the type is the string "<error>", it means that there is already an error related to the type itself.
196
if ( value != null && isErrorString( value.getValue() ) ) return null;
197         
198         return value != null ? ( ReferenceType ) value.getValue() : null;
199     }
200     
201     public static Integer JavaDoc getInteger( AnnotationInstance annotation, String JavaDoc memberName, boolean defaultIsNull )
202     {
203         AnnotationValue value = getAnnotationValue( annotation, memberName, defaultIsNull );
204         if ( value == null ) return defaultIsNull ? null : new Integer JavaDoc( 0 );
205         Object JavaDoc result = value.getValue();
206         
207         if ( result instanceof String JavaDoc )
208         {
209             assert isErrorString( result ) : result;
210             return new Integer JavaDoc( 0 );
211         }
212         
213         return ( Integer JavaDoc ) value.getValue();
214     }
215     
216     public static boolean isErrorString( Object JavaDoc str )
217     {
218         return ERROR_STRING.equals( str );
219     }
220     
221     public static Long JavaDoc getLong( AnnotationInstance annotation, String JavaDoc memberName, boolean defaultIsNull )
222     {
223         AnnotationValue value = getAnnotationValue( annotation, memberName, defaultIsNull );
224         if ( value == null ) return defaultIsNull ? null : new Long JavaDoc( 0 );
225         Object JavaDoc result = value.getValue();
226         
227         if ( result instanceof String JavaDoc )
228         {
229             assert result.equals( ERROR_STRING ) : result;
230             return new Long JavaDoc( 0 );
231         }
232         
233         return ( Long JavaDoc ) value.getValue();
234     }
235     
236     public static Float JavaDoc getFloat( AnnotationInstance annotation, String JavaDoc memberName, boolean defaultIsNull )
237     {
238         AnnotationValue value = getAnnotationValue( annotation, memberName, defaultIsNull );
239         if ( value == null ) return defaultIsNull ? null : new Float JavaDoc( 0 );
240         Object JavaDoc result = value.getValue();
241         
242         if ( result instanceof String JavaDoc )
243         {
244             assert result.equals( ERROR_STRING ) : result;
245             return new Float JavaDoc( 0 );
246         }
247         
248         return ( Float JavaDoc ) value.getValue();
249     }
250     
251     public static Double JavaDoc getDouble( AnnotationInstance annotation, String JavaDoc memberName, boolean defaultIsNull )
252     {
253         AnnotationValue value = getAnnotationValue( annotation, memberName, defaultIsNull );
254         if ( value == null ) return defaultIsNull ? null : new Double JavaDoc( 0 );
255         Object JavaDoc result = value.getValue();
256         
257         if ( result instanceof String JavaDoc )
258         {
259             assert result.equals( ERROR_STRING ) : result;
260             return new Double JavaDoc( 0 );
261         }
262         
263         return ( Double JavaDoc ) value.getValue();
264     }
265     
266     public static Boolean JavaDoc getBoolean( AnnotationInstance annotation, String JavaDoc memberName, boolean defaultIsNull )
267     {
268         AnnotationValue value = getAnnotationValue( annotation, memberName, defaultIsNull );
269         if ( value == null ) return defaultIsNull ? null : Boolean.FALSE;
270         Object JavaDoc result = value.getValue();
271         
272         if ( result instanceof String JavaDoc )
273         {
274             assert result.equals( ERROR_STRING ) : result;
275             return Boolean.FALSE;
276         }
277         
278         return ( Boolean JavaDoc ) value.getValue();
279     }
280     
281     public static Object JavaDoc getValue( Declaration element, String JavaDoc annotationName, String JavaDoc 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 JavaDoc getAnnotationArrayValue( Declaration element, String JavaDoc annotationName,
288                                                                     String JavaDoc memberName, boolean defaultIsNull )
289     {
290         AnnotationValue value = assertAnnotationValue( element, annotationName, memberName, defaultIsNull );
291         if ( value == null ) return null;
292         ArrayList JavaDoc ret = new ArrayList JavaDoc();
293         getValues( value, ret, true );
294         return ret;
295     }
296     
297     public static List JavaDoc getAnnotationArray( AnnotationInstance annotation, String JavaDoc memberName,
298                                                                boolean defaultIsNull )
299     {
300         AnnotationValue value = getAnnotationValue( annotation, memberName, defaultIsNull );
301         return getAnnotationArray( value );
302     }
303     
304     public static List JavaDoc getAnnotationArray( AnnotationValue value )
305     {
306         if ( value == null ) return null;
307         ArrayList JavaDoc ret = new ArrayList JavaDoc();
308         getValues( value, ret, true );
309         return ret;
310     }
311     
312     private static void getValues( AnnotationValue arrayValue, List JavaDoc translatedValues, boolean weedOutErrorType )
313     {
314         List JavaDoc values = ( List JavaDoc ) arrayValue.getValue();
315         for ( Iterator JavaDoc ii = values.iterator(); ii.hasNext(); )
316         {
317             Object JavaDoc i = ii.next();
318             Object JavaDoc value = i instanceof AnnotationValue ? ( ( AnnotationValue ) i ).getValue() : i;
319             if ( ! weedOutErrorType || ! isErrorString( value ) ) translatedValues.add( value );
320         }
321     }
322     
323     public static String JavaDoc getQualifiedName( AnnotationInstance annotation )
324     {
325         return getDeclaration( annotation.getAnnotationType() ).getQualifiedName();
326     }
327     
328     public static String JavaDoc getSimpleName( AnnotationInstance annotation )
329     {
330         return getDeclaration( annotation.getAnnotationType() ).getSimpleName();
331     }
332     
333     public static AnnotationInstance getAnnotation( AnnotationInstance annotation, String JavaDoc 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 JavaDoc methodName, String JavaDoc desiredAnnotation )
340     {
341         return getClassMethod( jclass, methodName, desiredAnnotation, false );
342     }
343     
344     private static MethodDeclaration getClassMethod( TypeDeclaration type, String JavaDoc methodName, String JavaDoc 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 JavaDoc fieldName, String JavaDoc desiredAnnotation )
377     {
378         return getClassField( jclass, fieldName, desiredAnnotation, false );
379     }
380     
381     private static FieldDeclaration getClassField( TypeDeclaration type, String JavaDoc fieldName, String JavaDoc 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 JavaDoc desiredAnnotation )
414     {
415         Collection JavaDoc results = new ArrayList JavaDoc();
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 JavaDoc desiredAnnotation, boolean onlyPublicOrPrivate,
421                                          Collection JavaDoc 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                     //
440
// Make sure we're not adding a duplicate method -- one that was already overridden.
441
//
442
if ( onlyPublicOrPrivate )
443                     {
444                         ParameterDeclaration[] methodParams = method.getParameters();
445                         
446                         for ( Iterator JavaDoc 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 JavaDoc getClassFields( TypeDeclaration jclass )
488     {
489         Collection JavaDoc results = new ArrayList JavaDoc();
490         getClassFields( jclass, false, results );
491         return results;
492     }
493     
494     private static void getClassFields( TypeDeclaration type, boolean onlyPublicOrPrivate,
495                                         Collection JavaDoc 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 JavaDoc getClassNestedTypes( TypeDeclaration jclass )
516     {
517         Collection JavaDoc results = new ArrayList JavaDoc();
518         getClassNestedTypes( jclass, false, results );
519         return results;
520     }
521     
522     private static void getClassNestedTypes( TypeDeclaration type, boolean onlyPublicOrPrivate,
523                                              Collection JavaDoc 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     /**
545      * Get a Class.forName-able string for the given type signature.
546      */

547     public static String JavaDoc 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 JavaDoc getFormClassName( DeclaredType jclass, AnnotationProcessorEnvironment env )
568     {
569         return getFormClassName( getDeclaration( jclass ), env );
570     }
571     
572     public static boolean isAbsoluteURL( String JavaDoc path )
573     {
574         try
575         {
576             return new URI JavaDoc( path ).getScheme() != null;
577         }
578         catch ( URISyntaxException JavaDoc e )
579         {
580             return false;
581         }
582     }
583     
584     public static boolean isAssignableFrom( String JavaDoc 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 JavaDoc 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 JavaDoc 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 JavaDoc elements, String JavaDoc elementName )
679     {
680         for ( Iterator JavaDoc ii = elements.iterator(); ii.hasNext(); )
681         {
682             Object JavaDoc 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 JavaDoc fieldName )
691     {
692         return ( FieldDeclaration ) findElement( getClassFields( jclass ), fieldName );
693     }
694     
695     public static ClassDeclaration findInnerClass( TypeDeclaration jclass, String JavaDoc innerClassName )
696     {
697         return ( ClassDeclaration ) findElement( getClassNestedTypes( jclass ), innerClassName );
698     }
699     
700     public static String JavaDoc getEnumFieldName( AnnotationValue enumMember )
701     {
702         if ( enumMember == null || enumMember.getValue() == null )
703             return "";
704         else
705             return enumMember.getValue().toString();
706     }
707     
708     /**
709      * Get the qualified name of the given class, with '$' used to separate inner classes; the returned string can be
710      * used with Class.forName().
711      */

712     public static String JavaDoc 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 JavaDoc getLoadableName( DeclaredType jclass )
727     {
728         return getLoadableName( getDeclaration( jclass ) );
729     }
730     
731     public static File JavaDoc 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 JavaDoc _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 JavaDoc 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 JavaDoc 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 JavaDoc propertyName, Object JavaDoc value )
789         {
790             if ( _attributes == null ) _attributes = new HashMap JavaDoc();
791             _attributes.put( propertyName, value );
792         }
793     
794         public Object JavaDoc getAttribute( String JavaDoc 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         //
807
// TODO: This entire method is a workaround for a bug in APT where an annotation may not equal itelf.
808
// If this behavior changes, we want to rely on equals(), not this deep comparison, which is more expensive
809
// and wrong if the two annotations 'look' exactly the same.
810
//
811
if ( ! allowExactDuplicates
812              && env instanceof ExtendedAnnotationProcessorEnvironment
813              && ( ( ExtendedAnnotationProcessorEnvironment ) env ).useEqualsToCompareAnnotations() )
814         {
815             return a1.equals( a2 );
816         }
817         
818         Map JavaDoc vals1 = a1.getElementValues();
819         Map JavaDoc vals2 = a2.getElementValues();
820         
821         if ( vals1.size() != vals2.size() ) return false;
822         
823         
824         Iterator JavaDoc ents1 = vals1.entrySet().iterator();
825         Iterator JavaDoc ents2 = vals2.entrySet().iterator();
826         while ( ents1.hasNext() )
827         {
828             Map.Entry JavaDoc entry1 = ( Map.Entry JavaDoc ) ents1.next();
829             Map.Entry JavaDoc entry2 = ( Map.Entry JavaDoc ) ents2.next();
830             
831             if ( ! ( ( AnnotationTypeElementDeclaration ) entry1.getKey() ).getSimpleName().equals( ( ( AnnotationTypeElementDeclaration ) entry2.getKey() ).getSimpleName() ) ) return false;
832             Object JavaDoc val1 = ( ( AnnotationValue ) entry1.getValue() ).getValue();
833             Object JavaDoc val2 = ( ( AnnotationValue ) entry2.getValue() ).getValue();
834             
835             if ( val1 instanceof Collection JavaDoc )
836             {
837                 if ( ! ( val2 instanceof Collection JavaDoc ) ) return false;
838                 Collection JavaDoc list1 = ( Collection JavaDoc ) val1;
839                 Collection JavaDoc list2 = ( Collection JavaDoc ) val2;
840                 if ( list1.size() != list2.size() ) return false;
841                 Iterator JavaDoc j1 = list1.iterator();
842                 Iterator JavaDoc j2 = list2.iterator();
843                 
844                 while ( j1.hasNext() )
845                 {
846                     Object JavaDoc o1 = ( ( AnnotationValue ) j1.next() ).getValue();
847                     Object JavaDoc 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 JavaDoc _propertyName;
877         private String JavaDoc _type;
878         
879         public BeanPropertyDescriptor( String JavaDoc propertyName, String JavaDoc type )
880         {
881             _propertyName = propertyName;
882             _type = type;
883         }
884         
885         public String JavaDoc getPropertyName()
886         {
887             return _propertyName;
888         }
889         
890         public String JavaDoc 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 JavaDoc propertyName, String JavaDoc 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 JavaDoc returnType = method.getReturnType().toString();
919             
920             if ( ! returnType.equals( "void" ) && method.getParameters().length == 0 )
921             {
922                 String JavaDoc methodName = method.getSimpleName();
923                 String JavaDoc 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                     //
938
// If the first two letters are uppercase, we don't change the first character to lowercase.
939
// This is so that something like getURI has a property name of 'URI' (see JavaBeans spec).
940
//
941
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 JavaDoc getBeanProperties( ClassDeclaration type, boolean getInheritedProperties )
959     {
960         MethodDeclaration[] methods = getInheritedProperties ? getClassMethods( type, null ) : type.getMethods();
961         ArrayList JavaDoc ret = new ArrayList JavaDoc();
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 JavaDoc removeFileExtension( String JavaDoc uri )
983     {
984         int lastDot = uri.lastIndexOf( '.' );
985         return uri.substring( 0, lastDot );
986     }
987     
988     public static TypeDeclaration inferTypeFromPath( String JavaDoc webappRelativePath, AnnotationProcessorEnvironment env )
989     {
990         assert webappRelativePath.startsWith( "/" ) : webappRelativePath;
991         String JavaDoc 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 JavaDoc( "not implemented " );
1012        }
1013
1014        public String JavaDoc getQualifiedName()
1015        {
1016            return ERROR_STRING;
1017        }
1018
1019        /*
1020        public Collection getFormalTypeParameters()
1021        {
1022            return Collections.EMPTY_LIST;
1023        }
1024        */

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 JavaDoc getDocComment()
1052        {
1053            throw new IllegalStateException JavaDoc( "not implemented " );
1054        }
1055
1056        public AnnotationInstance[] getAnnotationInstances()
1057        {
1058            return ANNOTATIONS;
1059        }
1060
1061        /*
1062        public Annotation getAnnotation( Class s )
1063        {
1064            throw new IllegalStateException( "not implemented " );
1065        }
1066        */

1067
1068        public Set JavaDoc getModifiers()
1069        {
1070            return Collections.EMPTY_SET;
1071        }
1072
1073        public String JavaDoc getSimpleName()
1074        {
1075            return getQualifiedName();
1076        }
1077
1078        public SourcePosition getPosition()
1079        {
1080            throw new IllegalStateException JavaDoc( "not implemented " );
1081        }
1082        
1083        public boolean hasModifier( Modifier modifier )
1084        {
1085            return false;
1086        }
1087
1088        /*
1089        public void accept( DeclarationVisitor declarationVisitor )
1090        {
1091            throw new IllegalStateException( "not implemented " );
1092        }
1093        */

1094    }
1095    
1096    /**
1097     * This is the same logic that we have in the runtime, in PageFlowRequestProcessor. Can't share the code, though.
1098     */

1099    public static boolean isAbsoluteURI( String JavaDoc uri )
1100    {
1101         //
1102
// This method needs to be fast, so it can't use java.net.URI.
1103
//
1104
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 JavaDoc _val = null;
1138    
1139        public Mutable()
1140        {
1141        }
1142        
1143        public Mutable( Object JavaDoc val )
1144        {
1145            _val = val;
1146        }
1147    
1148        public void set( Object JavaDoc val )
1149        {
1150            _val = val;
1151        }
1152    
1153        public Object JavaDoc 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 JavaDoc getFileRelativeToSourceFile( TypeDeclaration outerClass, String JavaDoc relativePath,
1171                                                    AnnotationProcessorEnvironment env )
1172            throws FatalCompileTimeException
1173    {
1174        assert relativePath.length() > 0;
1175        
1176        //
1177
// If it starts with '/', just find the webapp-relative file.
1178
//
1179
if ( relativePath.charAt( 0 ) == '/' ) return getWebappRelativeFile( relativePath, true, env );
1180        
1181        //
1182
// Look for the file relative to the source directory of the given class.
1183
//
1184
File JavaDoc sourceFile = getSourceFile( outerClass, false );
1185        File JavaDoc desiredParentDir = sourceFile.getAbsoluteFile().getParentFile();
1186        File JavaDoc retVal = new File JavaDoc( desiredParentDir, relativePath );
1187        
1188        //
1189
// If we still haven't found it, construct a webapp-relative path and look for the file relative to the webapp.
1190
//
1191
if ( ! retVal.exists() )
1192        {
1193            String JavaDoc 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 JavaDoc getWebappRelativeFile( String JavaDoc webappRelativePath, boolean lookInSourceRoots,
1203                                              AnnotationProcessorEnvironment env )
1204        throws FatalCompileTimeException
1205    {
1206        //
1207
// Look for the file out in the web-addressable portion of the webapp.
1208
//
1209
assert webappRelativePath.startsWith( "/" ) : webappRelativePath;
1210        String JavaDoc webContentRoot = getWebContentRoot( env );
1211        File JavaDoc retVal = new File JavaDoc( webContentRoot + webappRelativePath );
1212        
1213        //
1214
// If appropriate, look for the file under all the source roots.
1215
//
1216
if ( ! retVal.exists() && lookInSourceRoots )
1217        {
1218            String JavaDoc[] webSourceRoots = getWebSourceRoots( env );
1219            
1220            for ( int i = 0; i < webSourceRoots.length; i++ )
1221            {
1222                String JavaDoc webSourceRoot = webSourceRoots[i];
1223                File JavaDoc webSourceRelativeFile = new File JavaDoc( webSourceRoot + webappRelativePath );
1224                if ( webSourceRelativeFile.exists() ) return webSourceRelativeFile;
1225            }
1226        }
1227        
1228        return retVal;
1229    }
1230    
1231    public static String JavaDoc[] getWebSourceRoots( AnnotationProcessorEnvironment env )
1232        throws FatalCompileTimeException
1233    {
1234        return ( String JavaDoc[] ) getOption( "web.source.roots", true, env );
1235    }
1236    
1237    public static String JavaDoc getWebContentRoot( AnnotationProcessorEnvironment env )
1238            throws FatalCompileTimeException
1239    {
1240        return ( String JavaDoc ) getOption( "web.content.root", false, env );
1241    }
1242    
1243    public static String JavaDoc getWebBuildRoot( AnnotationProcessorEnvironment env )
1244            throws FatalCompileTimeException
1245    {
1246        return ( String JavaDoc ) getOption( "web.output.root", false, env );
1247    }
1248    
1249    private static Object JavaDoc getOption( String JavaDoc optionName, boolean isList, AnnotationProcessorEnvironment env )
1250        throws MissingOptionException
1251    {
1252        Object JavaDoc cached = env.getAttribute( optionName );
1253        if ( cached != null ) return cached;
1254        
1255        Map JavaDoc options = env.getOptions();
1256        String JavaDoc value = ( String JavaDoc ) options.get( optionName );
1257        
1258        if ( value == null )
1259        {
1260            // TODO: there appears to be a bug in APT where both the key/value are contained in the key
1261
String JavaDoc aptOption = "-A" + optionName + '=';
1262            for ( Iterator JavaDoc i = options.keySet().iterator(); i.hasNext(); )
1263            {
1264                String JavaDoc key = ( String JavaDoc ) 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 JavaDoc retVal = value;
1277        
1278        if ( isList )
1279        {
1280            String JavaDoc[] values = ( ( String JavaDoc ) 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