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.custom.captcha;
20  
21  import java.awt.Color;
22  import java.io.IOException;
23  import java.io.OutputStream;
24  import java.util.Map;
25  import java.util.logging.Level;
26  import java.util.logging.Logger;
27  
28  import javax.faces.application.Resource;
29  import javax.faces.application.ResourceHandler;
30  import javax.faces.context.FacesContext;
31  import javax.servlet.ServletResponseWrapper;
32  import javax.servlet.http.HttpServletResponse;
33  
34  import org.apache.myfaces.custom.captcha.util.CAPTCHAImageGenerator;
35  import org.apache.myfaces.custom.captcha.util.CAPTCHATextGenerator;
36  import org.apache.myfaces.custom.captcha.util.ColorGenerator;
37  import org.apache.myfaces.shared_tomahawk.resource.ResourceHandlerSupport;
38  import org.apache.myfaces.tomahawk.application.DefaultResourceHandlerSupport;
39  
40  public class CAPTCHAResourceHandlerWrapper extends javax.faces.application.ResourceHandlerWrapper
41  {
42      public final static String CAPTCHA_LIBRARY = "oam.custom.captcha";
43      
44      private ResourceHandler _delegate;
45      
46      private ResourceHandlerSupport _resourceHandlerSupport;
47  
48      public CAPTCHAResourceHandlerWrapper(ResourceHandler delegate)
49      {
50          super();
51          _delegate = delegate;
52      }
53      
54      @Override
55      public ResourceHandler getWrapped()
56      {
57          return _delegate;
58      }
59  
60      @Override
61      public Resource createResource(String resourceName, String libraryName)
62      {
63          if (libraryName != null && CAPTCHA_LIBRARY.equals(libraryName))
64          {
65              return internalCreateResource(resourceName, libraryName);
66          }
67          else
68          {
69              return super.createResource(resourceName, libraryName);
70          }
71      }
72  
73      @Override
74      public Resource createResource(String resourceName, String libraryName, String contentType)
75      {
76          if (libraryName != null && CAPTCHA_LIBRARY.equals(libraryName))
77          {
78              return internalCreateResource(resourceName, libraryName);
79          }
80          else
81          {
82              return super.createResource(resourceName, libraryName, contentType);
83          }
84      }
85      
86      private Resource internalCreateResource(String resourceName, String libraryName)
87      {
88          FacesContext facesContext = FacesContext.getCurrentInstance();
89          if (isResourceRequest(facesContext))
90          {
91              Map<String, String> requestMap = facesContext.getExternalContext().getRequestParameterMap();
92              String captchaSessionKeyName = requestMap.get(CAPTCHAComponent.ATTRIBUTE_CAPTCHA_SESSION_KEY_NAME).toString();
93              return new CAPTCHAResource(getResourceHandlerSupport(), captchaSessionKeyName, resourceName);
94          }
95          else
96          {
97              String captchaSessionKeyName = (String) facesContext.getAttributes().get(CAPTCHAComponent.ATTRIBUTE_CAPTCHA_SESSION_KEY_NAME);
98              return new CAPTCHAResource(getResourceHandlerSupport(), captchaSessionKeyName, resourceName);
99          }
100     }
101     
102     @Override
103     public void handleResourceRequest(FacesContext facesContext) throws IOException
104     {
105         final Map<String, String> requestMap = facesContext.getExternalContext().getRequestParameterMap();
106         final String libraryName = requestMap.get("ln");
107         
108         if (libraryName != null && CAPTCHA_LIBRARY.equals(libraryName))
109         {
110             final String captchaSessionKeyName = requestMap.get(CAPTCHAComponent.ATTRIBUTE_CAPTCHA_SESSION_KEY_NAME).toString();
111             String resourceBasePath = getResourceHandlerSupport().calculateResourceBasePath(facesContext);
112             
113             Object response = facesContext.getExternalContext().getResponse();
114             HttpServletResponse httpServletResponse = getHttpServletResponse(response);
115             
116             String resourceName = null;
117             if (resourceBasePath.startsWith(ResourceHandler.RESOURCE_IDENTIFIER))
118             {
119                 resourceName = resourceBasePath
120                         .substring(ResourceHandler.RESOURCE_IDENTIFIER.length() + 1);
121             }
122             else
123             {
124                 //Does not have the conditions for be a resource call
125                 httpServletResponse.setStatus(HttpServletResponse.SC_NOT_FOUND);
126                 return;
127             }
128             
129             if (captchaSessionKeyName == null)
130             {
131                 httpServletResponse.setStatus(HttpServletResponse.SC_NOT_FOUND);
132                 return;
133             }
134 
135             Resource resource = null;
136             if (libraryName != null)
137             {
138                 //log.info("libraryName=" + libraryName);
139                 resource = facesContext.getApplication().getResourceHandler().createResource(resourceName, libraryName);
140             }
141             else
142             {
143                 resource = facesContext.getApplication().getResourceHandler().createResource(resourceName);
144             }
145             
146             if (resource == null)
147             {
148                 httpServletResponse.setStatus(HttpServletResponse.SC_NOT_FOUND);
149                 return;
150             }
151     
152             if (!resource.userAgentNeedsUpdate(facesContext))
153             {
154                 httpServletResponse.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
155                 return;
156             }
157             
158             httpServletResponse.setContentType(resource.getContentType());
159             
160             Map<String, String> headers = resource.getResponseHeaders();
161     
162             for (Map.Entry<String, String> entry : headers.entrySet())
163             {
164                 httpServletResponse.setHeader(entry.getKey(), entry.getValue());
165             }
166 
167             //serve up the bytes
168             try
169             {
170                 // construct the CAPTCHA image generator object.
171                 CAPTCHAImageGenerator captchaImageGenerator = new CAPTCHAImageGenerator();
172                 OutputStream out = httpServletResponse.getOutputStream();
173                 try
174                 {
175                     String captchaText;
176                     Color endingColor = ColorGenerator.generateRandomColor(null);
177                     Color startingColor = ColorGenerator
178                             .generateRandomColor(endingColor);
179                 
180                     // Generate random CAPTCHA text.
181                     captchaText = CAPTCHATextGenerator.generateRandomText();
182 
183                     // Set the generated text in the user session.
184                     facesContext.getExternalContext().getSessionMap().put(
185                             captchaSessionKeyName, captchaText);
186 
187                     // Generate the image, the BG color is randomized from starting to ending colors.
188                     captchaImageGenerator.generateImage(out, captchaText,
189                             startingColor, endingColor);
190                 }
191                 finally
192                 {
193                     out.close();
194                 }
195             }
196             catch (IOException e)
197             {
198                 Logger log = Logger.getLogger(CAPTCHAResourceHandlerWrapper.class.getName());
199                 if (log.isLoggable(Level.SEVERE))
200                     log.severe("Error trying to load resource " + resourceName
201                             + " with library " + libraryName + " :"
202                             + e.getMessage());
203                 httpServletResponse.setStatus(HttpServletResponse.SC_NOT_FOUND);
204             }
205         }
206         else
207         {
208             super.handleResourceRequest(facesContext);
209         }
210     }
211     
212     @Override
213     public boolean libraryExists(String libraryName)
214     {
215         if (libraryName != null && CAPTCHA_LIBRARY.equals(libraryName))
216         {
217             return true;
218         }
219         else
220         {
221             return super.libraryExists(libraryName);
222         }
223     }
224 
225     /**
226      * @param resourceHandlerSupport
227      *            the resourceHandlerSupport to set
228      */
229     public void setResourceHandlerSupport(
230             ResourceHandlerSupport resourceHandlerSupport)
231     {
232         _resourceHandlerSupport = resourceHandlerSupport;
233     }
234 
235     /**
236      * @return the resourceHandlerSupport
237      */
238     protected ResourceHandlerSupport getResourceHandlerSupport()
239     {
240         if (_resourceHandlerSupport == null)
241         {
242             _resourceHandlerSupport = new DefaultResourceHandlerSupport();
243         }
244         return _resourceHandlerSupport;
245     }
246     
247     private static HttpServletResponse getHttpServletResponse(Object response)
248     {
249         // unwrap the response until we find a HttpServletResponse
250         while (response != null)
251         {
252             if (response instanceof HttpServletResponse)
253             {
254                 // found
255                 return (HttpServletResponse) response;
256             }
257             if (response instanceof ServletResponseWrapper)
258             {
259                 // unwrap
260                 response = ((ServletResponseWrapper) response).getResponse();
261             }
262             // no more possibilities to find a HttpServletResponse
263             break; 
264         }
265         return null; // not found
266     }
267 }