KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > beehive > netui > compiler > grammar > WebappPathType


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.grammar;
19
20 import org.apache.beehive.netui.compiler.AnnotationMemberType;
21 import org.apache.beehive.netui.compiler.AnnotationGrammar;
22 import org.apache.beehive.netui.compiler.CompilerUtils;
23 import org.apache.beehive.netui.compiler.FlowControllerInfo;
24 import org.apache.beehive.netui.compiler.FatalCompileTimeException;
25 import org.apache.beehive.netui.compiler.typesystem.declaration.AnnotationValue;
26 import org.apache.beehive.netui.compiler.typesystem.declaration.AnnotationInstance;
27 import org.apache.beehive.netui.compiler.typesystem.declaration.MemberDeclaration;
28 import org.apache.beehive.netui.compiler.typesystem.declaration.AnnotationTypeElementDeclaration;
29 import org.apache.beehive.netui.compiler.typesystem.declaration.TypeDeclaration;
30 import org.apache.beehive.netui.compiler.typesystem.declaration.Modifier;
31 import org.apache.beehive.netui.compiler.typesystem.declaration.PackageDeclaration;
32 import org.apache.beehive.netui.compiler.typesystem.env.AnnotationProcessorEnvironment;
33
34 import java.net.URISyntaxException JavaDoc;
35 import java.net.URI JavaDoc;
36 import java.io.File JavaDoc;
37
38 /**
39  * String type that emits a warning if the given path does not exist in the webapp for this pageflow.
40  */

41 public class WebappPathType
42         extends AnnotationMemberType
43 {
44     private static final String JavaDoc[] CHECKABLE_EXTENSIONS =
45             {
46                 JSP_FILE_EXTENSION,
47                 XJSP_FILE_EXTENSION,
48                 JPF_FILE_EXTENSION,
49                 "xml",
50                 "htm",
51                 "html"
52             };
53     
54     private boolean _pathMustBeRelative = false;
55     private FlowControllerInfo _flowControllerInfo;
56     
57     
58     public WebappPathType( boolean pathMustBeRelative, String JavaDoc requiredRuntimeVersion, AnnotationGrammar parentGrammar,
59                            FlowControllerInfo fcInfo )
60     {
61         super( requiredRuntimeVersion, parentGrammar );
62         _pathMustBeRelative = pathMustBeRelative;
63         _flowControllerInfo = fcInfo;
64     }
65
66     private static boolean isCheckableExtension( String JavaDoc filePath )
67     {
68         for ( int i = 0; i < CHECKABLE_EXTENSIONS.length; ++i )
69         {
70             if ( filePath.endsWith( CHECKABLE_EXTENSIONS[i] ) ) return true;
71         }
72         
73         return false;
74     }
75     
76     public Object JavaDoc onCheck( AnnotationTypeElementDeclaration valueDecl, AnnotationValue value,
77                            AnnotationInstance[] parentAnnotations, MemberDeclaration classMember,
78                            int annotationArrayIndex )
79             throws FatalCompileTimeException
80     {
81         String JavaDoc filePath = ( String JavaDoc ) value.getValue();
82         
83         //
84
// First make sure it's a valid URI.
85
//
86
try
87         {
88             URI JavaDoc uri = new URI JavaDoc( filePath );
89             filePath = uri.getPath(); // decodes the path
90
}
91         catch ( URISyntaxException JavaDoc e )
92         {
93             addError( value, "error.invalid-uri", e.getLocalizedMessage() );
94             return null;
95         }
96         
97         //
98
// The path will be null for an 'opaque' URI, like "news:comp.lang.java".
99
//
100
if ( filePath == null || filePath.length() == 0 ) return null;
101         
102         //
103
// Make sure it's a filetype that should exist on the filesystem. If not, ignore it.
104
//
105
if ( ! checkAnyExtension() && ! isCheckableExtension( filePath ) ) return null;
106
107         boolean fileExists = true;
108         TypeDeclaration outerClass = CompilerUtils.getOutermostClass( classMember );
109         File JavaDoc fileToCheck = null;
110
111         if ( filePath.charAt( 0 ) == '/' ) // relative to webapp root
112
{
113             if ( _pathMustBeRelative ) addError( value, "error.relative-uri" );
114             
115             if ( filePath.endsWith( JPF_FILE_EXTENSION_DOT ) )
116             {
117                 TypeDeclaration type = CompilerUtils.inferTypeFromPath( filePath, getEnv() );
118                 fileToCheck = type != null ? CompilerUtils.getSourceFile( type, false ) : null;
119                 
120                 // Note that if we can't infer the file from the type, we'll fall through to the next case, where
121
// we actually look for the file in the webapp.
122
}
123             
124             if ( fileToCheck == null )
125             {
126                 File JavaDoc jpfSourceFile = CompilerUtils.getSourceFile( CompilerUtils.getOuterClass( classMember ), false );
127                 
128                 //
129
// We don't always have the source file for the classMember's containing class (e.g., when this class
130
// extends a class that's on classpath but not sourcepath). If we don't have the source, just ignore.
131
//
132
if ( jpfSourceFile != null )
133                 {
134                     fileToCheck = CompilerUtils.getWebappRelativeFile( filePath, allowFileInPageFlowSourceDir(), getEnv() );
135                     
136                     if ( ! fileToCheck.exists() && ! ( ignoreDirectories() && fileToCheck.isDirectory() ) )
137                     {
138                         fileExists = false;
139                     }
140                 }
141             }
142         }
143         
144         //
145
// If the class being compiled is abstract, don't print warnings for relative-path files that aren't
146
// found. The derived class might have them.
147
//
148
else if ( filePath.indexOf( '/' ) != 0 && ! outerClass.hasModifier( Modifier.ABSTRACT ) )
149         {
150             CompilerUtils.Mutable retFileToCheck = new CompilerUtils.Mutable();
151             fileExists = checkRelativePath( filePath, outerClass, retFileToCheck, ignoreDirectories(),
152                                             allowFileInPageFlowSourceDir(), getEnv() );
153             fileToCheck = ( File JavaDoc ) retFileToCheck.get();
154         }
155
156         if ( fileExists )
157         {
158             if ( fileToCheck != null ) runAdditionalChecks( fileToCheck, value );
159         }
160         else
161         {
162             if ( doFatalError() )
163             {
164                 addError( value, "error.file-not-found", filePath );
165             }
166             else
167             {
168                 addWarning( value, "warning.file-not-found", filePath );
169             }
170         }
171         
172         if ( fileToCheck != null ) _flowControllerInfo.addReferencedFile( fileToCheck );
173         
174         return null;
175     }
176     
177     public static boolean relativePathExists( String JavaDoc filePath, TypeDeclaration outerClass,
178                                               AnnotationProcessorEnvironment env )
179             throws FatalCompileTimeException
180     {
181         assert filePath.charAt( 0 ) != '/' : filePath + " is not a relative path";
182         if ( ! isCheckableExtension( filePath ) ) return true;
183         return checkRelativePath( filePath, outerClass, null, true, false, env );
184     }
185     
186     private static boolean checkRelativePath( String JavaDoc filePath, TypeDeclaration outerClass,
187                                               CompilerUtils.Mutable retFileToCheck,
188                                               boolean ignoreDirectories, boolean allowFileInPageFlowSourceDir,
189                                               AnnotationProcessorEnvironment env )
190         throws FatalCompileTimeException
191     
192     {
193         File JavaDoc fileToCheck = null;
194         boolean fileExists = true;
195         
196         if ( filePath.endsWith( JPF_FILE_EXTENSION_DOT ) )
197         {
198             String JavaDoc className = filePath.substring( 0, filePath.length() - JPF_FILE_EXTENSION_DOT.length() );
199             String JavaDoc pkg = outerClass.getPackage().getQualifiedName();
200             while ( className.startsWith( "../" ) && className.length() > 3 )
201             {
202                 className = className.substring( 3 );
203                 int lastDot = pkg.lastIndexOf( '.' );
204                 pkg = lastDot != -1 ? pkg.substring( 0, lastDot ) : "";
205             }
206             className = ( pkg.length() > 0 ? pkg + '.' : "" ) + className.replace( '/', '.' );
207             TypeDeclaration type = env.getTypeDeclaration( className );
208             fileToCheck = type != null ? CompilerUtils.getSourceFile( type, false ) : null;
209             if ( fileToCheck == null ) fileExists = false;
210         }
211         // In certain error conditions (jpfFile == null), we can't determine the file. In this case, just ignore.
212
else if ( CompilerUtils.getSourceFile( outerClass, false ) != null )
213         {
214             if ( allowFileInPageFlowSourceDir )
215             {
216                 fileToCheck = CompilerUtils.getFileRelativeToSourceFile( outerClass, filePath, env );
217             }
218             else
219             {
220                 // Use the package name to infer the relative path (from web content root) to the page flow directory.
221
String JavaDoc webContentRoot = CompilerUtils.getWebContentRoot( env );
222                 String JavaDoc jpfParentRelativePath = "";
223                 PackageDeclaration jpfPackage = outerClass.getPackage();
224                 if ( jpfPackage != null ) jpfParentRelativePath = jpfPackage.getQualifiedName().replace( '.', '/' );
225                 File JavaDoc desiredParentDir = new File JavaDoc( webContentRoot, jpfParentRelativePath );
226                 fileToCheck = new File JavaDoc( desiredParentDir, filePath );
227             }
228             
229             if ( ! fileToCheck.exists() && ! ( ignoreDirectories && fileToCheck.isDirectory() ) )
230             {
231                 fileExists = false;
232             }
233         }
234         
235         if ( retFileToCheck != null ) retFileToCheck.set( fileToCheck );
236         return fileExists;
237     }
238     
239     protected boolean checkAnyExtension()
240     {
241         return false;
242     }
243     
244     protected boolean doFatalError()
245     {
246         return false;
247     }
248     
249     protected void runAdditionalChecks( File JavaDoc file, AnnotationValue member )
250     {
251     }
252     
253     protected boolean ignoreDirectories()
254     {
255         return true;
256     }
257     
258     /**
259      * Tell whether the file must be in the page flow directory. If not, it is assumed to live in a webapp-addressable
260      * directory whose path corresponds to the page flow's package. This is here to support page flows in WEB-INF.
261      */

262     protected boolean allowFileInPageFlowSourceDir()
263     {
264         return false;
265     }
266     
267     protected FlowControllerInfo getFlowControllerInfo()
268     {
269         return _flowControllerInfo;
270     }
271 }
272
Popular Tags