View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  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  package org.apache.jetspeed.mocks;
18  
19  import java.io.File;
20  import java.io.IOException;
21  import java.io.InputStream;
22  import java.net.MalformedURLException;
23  import java.net.URL;
24  import java.util.ArrayList;
25  import java.util.HashMap;
26  import java.util.HashSet;
27  import java.util.Iterator;
28  import java.util.List;
29  import java.util.Map;
30  import java.util.Set;
31  
32  import javax.servlet.RequestDispatcher;
33  import javax.servlet.Servlet;
34  
35  import org.apache.commons.digester.Digester;
36  import org.apache.commons.digester.Rule;
37  import org.apache.commons.logging.Log;
38  import org.apache.commons.logging.LogFactory;
39  import org.apache.oro.text.GlobCompiler;
40  import org.apache.oro.text.regex.Pattern;
41  import org.apache.oro.text.regex.PatternCompiler;
42  import org.apache.oro.text.regex.PatternMatcher;
43  import org.apache.oro.text.regex.Perl5Matcher;
44  
45  import com.mockrunner.mock.web.MockServletConfig;
46  
47  public class ResourceLocatingServletContext extends BaseMockServletContext
48  {
49      protected final static Log log = LogFactory.getLog(ResourceLocatingServletContext.class);
50      
51      private final File rootPath;
52      private final Map pathOverrides = new HashMap();
53      private final List servletInfoList = new ArrayList();
54      private final List servletMappingInfoList = new ArrayList();
55      private final Map servletInstanceMap = new HashMap();
56      
57      public ResourceLocatingServletContext(File rootPath)
58      {
59          super();        
60          this.rootPath = rootPath;
61      }
62      
63      public ResourceLocatingServletContext(File rootPath, boolean loadServlet)
64      {
65          super();
66          this.rootPath = rootPath;
67  
68          if (loadServlet)
69              loadServlets();
70      }
71      
72      public final void addPathOverride(String path, File file)
73      {
74          pathOverrides.put(path, file);
75      }
76  
77      public URL getResource(String path) throws MalformedURLException
78      {
79         if(pathOverrides.containsKey(path))
80         {
81             return ((File)pathOverrides.get(path)).toURL();
82         }
83         else
84         {
85             return new File(rootPath, path).toURL();
86         }
87      }
88  
89      public String getRealPath(String path)
90      {
91          if(pathOverrides.containsKey(path))
92          {
93              return ((File)pathOverrides.get(path)).getAbsolutePath();
94          }
95          else
96          {
97              return new File(rootPath, path).getAbsolutePath();
98          }
99      }
100 
101     public InputStream getResourceAsStream(String path)
102     {
103         try
104         {
105             return getResource(path).openStream();
106         }
107         catch (IOException e)
108         {
109             // TODO Auto-generated catch block
110             e.printStackTrace();
111             return null;
112         }
113     }
114 
115     public Set getResourcePaths(String path)
116     {
117         File start = new File(rootPath, path);        
118         File[] children = start.listFiles();
119         HashSet pathes = new HashSet();
120         for(int i=0; i < children.length; i++)
121         {
122             File child = children[i];
123             String relativePath = child.getPath().substring(rootPath.getPath().length()).replace('//','/');
124             
125             if(child.isDirectory())
126             {                
127                 pathes.add(relativePath+"/");
128             }
129             else
130             {
131                 pathes.add(relativePath);
132             }
133         }
134         
135         Iterator itr = pathOverrides.keySet().iterator();
136         while(itr.hasNext())
137         {
138             pathes.add(itr.next());
139         }
140         
141         return pathes;
142     }
143 
144     public RequestDispatcher getRequestDispatcher(String arg0)
145     {
146         Servlet servlet = findServletByPath(arg0);
147 
148         if (servlet == null)
149         {
150             throw new IllegalArgumentException("Failed to find servlet for the path: " + arg0);
151         }
152 
153         return new ResourceLocatingRequestDispatcher(servlet, arg0, null);
154     }
155 
156     protected Servlet findServletByPath(String path)
157     {
158         Servlet servlet = null;
159 
160         for (Iterator it = this.servletMappingInfoList.iterator(); it.hasNext(); )
161         {
162             ServletMappingInfo servletMappingInfo = (ServletMappingInfo) it.next();
163             Pattern pattern = servletMappingInfo.getPattern();
164 
165             if (pattern != null)
166             {
167                 PatternMatcher matcher = new Perl5Matcher();
168                 
169                 if ((matcher.matches(path, pattern)) || (matcher.matches(path + "/", pattern)))
170                 {
171                     servlet = (Servlet) this.servletInstanceMap.get(servletMappingInfo.getServletName());
172                     break;
173                 }
174             }
175         }
176         
177         return servlet;
178     }
179 
180     protected void loadServlets() 
181     {
182         this.servletInfoList.clear();
183         this.servletMappingInfoList.clear();
184 
185         Digester digester = new Digester();
186         
187         digester.addObjectCreate("web-app/servlet", ServletInfo.class);
188         digester.addBeanPropertySetter("web-app/servlet/servlet-name", "servletName");
189         digester.addBeanPropertySetter("web-app/servlet/servlet-class", "servletClass");
190         digester.addCallMethod("web-app/servlet/init-param", "addInitParam", 2);
191         digester.addCallParam("web-app/servlet/init-param/param-name", 0);
192         digester.addCallParam("web-app/servlet/init-param/param-value", 1);
193         digester.addRule("web-app/servlet", new ServletRule(this.servletInfoList));
194         
195         digester.addObjectCreate("web-app/servlet-mapping", ServletMappingInfo.class);
196         digester.addBeanPropertySetter("web-app/servlet-mapping/servlet-name", "servletName");
197         digester.addBeanPropertySetter("web-app/servlet-mapping/url-pattern", "urlPattern");
198         digester.addRule("web-app/servlet-mapping", new ServletMappingRule(this.servletMappingInfoList));
199 
200         File webInfPath = new File(this.rootPath, "WEB-INF");        
201         File webDescriptorFile = new File(webInfPath, "web.xml");
202         log.debug("parsing webDescriptorFile: " + webDescriptorFile);
203 
204         try
205         {
206             digester.parse(webDescriptorFile);
207         }
208         catch (Exception e)
209         {
210             log.error("Failed to parse webDescriptorFile: " + webDescriptorFile, e);
211         }
212         
213         for (Iterator it = this.servletInfoList.iterator(); it.hasNext(); )
214         {
215             ServletInfo servletInfo = (ServletInfo) it.next();
216             
217             try
218             {
219                 Servlet servlet = (Servlet) Class.forName(servletInfo.getServletClass()).newInstance();
220                 MockServletConfig servletConfig = new MockServletConfig();
221                 servletConfig.setServletContext(this);
222                 
223                 Map initParamMap = servletInfo.getInitParamMap();
224                 
225                 for (Iterator itParam = initParamMap.keySet().iterator(); itParam.hasNext(); )
226                 {
227                     String paramName = (String) itParam.next();
228                     String paramValue = (String) initParamMap.get(paramName);
229                     servletConfig.setInitParameter(paramName, paramValue);
230                 }
231                 
232                 servlet.init(servletConfig);
233                 
234                 this.servletInstanceMap.put(servletInfo.getServletName(), servlet);
235             }
236             catch (Exception e)
237             {
238                 log.error("Failed to load and initialize servlet: " + servletInfo);
239             }
240         }
241     }
242 
243     public static class ServletInfo 
244     {
245         protected String servletName;
246         protected String servletClass;
247         protected Map initParamMap = new HashMap();
248 
249         public void setServletName(String servletName) 
250         {
251             this.servletName = servletName;
252         }
253         
254         public String getServletName() 
255         {
256             return this.servletName;
257         }
258 
259         public void setServletClass(String servletClass) 
260         {
261             this.servletClass = servletClass;
262         }
263 
264         public String getServletClass() 
265         {
266             return this.servletClass;
267         }
268 
269         public void addInitParam(String paramName, String paramValue) 
270         {
271             this.initParamMap.put(paramName, paramValue);
272         }
273 
274         public Map getInitParamMap() {
275             return this.initParamMap;
276         }
277 
278         public String toString() {
279             return "ServletInfo [" + this.servletName + ", " + this.servletClass + ", " + this.initParamMap + "]";
280         }
281     }
282 
283     public static class ServletMappingInfo 
284     {
285         protected String servletName;
286         protected String urlPattern;
287         protected Pattern pattern;
288 
289         public void setServletName(String servletName) 
290         {
291             this.servletName = servletName;
292         }
293 
294         public String getServletName() 
295         {
296             return this.servletName;
297         }
298 
299         public void setUrlPattern(String urlPattern) 
300         {
301             this.urlPattern = urlPattern;
302             this.pattern = null;
303 
304             try
305             {
306                 PatternCompiler compiler = new GlobCompiler();
307                 this.pattern = compiler.compile(this.urlPattern);
308             }
309             catch (Exception e)
310             {
311                 log.error("Invalid url pattern: " + this.urlPattern);
312             }
313         }
314 
315         public String getUrlPattern() 
316         {
317             return this.urlPattern;
318         }
319 
320         public Pattern getPattern()
321         {
322             return this.pattern;
323         }
324 
325         public String toString() {
326             return "ServletMappingInfo [" + this.urlPattern + ", " + this.servletName + "]";
327         }
328     }
329     
330     public static class ServletRule extends Rule 
331     {
332         private List servletInfoList;
333 
334         public ServletRule(List servletInfoList)
335         {
336             this.servletInfoList = servletInfoList;
337         }
338 
339         public void end(String namespace, String name) 
340         {
341             try
342             {
343                 ServletInfo servletInfo = (ServletInfo) digester.peek(0);
344                 this.servletInfoList.add(servletInfo);
345             }
346             catch (Exception e)
347             {
348                 log.error("Exception occurred in ServletRule", e);
349             }
350         }
351     }
352 
353     public static class ServletMappingRule extends Rule
354     {
355         private List servletMappingInfoList;
356 
357         public ServletMappingRule(List servletMappingInfoList)
358         {
359             this.servletMappingInfoList = servletMappingInfoList;
360         }
361 
362         public void end(String namespace, String name) 
363         {
364             try 
365             {
366                 ServletMappingInfo servletMappingInfo = (ServletMappingInfo) digester.peek(0);
367                 this.servletMappingInfoList.add(servletMappingInfo);
368             }
369             catch (Exception e)
370             {
371                 log.error("Exception occurred in ServletMappingRule", e);
372             }
373         }
374     }
375 
376     
377 }