View Javadoc

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