View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.myfaces.webapp.filter;
20  
21  import java.io.File;
22  import java.io.IOException;
23  import java.io.InputStream;
24  
25  import javax.servlet.Filter;
26  import javax.servlet.FilterChain;
27  import javax.servlet.FilterConfig;
28  import javax.servlet.RequestDispatcher;
29  import javax.servlet.ServletContext;
30  import javax.servlet.ServletException;
31  import javax.servlet.ServletRequest;
32  import javax.servlet.ServletResponse;
33  import javax.servlet.http.HttpServletRequest;
34  import javax.xml.parsers.SAXParser;
35  import javax.xml.parsers.SAXParserFactory;
36  
37  
38  /**
39   *
40   * Due to the manner in which the JSP / servlet lifecycle
41   * functions, it is not currently possible to specify default
42   * welcome files for a web application and map them to the
43   * MyFacesServlet.  Normally they will be mapped to the
44   * default servlet for the JSP container.  To offset this
45   * shortcoming, we utilize a servlet Filter which examines
46   * the URI of all incoming requests.
47   *
48   * @author Robert J. Lebowitz (latest modification by $Author: skitching $)
49   * @author Anton Koinov
50   * @since February 18th, 2003
51   * @version $Revision: 673833 $ $Date: 2008-07-03 16:58:05 -0500 (Thu, 03 Jul 2008) $
52   */
53  public class WelcomeFileFilter
54  implements Filter
55  {
56      //~ Instance fields --------------------------------------------------------
57  
58      private FilterConfig   _config;
59      private ServletContext _context;
60      private String[]       _welcomeFiles = new String[0];
61  
62      //~ Methods ----------------------------------------------------------------
63  
64      /**
65       * @see javax.servlet.Filter#destroy()
66       */
67      public void destroy()
68      {
69          _config           = null;
70          _context          = null;
71          _welcomeFiles     = null;
72      }
73  
74      /**
75       *
76       * If the URI indicates a context, or a subdirectory within a particular
77       * context, but does not specify a filename, the request is redirected to
78       * one of the default welcome files, assuming they are provided in the web.xml file.
79       * If no welcome files are specified, or if none of the welcome files
80       * actually exists, then the request is redirected to a file named "index.jsp" for
81       * that context or subdirectory with the current context.  If the index.jsp file
82       * does not exist, the servlet will return a File Not Found Error 404 message.
83       *
84       * A well configured servlet should provide a means of handling this type of
85       * error, along with a link to an appropriate help page.
86       *
87       * A URI is thought to represent a context and/or subdirectory(s) if
88       * it lacks a suffix following the pattern <b>.suffix</b>.
89       *
90       */
91      public void doFilter(
92          ServletRequest request, ServletResponse response, FilterChain chain)
93      throws IOException, ServletException
94      {
95          if (_config == null)
96          {
97              return;
98          }
99  
100         HttpServletRequest httpRequest = (HttpServletRequest) request;
101         String             uri = httpRequest.getRequestURI();
102 
103         // if the uri does not contain a suffix, we consider 
104         // it to represent a directory / context, not a file.
105         // file has suffix.  No need to search for welcome file
106         if (uri.lastIndexOf('.') > uri.lastIndexOf('/'))
107         {
108             chain.doFilter(request, response);
109 
110             return;
111         }
112 
113         String       contextPath = httpRequest.getContextPath();
114         String       welcomeFile = null;
115         StringBuffer sb          = new StringBuffer(uri);
116 
117         if (!uri.endsWith("/"))
118         {
119             sb.append('/');
120         }
121 
122         String baseURI = sb.delete(
123                 0,
124                 contextPath.length()).toString();
125 
126         // REVISIT: we probably can check for existence once at startup 
127         //          and know the exact welcome file by now. Of course, that 
128         //          would not work if the files change at runtime, but does it matter?
129         for (int i = 0; i < _welcomeFiles.length; i++)
130         {
131             sb.setLength(0);
132             sb.append(baseURI).append(_welcomeFiles[i]);
133 
134             File file = new File(_context.getRealPath(sb.toString()));
135 
136             //                        context.log("Welcome File: " + file.getAbsolutePath());
137             if (file.exists())
138             {
139                 // REVISIT: This will force all "welcome" JSPs through MyFaces. 
140                 //           Shouldn't we allow the user to enter *.jsf and check for *.jsp for existence, instead? 
141                 if (_welcomeFiles[i].endsWith(".jsp"))
142                 {
143                     // alter the name of the file we are requesting to
144                     // force it through the MyFacesServlet
145                     sb.replace(
146                         sb.lastIndexOf(".jsp"),
147                         sb.length(),
148                         ".jsf");
149                     welcomeFile = sb.toString();
150                 }
151 
152                 // we have discovered a filename;
153                 // stop the loop
154                 break;
155             }
156         }
157 
158         if (welcomeFile == null)
159         {
160             sb.setLength(0);
161             sb.append(baseURI);
162             sb.append("index.jsf");
163             welcomeFile = sb.toString();
164         }
165 
166         RequestDispatcher rd = httpRequest.getRequestDispatcher(welcomeFile);
167         rd.forward(request, response);
168 
169         return;
170     }
171 
172     /**
173      * During the init method, we have to get any predefined welcome files
174      * for the current ServletContext.
175      * @param config The filter configuration data
176      * @throws ServletException
177      */
178     public void init(FilterConfig config)
179     throws ServletException
180     {
181         if (config == null)
182         {
183             return;
184         }
185 
186         this._config      = config;
187         this._context     = config.getServletContext();
188 
189         try
190         {
191             SAXParserFactory factory = SAXParserFactory.newInstance();
192             factory.setValidating(false);
193             factory.setNamespaceAware(false);
194 
195             SAXParser          parser  = factory.newSAXParser();
196             WelcomeFileHandler handler = new WelcomeFileHandler();
197             InputStream        is      =
198                 _context.getResourceAsStream("WEB-INF/web.xml");
199 
200             if (is == null)
201             {
202                 _context.log("Unable to get inputstream for web.xml");
203             }
204 
205             parser.parse(is, handler);
206             _welcomeFiles = handler.getWelcomeFiles();
207             _context.log("Number of welcome files: " + _welcomeFiles.length);
208         }
209         catch (Exception ex)
210         {
211             throw new ServletException(ex);
212         }
213     }
214 }