• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 //  ========================================================================
3 //  Copyright (c) 1995-2014 Mort Bay Consulting Pty. Ltd.
4 //  ------------------------------------------------------------------------
5 //  All rights reserved. This program and the accompanying materials
6 //  are made available under the terms of the Eclipse Public License v1.0
7 //  and Apache License v2.0 which accompanies this distribution.
8 //
9 //      The Eclipse Public License is available at
10 //      http://www.eclipse.org/legal/epl-v10.html
11 //
12 //      The Apache License v2.0 is available at
13 //      http://www.opensource.org/licenses/apache2.0.php
14 //
15 //  You may elect to redistribute this code under either of these licenses.
16 //  ========================================================================
17 //
18 
19 package org.eclipse.jetty.servlet;
20 
21 import java.util.ArrayList;
22 import java.util.HashMap;
23 import java.util.List;
24 import java.util.Map;
25 
26 import javax.servlet.RequestDispatcher;
27 import javax.servlet.ServletContext;
28 import javax.servlet.ServletException;
29 import javax.servlet.http.HttpServletRequest;
30 
31 import org.eclipse.jetty.server.handler.ContextHandler;
32 import org.eclipse.jetty.server.handler.ErrorHandler;
33 
34 /* ------------------------------------------------------------ */
35 /** Error Page Error Handler
36  *
37  * An ErrorHandler that maps exceptions and status codes to URIs for dispatch using
38  * the internal ERROR style of dispatch.
39  *
40  */
41 public class ErrorPageErrorHandler extends ErrorHandler implements ErrorHandler.ErrorPageMapper
42 {
43     public final static String GLOBAL_ERROR_PAGE = "org.eclipse.jetty.server.error_page.global";
44 
45     protected ServletContext _servletContext;
46     private final Map<String,String> _errorPages= new HashMap<String,String>(); // code or exception to URL
47     private final List<ErrorCodeRange> _errorPageList=new ArrayList<ErrorCodeRange>(); // list of ErrorCode by range
48 
49     /* ------------------------------------------------------------ */
ErrorPageErrorHandler()50     public ErrorPageErrorHandler()
51     {}
52 
53     @Override
getErrorPage(HttpServletRequest request)54     public String getErrorPage(HttpServletRequest request)
55     {
56         String error_page= null;
57         Class<?> exClass= (Class<?>)request.getAttribute(RequestDispatcher.ERROR_EXCEPTION_TYPE);
58 
59         if (ServletException.class.equals(exClass))
60         {
61             error_page= (String)_errorPages.get(exClass.getName());
62             if (error_page == null)
63             {
64                 Throwable th= (Throwable)request.getAttribute(RequestDispatcher.ERROR_EXCEPTION);
65                 while (th instanceof ServletException)
66                     th= ((ServletException)th).getRootCause();
67                 if (th != null)
68                     exClass= th.getClass();
69             }
70         }
71 
72         while (error_page == null && exClass != null )
73         {
74             error_page= (String)_errorPages.get(exClass.getName());
75             exClass= exClass.getSuperclass();
76         }
77 
78         if (error_page == null)
79         {
80             // look for an exact code match
81             Integer code=(Integer)request.getAttribute(RequestDispatcher.ERROR_STATUS_CODE);
82             if (code!=null)
83             {
84                 error_page= (String)_errorPages.get(Integer.toString(code));
85 
86                 // if still not found
87                 if ((error_page == null) && (_errorPageList != null))
88                 {
89                     // look for an error code range match.
90                     for (int i = 0; i < _errorPageList.size(); i++)
91                     {
92                         ErrorCodeRange errCode = (ErrorCodeRange) _errorPageList.get(i);
93                         if (errCode.isInRange(code))
94                         {
95                             error_page = errCode.getUri();
96                             break;
97                         }
98                     }
99                 }
100             }
101         }
102 
103         //try new servlet 3.0 global error page
104         if (error_page == null)
105         {
106             error_page = _errorPages.get(GLOBAL_ERROR_PAGE);
107         }
108 
109         return error_page;
110     }
111 
112     /* ------------------------------------------------------------ */
113     /**
114      * @return Returns the errorPages.
115      */
getErrorPages()116     public Map<String,String> getErrorPages()
117     {
118         return _errorPages;
119     }
120 
121     /* ------------------------------------------------------------ */
122     /**
123      * @param errorPages The errorPages to set. A map of Exception class name  or error code as a string to URI string
124      */
setErrorPages(Map<String,String> errorPages)125     public void setErrorPages(Map<String,String> errorPages)
126     {
127         _errorPages.clear();
128         if (errorPages!=null)
129             _errorPages.putAll(errorPages);
130     }
131 
132     /* ------------------------------------------------------------ */
133     /** Add Error Page mapping for an exception class
134      * This method is called as a result of an exception-type element in a web.xml file
135      * or may be called directly
136      * @param exception The exception
137      * @param uri The URI of the error page.
138      */
addErrorPage(Class<? extends Throwable> exception,String uri)139     public void addErrorPage(Class<? extends Throwable> exception,String uri)
140     {
141         _errorPages.put(exception.getName(),uri);
142     }
143 
144     /* ------------------------------------------------------------ */
145     /** Add Error Page mapping for an exception class
146      * This method is called as a result of an exception-type element in a web.xml file
147      * or may be called directly
148      * @param exceptionClassName The exception
149      * @param uri The URI of the error page.
150      */
addErrorPage(String exceptionClassName,String uri)151     public void addErrorPage(String exceptionClassName,String uri)
152     {
153         _errorPages.put(exceptionClassName,uri);
154     }
155 
156     /* ------------------------------------------------------------ */
157     /** Add Error Page mapping for a status code.
158      * This method is called as a result of an error-code element in a web.xml file
159      * or may be called directly
160      * @param code The HTTP status code to match
161      * @param uri The URI of the error page.
162      */
addErrorPage(int code,String uri)163     public void addErrorPage(int code,String uri)
164     {
165         _errorPages.put(Integer.toString(code),uri);
166     }
167 
168     /* ------------------------------------------------------------ */
169     /** Add Error Page mapping for a status code range.
170      * This method is not available from web.xml and must be called
171      * directly.
172      * @param from The lowest matching status code
173      * @param to The highest matching status code
174      * @param uri The URI of the error page.
175      */
addErrorPage(int from, int to, String uri)176     public void addErrorPage(int from, int to, String uri)
177     {
178         _errorPageList.add(new ErrorCodeRange(from, to, uri));
179     }
180 
181     /* ------------------------------------------------------------ */
182     @Override
doStart()183     protected void doStart() throws Exception
184     {
185         super.doStart();
186         _servletContext=ContextHandler.getCurrentContext();
187     }
188 
189     /* ------------------------------------------------------------ */
190     /* ------------------------------------------------------------ */
191     private class ErrorCodeRange
192     {
193         private int _from;
194         private int _to;
195         private String _uri;
196 
ErrorCodeRange(int from, int to, String uri)197         ErrorCodeRange(int from, int to, String uri)
198             throws IllegalArgumentException
199         {
200             if (from > to)
201                 throw new IllegalArgumentException("from>to");
202 
203             _from = from;
204             _to = to;
205             _uri = uri;
206         }
207 
isInRange(int value)208         boolean isInRange(int value)
209         {
210             if ((value >= _from) && (value <= _to))
211             {
212                 return true;
213             }
214 
215             return false;
216         }
217 
getUri()218         String getUri()
219         {
220             return _uri;
221         }
222 
223         @Override
toString()224         public String toString()
225         {
226             return "from: " + _from + ",to: " + _to + ",uri: " + _uri;
227         }
228     }
229 }
230