View Javadoc

    1   // ========================================================================
    2   // Copyright 2006 Mort Bay Consulting Pty. Ltd.
    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   // http://www.apache.org/licenses/LICENSE-2.0
    8   // Unless required by applicable law or agreed to in writing, software
    9   // distributed under the License is distributed on an "AS IS" BASIS,
    10  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    11  // See the License for the specific language governing permissions and
    12  // limitations under the License.
    13  // ========================================================================
    14
    15  package org.mortbay.jetty.servlet;
    16
    17  import java.io.IOException;
    18  import java.util.ArrayList;
    19  import java.util.HashMap;
    20  import java.util.List;
    21  import java.util.Map;
    22
    23  import javax.servlet.ServletContext;
    24  import javax.servlet.ServletException;
    25  import javax.servlet.http.HttpServletRequest;
    26  import javax.servlet.http.HttpServletResponse;
    27
    28  import org.mortbay.jetty.HttpConnection;
    29  import org.mortbay.jetty.HttpMethods;
    30  import org.mortbay.jetty.handler.ContextHandler;
    31  import org.mortbay.jetty.handler.ErrorHandler;
    32  import org.mortbay.jetty.webapp.WebAppContext;
    33  import org.mortbay.log.Log;
    34  import org.mortbay.util.TypeUtil;
    35
    36  /** Error Page Error Handler
    37   *
    38   * An ErrorHandler that maps exceptions and status codes to URIs for dispatch using
    39   * the internal ERROR style of dispatch.
    40   * @author gregw
    41   *
    42   */
    43  public class ErrorPageErrorHandler extends ErrorHandler
    44  {
    45      protected ServletContext _servletContext;
    46      protected Map _errorPages; // code or exception to URL
    47      protected List _errorPageList; // list of ErrorCode by range
    48
    49      /* ------------------------------------------------------------ */
    50      /**
    51       * @param context
    52       */
    53      public ErrorPageErrorHandler()
    54      {}
    55
    56      /* ------------------------------------------------------------ */
    57      /*
    58       * @see org.mortbay.jetty.handler.ErrorHandler#handle(java.lang.String, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse, int)
    59       */
    60      public void handle(String target, HttpServletRequest request, HttpServletResponse response, int dispatch) throws IOException
    61      {
    62          String method = request.getMethod();
    63          if(!method.equals(HttpMethods.GET) && !method.equals(HttpMethods.POST) && !method.equals(HttpMethods.HEAD))
    64          {
    65              HttpConnection.getCurrentConnection().getRequest().setHandled(true);
    66              return;
    67          }
    68          if (_errorPages!=null)
    69          {
    70              String error_page= null;
    71              Class exClass= (Class)request.getAttribute(ServletHandler.__J_S_ERROR_EXCEPTION_TYPE);
    72
    73              if (ServletException.class.equals(exClass))
    74              {
    75                  error_page= (String)_errorPages.get(exClass.getName());
    76                  if (error_page == null)
    77                  {
    78                      Throwable th= (Throwable)request.getAttribute(ServletHandler.__J_S_ERROR_EXCEPTION);
    79                      while (th instanceof ServletException)
    80                          th= ((ServletException)th).getRootCause();
    81                      if (th != null)
    82                          exClass= th.getClass();
    83                  }
    84              }
    85
    86              while (error_page == null && exClass != null )
    87              {
    88                  error_page= (String)_errorPages.get(exClass.getName());
    89                  exClass= exClass.getSuperclass();
    90              }
    91
    92              if (error_page == null)
    93              {
    94                  // look for an exact code match
    95                  Integer code=(Integer)request.getAttribute(ServletHandler.__J_S_ERROR_STATUS_CODE);
    96                  if (code!=null)
    97                  {
    98                      error_page= (String)_errorPages.get(TypeUtil.toString(code.intValue()));
    99
    100                     // if still not found
    101                     if ((error_page == null) && (_errorPageList != null))
    102                     {
    103                         // look for an error code range match.
    104                         for (int i = 0; i < _errorPageList.size(); i++)
    105                         {
    106                             ErrorCodeRange errCode = (ErrorCodeRange) _errorPageList.get(i);
    107                             if (errCode.isInRange(code.intValue()))
    108                             {
    109                                 error_page = errCode.getUri();
    110                                 break;
    111                             }
    112                         }
    113                     }
    114                 }
    115             }
    116
    117             if (error_page!=null)
    118             {
    119                 String old_error_page=(String)request.getAttribute(WebAppContext.ERROR_PAGE);
    120                 if (old_error_page==null || !old_error_page.equals(error_page))
    121                 {
    122                     request.setAttribute(WebAppContext.ERROR_PAGE, error_page);
    123
    124                     Dispatcher dispatcher = (Dispatcher) _servletContext.getRequestDispatcher(error_page);
    125                     try
    126                     {
    127                         if(dispatcher!=null)
    128                         {
    129                             dispatcher.error(request, response);
    130                             return;
    131                         }
    132                         else
    133                         {
    134                             Log.warn("No error page "+error_page);
    135                         }
    136                     }
    137                     catch (ServletException e)
    138                     {
    139                         Log.warn(Log.EXCEPTION, e);
    140                         return;
    141                     }
    142                 }
    143             }
    144         }
    145
    146         super.handle(target, request, response, dispatch);
    147     }
    148
    149     /* ------------------------------------------------------------ */
    150     /**
    151      * @return Returns the errorPages.
    152      */
    153     public Map getErrorPages()
    154     {
    155         return _errorPages;
    156     }
    157
    158     /* ------------------------------------------------------------ */
    159     /**
    160      * @param errorPages The errorPages to set. A map of Exception class name  or error code as a string to URI string
    161      */
    162     public void setErrorPages(Map errorPages)
    163     {
    164         _errorPages = errorPages;
    165     }
    166
    167     /* ------------------------------------------------------------ */
    168     /** Add Error Page mapping for an exception class
    169      * This method is called as a result of an exception-type element in a web.xml file
    170      * or may be called directly
    171      * @param code The class (or superclass) of the matching exceptions
    172      * @param uri The URI of the error page.
    173      */
    174     public void addErrorPage(Class exception,String uri)
    175     {
    176         if (_errorPages==null)
    177             _errorPages=new HashMap();
    178         _errorPages.put(exception.getName(),uri);
    179     }
    180
    181     /* ------------------------------------------------------------ */
    182     /** Add Error Page mapping for a status code.
    183      * This method is called as a result of an error-code element in a web.xml file
    184      * or may be called directly
    185      * @param code The HTTP status code to match
    186      * @param uri The URI of the error page.
    187      */
    188     public void addErrorPage(int code,String uri)
    189     {
    190         if (_errorPages==null)
    191             _errorPages=new HashMap();
    192         _errorPages.put(TypeUtil.toString(code),uri);
    193     }
    194
    195     /* ------------------------------------------------------------ */
    196     /** Add Error Page mapping for a status code range.
    197      * This method is not available from web.xml and must be called
    198      * directly.
    199      * @param from The lowest matching status code
    200      * @param to The highest matching status code
    201      * @param uri The URI of the error page.
    202      */
    203     public void addErrorPage(int from, int to, String uri)
    204     {
    205         if (_errorPageList == null)
    206         {
    207             _errorPageList = new ArrayList();
    208         }
    209         _errorPageList.add(new ErrorCodeRange(from, to, uri));
    210     }
    211
    212     /* ------------------------------------------------------------ */
    213     protected void doStart() throws Exception
    214     {
    215         super.doStart();
    216         _servletContext=ContextHandler.getCurrentContext();
    217     }
    218
    219     /* ------------------------------------------------------------ */
    220     protected void doStop() throws Exception
    221     {
    222         // TODO Auto-generated method stub
    223         super.doStop();
    224     }
    225
    226     /* ------------------------------------------------------------ */
    227     /* ------------------------------------------------------------ */
    228     private class ErrorCodeRange
    229     {
    230         private int _from;
    231         private int _to;
    232         private String _uri;
    233
    234         ErrorCodeRange(int from, int to, String uri)
    235             throws IllegalArgumentException
    236         {
    237             if (from > to)
    238                 throw new IllegalArgumentException("from>to");
    239
    240             _from = from;
    241             _to = to;
    242             _uri = uri;
    243         }
    244
    245         boolean isInRange(int value)
    246         {
    247             if ((value >= _from) && (value <= _to))
    248             {
    249                 return true;
    250             }
    251
    252             return false;
    253         }
    254
    255         String getUri()
    256         {
    257             return _uri;
    258         }
    259
    260         public String toString()
    261         {
    262             return "from: " + _from + ",to: " + _to + ",uri: " + _uri;
    263         }
    264     }
    265 }