View Javadoc

1   /*
2    * Copyright [2007] [University Corporation for Advanced Internet Development, Inc.]
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  
17  package edu.internet2.middleware.shibboleth.common.profile.provider;
18  
19  import java.io.IOException;
20  import java.io.OutputStreamWriter;
21  
22  import org.apache.velocity.Template;
23  import org.apache.velocity.VelocityContext;
24  import org.apache.velocity.app.VelocityEngine;
25  import org.apache.velocity.runtime.resource.util.StringResourceRepository;
26  import org.opensaml.ws.transport.InTransport;
27  import org.opensaml.ws.transport.OutTransport;
28  import org.opensaml.ws.transport.http.HttpServletRequestAdapter;
29  import org.opensaml.xml.util.DatatypeHelper;
30  import org.owasp.esapi.ESAPI;
31  import org.slf4j.Logger;
32  import org.slf4j.LoggerFactory;
33  
34  import edu.internet2.middleware.shibboleth.common.profile.AbstractErrorHandler;
35  import edu.internet2.middleware.shibboleth.common.util.StringResourceLoader;
36  
37  /**
38   * An error handler that render an error page by means of evaluating a Velocity template..
39   * 
40   * The following attributes are available within the velocity context page:
41   * 
42   * <table>
43   * <th>
44   * <td>Attribute Name</td>
45   * <td>Object Type</td>
46   * <td>Value</td>
47   * </th>
48   * <tr>
49   * <td>requestError</td>
50   * <td>{@link Throwable}</td>
51   * <td>Error that was thrown that triggered the invocation of this handler. </td>
52   * </tr>
53   * </table>
54   */
55  public class VelocityErrorHandler extends AbstractErrorHandler {
56  
57      /** Class logger. */
58      private final Logger log = LoggerFactory.getLogger(VelocityErrorHandler.class);
59  
60      /** Velocity engine used to render error page. */
61      private VelocityEngine velocityEngine;
62  
63      /** Location of the template to use to render the error page. */
64      private String templatePath;
65  
66      /**
67       * Constructor.
68       * 
69       * @param engine engine used to render error page
70       * @param template classpath location of template used to render error page
71       */
72      public VelocityErrorHandler(VelocityEngine engine, String template) {
73          if (engine == null) {
74              log.error("Velocity engine may not be null");
75              throw new IllegalArgumentException("Velocity engine may not be null");
76          }
77          velocityEngine = engine;
78  
79          templatePath = DatatypeHelper.safeTrimOrNullString(template);
80          if (templatePath == null) {
81              log.error("Velocity template path may not be null or empty");
82              throw new IllegalArgumentException("Velocity template path may not be null or empty");
83          }
84      }
85  
86      /**
87       * Initializes this error handler by loading the velocity template into the engine.
88       * 
89       * @throws IOException thrown if there is a problem reading the template file
90       */
91      public void initialize() throws IOException {
92          String templateString = DatatypeHelper.inputstreamToString(getClass().getResourceAsStream(templatePath), null);
93          StringResourceRepository repository = StringResourceLoader.getRepository();
94  
95          repository.putStringResource(templatePath, templateString);
96      }
97  
98      /** {@inheritDoc} */
99      public void processRequest(InTransport in, OutTransport out) {
100         VelocityContext context = new VelocityContext();
101         context.put("request", ((HttpServletRequestAdapter) in).getWrappedRequest());
102         context.put("requestError", in.getAttribute(AbstractErrorHandler.ERROR_KEY));
103         context.put("encoder", ESAPI.encoder());
104 
105         try {
106             OutputStreamWriter responseWriter = new OutputStreamWriter(out.getOutgoingStream());
107             Template template = velocityEngine.getTemplate(templatePath);
108             template.merge(context, responseWriter);
109             responseWriter.flush();
110         } catch (Throwable t) {
111             log.error("Unable to evaluate velocity error template", t);
112         }
113 
114         return;
115     }
116 }