diff --git a/CHANGES.txt b/CHANGES.txt index 32da5fdc627..e0857be3a1f 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -103,6 +103,10 @@ New Features configuration files loaded, including schema.xml and solrconfig.xml. (Erik Hatcher with inspiration from Andrew Saar) +12. SOLR-149: Changes to make Solr more easily embeddable, in addition + to logging which request handler handled each request. + (Ryan McKinley via yonik) + Changes in runtime behavior 1. Highlighting using DisMax will only pick up terms from the main user query, not boost or filter queries (klaas). diff --git a/src/java/org/apache/solr/core/Config.java b/src/java/org/apache/solr/core/Config.java index 79105856048..53471acf3fa 100644 --- a/src/java/org/apache/solr/core/Config.java +++ b/src/java/org/apache/solr/core/Config.java @@ -248,6 +248,11 @@ public class Config { } return instanceDir; } + + public static boolean isInstanceDirInitalized() + { + return instanceDir != null; + } // The directory where solr will look for config files by default. // defaults to "./solr/conf/" diff --git a/src/java/org/apache/solr/core/SolrCore.java b/src/java/org/apache/solr/core/SolrCore.java index bd93551044d..dccdcb4a77a 100644 --- a/src/java/org/apache/solr/core/SolrCore.java +++ b/src/java/org/apache/solr/core/SolrCore.java @@ -608,7 +608,8 @@ public final class SolrCore { handler.handleRequest(req,rsp); setResponseHeaderValues(responseHeader,req,rsp); - log.info(req.getParamString()+ " 0 "+ + log.info(req.getContext().get("path") + " " + + req.getParamString()+ " 0 "+ (int)(rsp.getEndTime() - req.getStartTime())); } diff --git a/src/webapp/WEB-INF/web.xml b/src/webapp/WEB-INF/web.xml index e1227ea35d3..ffaa8ebcec6 100644 --- a/src/webapp/WEB-INF/web.xml +++ b/src/webapp/WEB-INF/web.xml @@ -1,4 +1,4 @@ - + SolrRequestFilter diff --git a/src/webapp/src/org/apache/solr/servlet/SolrDispatchFilter.java b/src/webapp/src/org/apache/solr/servlet/SolrDispatchFilter.java index 4e0e45041ea..f46c9a0c6be 100644 --- a/src/webapp/src/org/apache/solr/servlet/SolrDispatchFilter.java +++ b/src/webapp/src/org/apache/solr/servlet/SolrDispatchFilter.java @@ -40,6 +40,7 @@ import org.apache.solr.core.SolrConfig; import org.apache.solr.core.SolrCore; import org.apache.solr.core.SolrException; import org.apache.solr.request.QueryResponseWriter; +import org.apache.solr.request.SolrParams; import org.apache.solr.request.SolrQueryRequest; import org.apache.solr.request.SolrQueryResponse; import org.apache.solr.request.SolrRequestHandler; @@ -53,31 +54,30 @@ public class SolrDispatchFilter implements Filter protected SolrCore core; protected SolrRequestParsers parsers; + protected boolean handleSelect = false; + protected String pathPrefix = null; // strip this from the begging of a path public void init(FilterConfig config) throws ServletException { log.info("SolrDispatchFilter.init()"); - try { - Context c = new InitialContext(); - - /*** - System.out.println("Enumerating JNDI Context=" + c); - NamingEnumeration en = c.list("java:comp/env"); - while (en.hasMore()) { - NameClassPair ncp = en.next(); - System.out.println(" ENTRY:" + ncp); + + // Only initalize the directory if it has not been done yet + if( !Config.isInstanceDirInitalized() ) { + try { + Context c = new InitialContext(); + String home = (String)c.lookup("java:comp/env/solr/home"); + if (home!=null) Config.setInstanceDir(home); + } catch (NoInitialContextException e) { + log.info("JNDI not configured for Solr (NoInitialContextEx)"); + } catch (NamingException e) { + log.info("No /solr/home in JNDI"); } - System.out.println("JNDI lookup=" + c.lookup("java:comp/env/solr/home")); - ***/ - - String home = (String)c.lookup("java:comp/env/solr/home"); - if (home!=null) Config.setInstanceDir(home); - } catch (NoInitialContextException e) { - log.info("JNDI not configured for Solr (NoInitialContextEx)"); - } catch (NamingException e) { - log.info("No /solr/home in JNDI"); } - + + // web.xml configuration + this.pathPrefix = config.getInitParameter( "path-prefix" ); + this.handleSelect = "true".equals( config.getInitParameter( "handle-select" ) ); + log.info("user.dir=" + System.getProperty("user.dir")); core = SolrCore.getSolrCore(); parsers = new SolrRequestParsers( core, SolrConfig.config ); @@ -99,17 +99,34 @@ public class SolrDispatchFilter implements Filter // this lets you handle /update/commit when /update is a servlet path += req.getPathInfo(); } + if( pathPrefix != null && path.startsWith( pathPrefix ) ) { + path = path.substring( pathPrefix.length() ); + } + int idx = path.indexOf( ':' ); if( idx > 0 ) { // save the portion after the ':' for a 'handler' path parameter path = path.substring( 0, idx ); } + SolrQueryRequest solrReq = null; SolrRequestHandler handler = core.getRequestHandler( path ); + if( handler == null && handleSelect ) { + if( "/select".equals( path ) || "/select/".equals( path ) ) { + solrReq = parsers.parse( path, req ); + String qt = solrReq.getParams().get( SolrParams.QT ); + handler = core.getRequestHandler( qt ); + if( handler == null ) { + throw new SolrException( 400, "unknown handler: "+qt); + } + } + } if( handler != null ) { - SolrQueryRequest solrReq = parsers.parse( path, req ); + if( solrReq == null ) { + solrReq = parsers.parse( path, req ); + } SolrQueryResponse solrRsp = new SolrQueryResponse(); - core.execute( handler, solrReq, solrRsp ); + this.execute( req, handler, solrReq, solrRsp ); if( solrRsp.getException() != null ) { sendError( (HttpServletResponse)response, solrRsp.getException() ); return; @@ -132,6 +149,12 @@ public class SolrDispatchFilter implements Filter // Otherwise let the webapp handle the request chain.doFilter(request, response); } + + protected void execute( HttpServletRequest req, SolrRequestHandler handler, SolrQueryRequest sreq, SolrQueryResponse rsp) { + // a custom filter could add more stuff to the request before passing it on. + // for example: sreq.getContext().put( "HttpServletRequest", req ); + core.execute( handler, sreq, rsp ); + } protected void sendError(HttpServletResponse res, Throwable ex) throws IOException { @@ -157,4 +180,49 @@ public class SolrDispatchFilter implements Filter } res.sendError( code, ex.getMessage() + trace ); } + + //--------------------------------------------------------------------- + //--------------------------------------------------------------------- + + /** + * Should the filter handle /select even if it is not mapped in solrconfig.xml + * + * This will use consistent error handling for /select?qt=xxx and /update/xml + * + */ + public boolean isHandleSelect() { + return handleSelect; + } + + public void setHandleSelect(boolean handleSelect) { + this.handleSelect = handleSelect; + } + + /** + * set the prefix for all paths. This is useful if you want to apply the + * filter to something other then *. + * + * For example, if web.xml specifies: + * + * + * SolrRequestFilter + * /xxx/* + * + * + * Make sure to set the PathPrefix to "/xxx" either with this function + * or in web.xml + * + * + * path-prefix + * /xxx + * + * + */ + public void setPathPrefix(String pathPrefix) { + this.pathPrefix = pathPrefix; + } + + public String getPathPrefix() { + return pathPrefix; + } } diff --git a/src/webapp/src/org/apache/solr/servlet/SolrRequestParsers.java b/src/webapp/src/org/apache/solr/servlet/SolrRequestParsers.java index e07b16a3bb9..7bdc825144b 100644 --- a/src/webapp/src/org/apache/solr/servlet/SolrRequestParsers.java +++ b/src/webapp/src/org/apache/solr/servlet/SolrRequestParsers.java @@ -109,11 +109,9 @@ public class SolrRequestParsers SolrParams params = parser.parseParamsAndFillStreams( req, streams ); SolrQueryRequest sreq = buildRequestFrom( params, streams ); - // If there is some path left over, add it to the context - int idx = req.getServletPath().indexOf( ':' ); - if( idx > 0 ) { - sreq.getContext().put( "path", req.getServletPath().substring( idx+1 ) ); - } + // Handlers and loggin will want to know the path. If it contains a ':' + // the handler could use it for RESTfull URLs + sreq.getContext().put( "path", path ); return sreq; }