Save This Page
Home » apache-solr-1.3.0 » org.apache.solr » servlet » [javadoc | source]
    1   /**
    2    * Licensed to the Apache Software Foundation (ASF) under one or more
    3    * contributor license agreements.  See the NOTICE file distributed with
    4    * this work for additional information regarding copyright ownership.
    5    * The ASF licenses this file to You under the Apache License, Version 2.0
    6    * (the "License"); you may not use this file except in compliance with
    7    * 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 org.apache.solr.servlet;
   19   
   20   import java.io.IOException;
   21   import java.io.PrintWriter;
   22   import java.io.StringWriter;
   23   import java.util.logging.Logger;
   24   
   25   import javax.servlet.Filter;
   26   import javax.servlet.FilterChain;
   27   import javax.servlet.FilterConfig;
   28   import javax.servlet.ServletException;
   29   import javax.servlet.ServletRequest;
   30   import javax.servlet.ServletResponse;
   31   import javax.servlet.http.HttpServletRequest;
   32   import javax.servlet.http.HttpServletResponse;
   33   
   34   import org.apache.solr.core.SolrConfig;
   35   import org.apache.solr.core.SolrCore;
   36   import org.apache.solr.core.SolrException;
   37   import org.apache.solr.request.QueryResponseWriter;
   38   import org.apache.solr.request.SolrParams;
   39   import org.apache.solr.request.SolrQueryRequest;
   40   import org.apache.solr.request.SolrQueryResponse;
   41   import org.apache.solr.request.SolrRequestHandler;
   42   
   43   /**
   44    * This filter looks at the incoming URL maps them to handlers defined in solrconfig.xml
   45    */
   46   public class SolrDispatchFilter implements Filter 
   47   {
   48     final Logger log = Logger.getLogger(SolrDispatchFilter.class.getName());
   49       
   50     protected SolrCore core;
   51     protected SolrRequestParsers parsers;
   52     protected boolean handleSelect = false;
   53     protected String pathPrefix = null; // strip this from the begging of a path
   54     protected String abortErrorMessage = null;
   55     
   56     public void init(FilterConfig config) throws ServletException 
   57     {
   58       log.info("SolrDispatchFilter.init()");
   59       
   60       try {
   61         // web.xml configuration
   62         this.pathPrefix = config.getInitParameter( "path-prefix" );
   63         
   64         // Let this filter take care of /select?xxx format
   65         this.handleSelect = 
   66           SolrConfig.config.getBool( "requestDispatcher/@handleSelect", false ); 
   67         
   68         log.info("user.dir=" + System.getProperty("user.dir"));
   69         core = SolrCore.getSolrCore();
   70         parsers = new SolrRequestParsers( core, SolrConfig.config );
   71       }
   72       catch( Throwable t ) {
   73         // catch this so our filter still works
   74         SolrConfig.severeErrors.add( t );
   75         SolrCore.log( t );
   76       }
   77       
   78       // Optionally abort if we found a sever error
   79       boolean abortOnConfigurationError = SolrConfig.config.getBool("abortOnConfigurationError",true);
   80       if( abortOnConfigurationError && SolrConfig.severeErrors.size() > 0 ) {
   81         StringWriter sw = new StringWriter();
   82         PrintWriter out = new PrintWriter( sw );
   83         out.println( "Severe errors in solr configuration.\n" );
   84         out.println( "Check your log files for more detailed infomation on what may be wrong.\n" );
   85         out.println( "If you want solr to continue after configuration errors, change: \n");
   86         out.println( " <abortOnConfigurationError>false</abortOnConfigurationError>\n" );
   87         out.println( "in solrconfig.xml\n" );
   88         
   89         for( Throwable t : SolrConfig.severeErrors ) {
   90           out.println( "-------------------------------------------------------------" );
   91           t.printStackTrace( out );
   92         }
   93         out.flush();
   94         
   95         // Servlet containers behave slightly differntly if you throw an exception durring 
   96         // initalization.  Resin will display that error for every page, jetty prints it in
   97         // the logs, but continues normally.  (We will see a 404 rather then the real error)
   98         // rather then leave the behavior undefined, lets cache the error and spit it out 
   99         // for every request.
  100         abortErrorMessage = sw.toString();
  101         //throw new ServletException( abortErrorMessage );
  102       }
  103       
  104       log.info("SolrDispatchFilter.init() done");
  105     }
  106   
  107     public void destroy() {
  108       core.close();
  109     }
  110     
  111     public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException 
  112     {
  113       if( abortErrorMessage != null ) {
  114         ((HttpServletResponse)response).sendError( 500, abortErrorMessage );
  115         return;
  116       }
  117       
  118       if( request instanceof HttpServletRequest) {
  119         SolrQueryRequest solrReq = null;
  120         HttpServletRequest req = (HttpServletRequest)request;
  121         try {
  122           String path = req.getServletPath();    
  123           if( req.getPathInfo() != null ) {
  124             // this lets you handle /update/commit when /update is a servlet
  125             path += req.getPathInfo(); 
  126           }
  127           if( pathPrefix != null && path.startsWith( pathPrefix ) ) {
  128             path = path.substring( pathPrefix.length() );
  129           }
  130           
  131           int idx = path.indexOf( ':' );
  132           if( idx > 0 ) {
  133             // save the portion after the ':' for a 'handler' path parameter
  134             path = path.substring( 0, idx );
  135           }
  136           
  137           SolrRequestHandler handler = null;
  138           if( path.length() > 1 ) { // don't match "" or "/" as valid path
  139             handler = core.getRequestHandler( path );
  140           }
  141           if( handler == null && handleSelect ) {
  142             if( "/select".equals( path ) || "/select/".equals( path ) ) {
  143               solrReq = parsers.parse( path, req );
  144               String qt = solrReq.getParams().get( SolrParams.QT );
  145               if( qt != null && qt.startsWith( "/" ) ) {
  146                 throw new SolrException( SolrException.ErrorCode.BAD_REQUEST, "Invalid query type.  Do not use /select to access: "+qt);
  147               }
  148               handler = core.getRequestHandler( qt );
  149               if( handler == null ) {
  150                 throw new SolrException( SolrException.ErrorCode.BAD_REQUEST, "unknown handler: "+qt);
  151               }
  152             }
  153           }
  154           if( handler != null ) {
  155             if( solrReq == null ) {
  156               solrReq = parsers.parse( path, req );
  157             }
  158             SolrQueryResponse solrRsp = new SolrQueryResponse();
  159             this.execute( req, handler, solrReq, solrRsp );
  160             if( solrRsp.getException() != null ) {
  161               sendError( (HttpServletResponse)response, solrRsp.getException() );
  162               return;
  163             }
  164             
  165             // Now write it out
  166             QueryResponseWriter responseWriter = core.getQueryResponseWriter(solrReq);
  167             response.setContentType(responseWriter.getContentType(solrReq, solrRsp));
  168             PrintWriter out = response.getWriter();
  169             responseWriter.write(out, solrReq, solrRsp);
  170             return;
  171           }
  172         }
  173         catch( Throwable ex ) {
  174           sendError( (HttpServletResponse)response, ex );
  175           return;
  176         }
  177         finally {
  178           if( solrReq != null ) {
  179             solrReq.close();
  180           }
  181         }
  182       }
  183       
  184       // Otherwise let the webapp handle the request
  185       chain.doFilter(request, response);
  186     }
  187   
  188     protected void execute( HttpServletRequest req, SolrRequestHandler handler, SolrQueryRequest sreq, SolrQueryResponse rsp) {
  189       // a custom filter could add more stuff to the request before passing it on.
  190       // for example: sreq.getContext().put( "HttpServletRequest", req );
  191       core.execute( handler, sreq, rsp );
  192     }
  193     
  194     protected void sendError(HttpServletResponse res, Throwable ex) throws IOException 
  195     {
  196       int code=500;
  197       String trace = "";
  198       if( ex instanceof SolrException ) {
  199         code = ((SolrException)ex).code();
  200       }
  201       
  202       // For any regular code, don't include the stack trace
  203       if( code == 500 || code < 100 ) {  
  204         StringWriter sw = new StringWriter();
  205         ex.printStackTrace(new PrintWriter(sw));
  206         trace = "\n\n"+sw.toString();
  207         
  208         SolrException.logOnce(log,null,ex );
  209         
  210         // non standard codes have undefined results with various servers
  211         if( code < 100 ) {
  212           log.warning( "invalid return code: "+code );
  213           code = 500;
  214         }
  215       }
  216       res.sendError( code, ex.getMessage() + trace );
  217     }
  218   
  219     //---------------------------------------------------------------------
  220     //---------------------------------------------------------------------
  221   
  222     /**
  223      * Should the filter handle /select even if it is not mapped in solrconfig.xml
  224      * 
  225      * This will use consistent error handling for /select?qt=xxx and /update/xml
  226      * 
  227      */
  228     public boolean isHandleSelect() {
  229       return handleSelect;
  230     }
  231   
  232     public void setHandleSelect(boolean handleSelect) {
  233       this.handleSelect = handleSelect;
  234     }
  235   
  236     /**
  237      * set the prefix for all paths.  This is useful if you want to apply the
  238      * filter to something other then *.  
  239      * 
  240      * For example, if web.xml specifies:
  241      * 
  242      * <filter-mapping>
  243      *  <filter-name>SolrRequestFilter</filter-name>
  244      *  <url-pattern>/xxx/*</url-pattern>
  245      * </filter-mapping>
  246      * 
  247      * Make sure to set the PathPrefix to "/xxx" either with this function
  248      * or in web.xml
  249      * 
  250      * <init-param>
  251      *  <param-name>path-prefix</param-name>
  252      *  <param-value>/xxx</param-value>
  253      * </init-param>
  254      * 
  255      */
  256     public void setPathPrefix(String pathPrefix) {
  257       this.pathPrefix = pathPrefix;
  258     }
  259   
  260     public String getPathPrefix() {
  261       return pathPrefix;
  262     }
  263   }

Save This Page
Home » apache-solr-1.3.0 » org.apache.solr » servlet » [javadoc | source]