103928aee4356845252ac6b662d5c72c29903813eJake Slack// 203928aee4356845252ac6b662d5c72c29903813eJake Slack// ======================================================================== 303928aee4356845252ac6b662d5c72c29903813eJake Slack// Copyright (c) 1995-2014 Mort Bay Consulting Pty. Ltd. 403928aee4356845252ac6b662d5c72c29903813eJake Slack// ------------------------------------------------------------------------ 503928aee4356845252ac6b662d5c72c29903813eJake Slack// All rights reserved. This program and the accompanying materials 603928aee4356845252ac6b662d5c72c29903813eJake Slack// are made available under the terms of the Eclipse Public License v1.0 703928aee4356845252ac6b662d5c72c29903813eJake Slack// and Apache License v2.0 which accompanies this distribution. 803928aee4356845252ac6b662d5c72c29903813eJake Slack// 903928aee4356845252ac6b662d5c72c29903813eJake Slack// The Eclipse Public License is available at 1003928aee4356845252ac6b662d5c72c29903813eJake Slack// http://www.eclipse.org/legal/epl-v10.html 1103928aee4356845252ac6b662d5c72c29903813eJake Slack// 1203928aee4356845252ac6b662d5c72c29903813eJake Slack// The Apache License v2.0 is available at 1303928aee4356845252ac6b662d5c72c29903813eJake Slack// http://www.opensource.org/licenses/apache2.0.php 1403928aee4356845252ac6b662d5c72c29903813eJake Slack// 1503928aee4356845252ac6b662d5c72c29903813eJake Slack// You may elect to redistribute this code under either of these licenses. 1603928aee4356845252ac6b662d5c72c29903813eJake Slack// ======================================================================== 1703928aee4356845252ac6b662d5c72c29903813eJake Slack// 1803928aee4356845252ac6b662d5c72c29903813eJake Slack 1903928aee4356845252ac6b662d5c72c29903813eJake Slackpackage org.eclipse.jetty.servlet; 2003928aee4356845252ac6b662d5c72c29903813eJake Slack 2103928aee4356845252ac6b662d5c72c29903813eJake Slackimport java.util.ArrayList; 2203928aee4356845252ac6b662d5c72c29903813eJake Slackimport java.util.HashMap; 2303928aee4356845252ac6b662d5c72c29903813eJake Slackimport java.util.List; 2403928aee4356845252ac6b662d5c72c29903813eJake Slackimport java.util.Map; 2503928aee4356845252ac6b662d5c72c29903813eJake Slack 2603928aee4356845252ac6b662d5c72c29903813eJake Slackimport javax.servlet.RequestDispatcher; 2703928aee4356845252ac6b662d5c72c29903813eJake Slackimport javax.servlet.ServletContext; 2803928aee4356845252ac6b662d5c72c29903813eJake Slackimport javax.servlet.ServletException; 2903928aee4356845252ac6b662d5c72c29903813eJake Slackimport javax.servlet.http.HttpServletRequest; 3003928aee4356845252ac6b662d5c72c29903813eJake Slack 3103928aee4356845252ac6b662d5c72c29903813eJake Slackimport org.eclipse.jetty.server.handler.ContextHandler; 3203928aee4356845252ac6b662d5c72c29903813eJake Slackimport org.eclipse.jetty.server.handler.ErrorHandler; 3303928aee4356845252ac6b662d5c72c29903813eJake Slack 3403928aee4356845252ac6b662d5c72c29903813eJake Slack/* ------------------------------------------------------------ */ 3503928aee4356845252ac6b662d5c72c29903813eJake Slack/** Error Page Error Handler 3603928aee4356845252ac6b662d5c72c29903813eJake Slack * 3703928aee4356845252ac6b662d5c72c29903813eJake Slack * An ErrorHandler that maps exceptions and status codes to URIs for dispatch using 3803928aee4356845252ac6b662d5c72c29903813eJake Slack * the internal ERROR style of dispatch. 3903928aee4356845252ac6b662d5c72c29903813eJake Slack * 4003928aee4356845252ac6b662d5c72c29903813eJake Slack */ 4103928aee4356845252ac6b662d5c72c29903813eJake Slackpublic class ErrorPageErrorHandler extends ErrorHandler implements ErrorHandler.ErrorPageMapper 4203928aee4356845252ac6b662d5c72c29903813eJake Slack{ 4303928aee4356845252ac6b662d5c72c29903813eJake Slack public final static String GLOBAL_ERROR_PAGE = "org.eclipse.jetty.server.error_page.global"; 4403928aee4356845252ac6b662d5c72c29903813eJake Slack 4503928aee4356845252ac6b662d5c72c29903813eJake Slack protected ServletContext _servletContext; 4603928aee4356845252ac6b662d5c72c29903813eJake Slack private final Map<String,String> _errorPages= new HashMap<String,String>(); // code or exception to URL 4703928aee4356845252ac6b662d5c72c29903813eJake Slack private final List<ErrorCodeRange> _errorPageList=new ArrayList<ErrorCodeRange>(); // list of ErrorCode by range 4803928aee4356845252ac6b662d5c72c29903813eJake Slack 4903928aee4356845252ac6b662d5c72c29903813eJake Slack /* ------------------------------------------------------------ */ 5003928aee4356845252ac6b662d5c72c29903813eJake Slack public ErrorPageErrorHandler() 5103928aee4356845252ac6b662d5c72c29903813eJake Slack {} 5203928aee4356845252ac6b662d5c72c29903813eJake Slack 5303928aee4356845252ac6b662d5c72c29903813eJake Slack @Override 5403928aee4356845252ac6b662d5c72c29903813eJake Slack public String getErrorPage(HttpServletRequest request) 5503928aee4356845252ac6b662d5c72c29903813eJake Slack { 5603928aee4356845252ac6b662d5c72c29903813eJake Slack String error_page= null; 5703928aee4356845252ac6b662d5c72c29903813eJake Slack Class<?> exClass= (Class<?>)request.getAttribute(RequestDispatcher.ERROR_EXCEPTION_TYPE); 5803928aee4356845252ac6b662d5c72c29903813eJake Slack 5903928aee4356845252ac6b662d5c72c29903813eJake Slack if (ServletException.class.equals(exClass)) 6003928aee4356845252ac6b662d5c72c29903813eJake Slack { 6103928aee4356845252ac6b662d5c72c29903813eJake Slack error_page= (String)_errorPages.get(exClass.getName()); 6203928aee4356845252ac6b662d5c72c29903813eJake Slack if (error_page == null) 6303928aee4356845252ac6b662d5c72c29903813eJake Slack { 6403928aee4356845252ac6b662d5c72c29903813eJake Slack Throwable th= (Throwable)request.getAttribute(RequestDispatcher.ERROR_EXCEPTION); 6503928aee4356845252ac6b662d5c72c29903813eJake Slack while (th instanceof ServletException) 6603928aee4356845252ac6b662d5c72c29903813eJake Slack th= ((ServletException)th).getRootCause(); 6703928aee4356845252ac6b662d5c72c29903813eJake Slack if (th != null) 6803928aee4356845252ac6b662d5c72c29903813eJake Slack exClass= th.getClass(); 6903928aee4356845252ac6b662d5c72c29903813eJake Slack } 7003928aee4356845252ac6b662d5c72c29903813eJake Slack } 7103928aee4356845252ac6b662d5c72c29903813eJake Slack 7203928aee4356845252ac6b662d5c72c29903813eJake Slack while (error_page == null && exClass != null ) 7303928aee4356845252ac6b662d5c72c29903813eJake Slack { 7403928aee4356845252ac6b662d5c72c29903813eJake Slack error_page= (String)_errorPages.get(exClass.getName()); 7503928aee4356845252ac6b662d5c72c29903813eJake Slack exClass= exClass.getSuperclass(); 7603928aee4356845252ac6b662d5c72c29903813eJake Slack } 7703928aee4356845252ac6b662d5c72c29903813eJake Slack 7803928aee4356845252ac6b662d5c72c29903813eJake Slack if (error_page == null) 7903928aee4356845252ac6b662d5c72c29903813eJake Slack { 8003928aee4356845252ac6b662d5c72c29903813eJake Slack // look for an exact code match 8103928aee4356845252ac6b662d5c72c29903813eJake Slack Integer code=(Integer)request.getAttribute(RequestDispatcher.ERROR_STATUS_CODE); 8203928aee4356845252ac6b662d5c72c29903813eJake Slack if (code!=null) 8303928aee4356845252ac6b662d5c72c29903813eJake Slack { 8403928aee4356845252ac6b662d5c72c29903813eJake Slack error_page= (String)_errorPages.get(Integer.toString(code)); 8503928aee4356845252ac6b662d5c72c29903813eJake Slack 8603928aee4356845252ac6b662d5c72c29903813eJake Slack // if still not found 8703928aee4356845252ac6b662d5c72c29903813eJake Slack if ((error_page == null) && (_errorPageList != null)) 8803928aee4356845252ac6b662d5c72c29903813eJake Slack { 8903928aee4356845252ac6b662d5c72c29903813eJake Slack // look for an error code range match. 9003928aee4356845252ac6b662d5c72c29903813eJake Slack for (int i = 0; i < _errorPageList.size(); i++) 9103928aee4356845252ac6b662d5c72c29903813eJake Slack { 9203928aee4356845252ac6b662d5c72c29903813eJake Slack ErrorCodeRange errCode = (ErrorCodeRange) _errorPageList.get(i); 9303928aee4356845252ac6b662d5c72c29903813eJake Slack if (errCode.isInRange(code)) 9403928aee4356845252ac6b662d5c72c29903813eJake Slack { 9503928aee4356845252ac6b662d5c72c29903813eJake Slack error_page = errCode.getUri(); 9603928aee4356845252ac6b662d5c72c29903813eJake Slack break; 9703928aee4356845252ac6b662d5c72c29903813eJake Slack } 9803928aee4356845252ac6b662d5c72c29903813eJake Slack } 9903928aee4356845252ac6b662d5c72c29903813eJake Slack } 10003928aee4356845252ac6b662d5c72c29903813eJake Slack } 10103928aee4356845252ac6b662d5c72c29903813eJake Slack } 10203928aee4356845252ac6b662d5c72c29903813eJake Slack 10303928aee4356845252ac6b662d5c72c29903813eJake Slack //try new servlet 3.0 global error page 10403928aee4356845252ac6b662d5c72c29903813eJake Slack if (error_page == null) 10503928aee4356845252ac6b662d5c72c29903813eJake Slack { 10603928aee4356845252ac6b662d5c72c29903813eJake Slack error_page = _errorPages.get(GLOBAL_ERROR_PAGE); 10703928aee4356845252ac6b662d5c72c29903813eJake Slack } 10803928aee4356845252ac6b662d5c72c29903813eJake Slack 10903928aee4356845252ac6b662d5c72c29903813eJake Slack return error_page; 11003928aee4356845252ac6b662d5c72c29903813eJake Slack } 11103928aee4356845252ac6b662d5c72c29903813eJake Slack 11203928aee4356845252ac6b662d5c72c29903813eJake Slack /* ------------------------------------------------------------ */ 11303928aee4356845252ac6b662d5c72c29903813eJake Slack /** 11403928aee4356845252ac6b662d5c72c29903813eJake Slack * @return Returns the errorPages. 11503928aee4356845252ac6b662d5c72c29903813eJake Slack */ 11603928aee4356845252ac6b662d5c72c29903813eJake Slack public Map<String,String> getErrorPages() 11703928aee4356845252ac6b662d5c72c29903813eJake Slack { 11803928aee4356845252ac6b662d5c72c29903813eJake Slack return _errorPages; 11903928aee4356845252ac6b662d5c72c29903813eJake Slack } 12003928aee4356845252ac6b662d5c72c29903813eJake Slack 12103928aee4356845252ac6b662d5c72c29903813eJake Slack /* ------------------------------------------------------------ */ 12203928aee4356845252ac6b662d5c72c29903813eJake Slack /** 12303928aee4356845252ac6b662d5c72c29903813eJake Slack * @param errorPages The errorPages to set. A map of Exception class name or error code as a string to URI string 12403928aee4356845252ac6b662d5c72c29903813eJake Slack */ 12503928aee4356845252ac6b662d5c72c29903813eJake Slack public void setErrorPages(Map<String,String> errorPages) 12603928aee4356845252ac6b662d5c72c29903813eJake Slack { 12703928aee4356845252ac6b662d5c72c29903813eJake Slack _errorPages.clear(); 12803928aee4356845252ac6b662d5c72c29903813eJake Slack if (errorPages!=null) 12903928aee4356845252ac6b662d5c72c29903813eJake Slack _errorPages.putAll(errorPages); 13003928aee4356845252ac6b662d5c72c29903813eJake Slack } 13103928aee4356845252ac6b662d5c72c29903813eJake Slack 13203928aee4356845252ac6b662d5c72c29903813eJake Slack /* ------------------------------------------------------------ */ 13303928aee4356845252ac6b662d5c72c29903813eJake Slack /** Add Error Page mapping for an exception class 13403928aee4356845252ac6b662d5c72c29903813eJake Slack * This method is called as a result of an exception-type element in a web.xml file 13503928aee4356845252ac6b662d5c72c29903813eJake Slack * or may be called directly 13603928aee4356845252ac6b662d5c72c29903813eJake Slack * @param exception The exception 13703928aee4356845252ac6b662d5c72c29903813eJake Slack * @param uri The URI of the error page. 13803928aee4356845252ac6b662d5c72c29903813eJake Slack */ 13903928aee4356845252ac6b662d5c72c29903813eJake Slack public void addErrorPage(Class<? extends Throwable> exception,String uri) 14003928aee4356845252ac6b662d5c72c29903813eJake Slack { 14103928aee4356845252ac6b662d5c72c29903813eJake Slack _errorPages.put(exception.getName(),uri); 14203928aee4356845252ac6b662d5c72c29903813eJake Slack } 14303928aee4356845252ac6b662d5c72c29903813eJake Slack 14403928aee4356845252ac6b662d5c72c29903813eJake Slack /* ------------------------------------------------------------ */ 14503928aee4356845252ac6b662d5c72c29903813eJake Slack /** Add Error Page mapping for an exception class 14603928aee4356845252ac6b662d5c72c29903813eJake Slack * This method is called as a result of an exception-type element in a web.xml file 14703928aee4356845252ac6b662d5c72c29903813eJake Slack * or may be called directly 14803928aee4356845252ac6b662d5c72c29903813eJake Slack * @param exceptionClassName The exception 14903928aee4356845252ac6b662d5c72c29903813eJake Slack * @param uri The URI of the error page. 15003928aee4356845252ac6b662d5c72c29903813eJake Slack */ 15103928aee4356845252ac6b662d5c72c29903813eJake Slack public void addErrorPage(String exceptionClassName,String uri) 15203928aee4356845252ac6b662d5c72c29903813eJake Slack { 15303928aee4356845252ac6b662d5c72c29903813eJake Slack _errorPages.put(exceptionClassName,uri); 15403928aee4356845252ac6b662d5c72c29903813eJake Slack } 15503928aee4356845252ac6b662d5c72c29903813eJake Slack 15603928aee4356845252ac6b662d5c72c29903813eJake Slack /* ------------------------------------------------------------ */ 15703928aee4356845252ac6b662d5c72c29903813eJake Slack /** Add Error Page mapping for a status code. 15803928aee4356845252ac6b662d5c72c29903813eJake Slack * This method is called as a result of an error-code element in a web.xml file 15903928aee4356845252ac6b662d5c72c29903813eJake Slack * or may be called directly 16003928aee4356845252ac6b662d5c72c29903813eJake Slack * @param code The HTTP status code to match 16103928aee4356845252ac6b662d5c72c29903813eJake Slack * @param uri The URI of the error page. 16203928aee4356845252ac6b662d5c72c29903813eJake Slack */ 16303928aee4356845252ac6b662d5c72c29903813eJake Slack public void addErrorPage(int code,String uri) 16403928aee4356845252ac6b662d5c72c29903813eJake Slack { 16503928aee4356845252ac6b662d5c72c29903813eJake Slack _errorPages.put(Integer.toString(code),uri); 16603928aee4356845252ac6b662d5c72c29903813eJake Slack } 16703928aee4356845252ac6b662d5c72c29903813eJake Slack 16803928aee4356845252ac6b662d5c72c29903813eJake Slack /* ------------------------------------------------------------ */ 16903928aee4356845252ac6b662d5c72c29903813eJake Slack /** Add Error Page mapping for a status code range. 17003928aee4356845252ac6b662d5c72c29903813eJake Slack * This method is not available from web.xml and must be called 17103928aee4356845252ac6b662d5c72c29903813eJake Slack * directly. 17203928aee4356845252ac6b662d5c72c29903813eJake Slack * @param from The lowest matching status code 17303928aee4356845252ac6b662d5c72c29903813eJake Slack * @param to The highest matching status code 17403928aee4356845252ac6b662d5c72c29903813eJake Slack * @param uri The URI of the error page. 17503928aee4356845252ac6b662d5c72c29903813eJake Slack */ 17603928aee4356845252ac6b662d5c72c29903813eJake Slack public void addErrorPage(int from, int to, String uri) 17703928aee4356845252ac6b662d5c72c29903813eJake Slack { 17803928aee4356845252ac6b662d5c72c29903813eJake Slack _errorPageList.add(new ErrorCodeRange(from, to, uri)); 17903928aee4356845252ac6b662d5c72c29903813eJake Slack } 18003928aee4356845252ac6b662d5c72c29903813eJake Slack 18103928aee4356845252ac6b662d5c72c29903813eJake Slack /* ------------------------------------------------------------ */ 18203928aee4356845252ac6b662d5c72c29903813eJake Slack @Override 18303928aee4356845252ac6b662d5c72c29903813eJake Slack protected void doStart() throws Exception 18403928aee4356845252ac6b662d5c72c29903813eJake Slack { 18503928aee4356845252ac6b662d5c72c29903813eJake Slack super.doStart(); 18603928aee4356845252ac6b662d5c72c29903813eJake Slack _servletContext=ContextHandler.getCurrentContext(); 18703928aee4356845252ac6b662d5c72c29903813eJake Slack } 18803928aee4356845252ac6b662d5c72c29903813eJake Slack 18903928aee4356845252ac6b662d5c72c29903813eJake Slack /* ------------------------------------------------------------ */ 19003928aee4356845252ac6b662d5c72c29903813eJake Slack /* ------------------------------------------------------------ */ 19103928aee4356845252ac6b662d5c72c29903813eJake Slack private class ErrorCodeRange 19203928aee4356845252ac6b662d5c72c29903813eJake Slack { 19303928aee4356845252ac6b662d5c72c29903813eJake Slack private int _from; 19403928aee4356845252ac6b662d5c72c29903813eJake Slack private int _to; 19503928aee4356845252ac6b662d5c72c29903813eJake Slack private String _uri; 19603928aee4356845252ac6b662d5c72c29903813eJake Slack 19703928aee4356845252ac6b662d5c72c29903813eJake Slack ErrorCodeRange(int from, int to, String uri) 19803928aee4356845252ac6b662d5c72c29903813eJake Slack throws IllegalArgumentException 19903928aee4356845252ac6b662d5c72c29903813eJake Slack { 20003928aee4356845252ac6b662d5c72c29903813eJake Slack if (from > to) 20103928aee4356845252ac6b662d5c72c29903813eJake Slack throw new IllegalArgumentException("from>to"); 20203928aee4356845252ac6b662d5c72c29903813eJake Slack 20303928aee4356845252ac6b662d5c72c29903813eJake Slack _from = from; 20403928aee4356845252ac6b662d5c72c29903813eJake Slack _to = to; 20503928aee4356845252ac6b662d5c72c29903813eJake Slack _uri = uri; 20603928aee4356845252ac6b662d5c72c29903813eJake Slack } 20703928aee4356845252ac6b662d5c72c29903813eJake Slack 20803928aee4356845252ac6b662d5c72c29903813eJake Slack boolean isInRange(int value) 20903928aee4356845252ac6b662d5c72c29903813eJake Slack { 21003928aee4356845252ac6b662d5c72c29903813eJake Slack if ((value >= _from) && (value <= _to)) 21103928aee4356845252ac6b662d5c72c29903813eJake Slack { 21203928aee4356845252ac6b662d5c72c29903813eJake Slack return true; 21303928aee4356845252ac6b662d5c72c29903813eJake Slack } 21403928aee4356845252ac6b662d5c72c29903813eJake Slack 21503928aee4356845252ac6b662d5c72c29903813eJake Slack return false; 21603928aee4356845252ac6b662d5c72c29903813eJake Slack } 21703928aee4356845252ac6b662d5c72c29903813eJake Slack 21803928aee4356845252ac6b662d5c72c29903813eJake Slack String getUri() 21903928aee4356845252ac6b662d5c72c29903813eJake Slack { 22003928aee4356845252ac6b662d5c72c29903813eJake Slack return _uri; 22103928aee4356845252ac6b662d5c72c29903813eJake Slack } 22203928aee4356845252ac6b662d5c72c29903813eJake Slack 22303928aee4356845252ac6b662d5c72c29903813eJake Slack @Override 22403928aee4356845252ac6b662d5c72c29903813eJake Slack public String toString() 22503928aee4356845252ac6b662d5c72c29903813eJake Slack { 22603928aee4356845252ac6b662d5c72c29903813eJake Slack return "from: " + _from + ",to: " + _to + ",uri: " + _uri; 22703928aee4356845252ac6b662d5c72c29903813eJake Slack } 22803928aee4356845252ac6b662d5c72c29903813eJake Slack } 22903928aee4356845252ac6b662d5c72c29903813eJake Slack} 230