SOLR-6585

git-svn-id: https://svn.apache.org/repos/asf/lucene/dev/trunk@1629433 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Noble Paul 2014-10-04 18:01:03 +00:00
parent 50b2e81e1c
commit c1fb329601
12 changed files with 136 additions and 18 deletions

View File

@ -410,6 +410,8 @@ New Features
* SOLR-6233: Provide basic command line tools for checking Solr status and health. * SOLR-6233: Provide basic command line tools for checking Solr status and health.
(Timothy Potter) (Timothy Potter)
* SOLR-6585: RequestHandlers can optionaly handle sub paths as well (Noble Paul)
Bug Fixes Bug Fixes
---------------------- ----------------------

View File

@ -22,6 +22,8 @@ import static com.google.common.base.Preconditions.checkNotNull;
import java.io.File; import java.io.File;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Locale; import java.util.Locale;
import java.util.Map; import java.util.Map;
@ -35,11 +37,13 @@ import org.apache.solr.cloud.ZkController;
import org.apache.solr.common.SolrException; import org.apache.solr.common.SolrException;
import org.apache.solr.common.SolrException.ErrorCode; import org.apache.solr.common.SolrException.ErrorCode;
import org.apache.solr.common.util.ExecutorUtil; import org.apache.solr.common.util.ExecutorUtil;
import org.apache.solr.handler.RequestHandlerBase;
import org.apache.solr.handler.admin.CollectionsHandler; import org.apache.solr.handler.admin.CollectionsHandler;
import org.apache.solr.handler.admin.CoreAdminHandler; import org.apache.solr.handler.admin.CoreAdminHandler;
import org.apache.solr.handler.admin.InfoHandler; import org.apache.solr.handler.admin.InfoHandler;
import org.apache.solr.handler.component.ShardHandlerFactory; import org.apache.solr.handler.component.ShardHandlerFactory;
import org.apache.solr.logging.LogWatcher; import org.apache.solr.logging.LogWatcher;
import org.apache.solr.request.SolrRequestHandler;
import org.apache.solr.update.UpdateShardHandler; import org.apache.solr.update.UpdateShardHandler;
import org.apache.solr.util.DefaultSolrThreadFactory; import org.apache.solr.util.DefaultSolrThreadFactory;
import org.apache.solr.util.FileUtils; import org.apache.solr.util.FileUtils;
@ -99,6 +103,17 @@ public class CoreContainer {
private String hostName; private String hostName;
private Map<String ,SolrRequestHandler> containerHandlers = new HashMap<>();
public SolrRequestHandler getRequestHandler(String path) {
return RequestHandlerBase.getRequestHandler(path, containerHandlers);
}
public Map<String, SolrRequestHandler> getRequestHandlers(){
return this.containerHandlers;
}
// private ClientConnectionManager clientConnectionManager = new PoolingClientConnectionManager(); // private ClientConnectionManager clientConnectionManager = new PoolingClientConnectionManager();
{ {
@ -222,8 +237,11 @@ public class CoreContainer {
zkSys.initZooKeeper(this, solrHome, cfg); zkSys.initZooKeeper(this, solrHome, cfg);
collectionsHandler = createHandler(cfg.getCollectionsHandlerClass(), CollectionsHandler.class); collectionsHandler = createHandler(cfg.getCollectionsHandlerClass(), CollectionsHandler.class);
containerHandlers.put("/admin/collections" , collectionsHandler);
infoHandler = createHandler(cfg.getInfoHandlerClass(), InfoHandler.class); infoHandler = createHandler(cfg.getInfoHandlerClass(), InfoHandler.class);
containerHandlers.put("/admin/info" , infoHandler);
coreAdminHandler = createHandler(cfg.getCoreAdminHandlerClass(), CoreAdminHandler.class); coreAdminHandler = createHandler(cfg.getCoreAdminHandlerClass(), CoreAdminHandler.class);
containerHandlers.put(cfg.getAdminPath() , coreAdminHandler);
coreConfigService = cfg.createCoreConfigService(loader, zkSys.getZkController()); coreConfigService = cfg.createCoreConfigService(loader, zkSys.getZkController());

View File

@ -49,6 +49,7 @@ public final class RequestHandlers {
// the map implementation should be thread safe // the map implementation should be thread safe
private final Map<String, SolrRequestHandler> handlers = private final Map<String, SolrRequestHandler> handlers =
new ConcurrentHashMap<>() ; new ConcurrentHashMap<>() ;
private final Map<String, SolrRequestHandler> immutableHandlers = Collections.unmodifiableMap(handlers) ;
/** /**
* Trim the trailing '/' if its there, and convert null to empty string. * Trim the trailing '/' if its there, and convert null to empty string.
@ -59,7 +60,7 @@ public final class RequestHandlers {
* to map to the same handler * to map to the same handler
* *
*/ */
private static String normalize( String p ) public static String normalize( String p )
{ {
if(p == null) return ""; if(p == null) return "";
if( p.endsWith( "/" ) && p.length() > 1 ) if( p.endsWith( "/" ) && p.length() > 1 )
@ -114,7 +115,7 @@ public final class RequestHandlers {
* Returns an unmodifiable Map containing the registered handlers * Returns an unmodifiable Map containing the registered handlers
*/ */
public Map<String,SolrRequestHandler> getRequestHandlers() { public Map<String,SolrRequestHandler> getRequestHandlers() {
return Collections.unmodifiableMap( handlers ); return immutableHandlers;
} }

View File

@ -38,6 +38,7 @@ import org.apache.solr.common.util.ExecutorUtil;
import org.apache.solr.common.util.NamedList; import org.apache.solr.common.util.NamedList;
import org.apache.solr.common.util.SimpleOrderedMap; import org.apache.solr.common.util.SimpleOrderedMap;
import org.apache.solr.core.DirectoryFactory.DirContext; import org.apache.solr.core.DirectoryFactory.DirContext;
import org.apache.solr.handler.RequestHandlerBase;
import org.apache.solr.handler.SnapPuller; import org.apache.solr.handler.SnapPuller;
import org.apache.solr.handler.UpdateRequestHandler; import org.apache.solr.handler.UpdateRequestHandler;
import org.apache.solr.handler.admin.ShowFileRequestHandler; import org.apache.solr.handler.admin.ShowFileRequestHandler;
@ -1217,7 +1218,7 @@ public final class SolrCore implements SolrInfoMBean, Closeable {
* This function is thread safe. * This function is thread safe.
*/ */
public SolrRequestHandler getRequestHandler(String handlerName) { public SolrRequestHandler getRequestHandler(String handlerName) {
return reqHandlers.get(handlerName); return RequestHandlerBase.getRequestHandler(RequestHandlers.normalize(handlerName), reqHandlers.getRequestHandlers());
} }
/** /**

View File

@ -20,13 +20,18 @@ package org.apache.solr.handler;
import java.io.IOException; import java.io.IOException;
import java.io.Reader; import java.io.Reader;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List;
import org.apache.commons.io.IOUtils; import org.apache.commons.io.IOUtils;
import org.apache.solr.common.util.ContentStream; import org.apache.solr.common.util.ContentStream;
import org.apache.solr.common.util.NamedList; import org.apache.solr.common.util.NamedList;
import org.apache.solr.common.util.SimpleOrderedMap; import org.apache.solr.common.util.SimpleOrderedMap;
import org.apache.solr.core.InitParams;
import org.apache.solr.core.PluginInfo;
import org.apache.solr.request.SolrQueryRequest; import org.apache.solr.request.SolrQueryRequest;
import org.apache.solr.request.SolrRequestHandler;
import org.apache.solr.response.SolrQueryResponse; import org.apache.solr.response.SolrQueryResponse;
import org.apache.solr.util.plugin.PluginInfoInitialized;
public class DumpRequestHandler extends RequestHandlerBase public class DumpRequestHandler extends RequestHandlerBase
{ {
@ -81,4 +86,20 @@ public class DumpRequestHandler extends RequestHandlerBase
public String getDescription() { public String getDescription() {
return "Dump handler (debug)"; return "Dump handler (debug)";
} }
@Override
public SolrRequestHandler getSubHandler(String path) {
if(subpaths !=null && subpaths.contains(path)) return this;
return null;
}
private List<String> subpaths;
@Override
public void init(NamedList args) {
super.init(args);
if(args !=null) {
NamedList nl = (NamedList) args.get(PluginInfo.DEFAULTS);
if(nl!=null) subpaths = nl.getAll("subpath");
}
}
} }

View File

@ -0,0 +1,28 @@
package org.apache.solr.handler;
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import org.apache.solr.request.SolrRequestHandler;
/**An interface for RequestHandlers need to handle all paths under its registered path
*/
public interface NestedRequestHandler {
public SolrRequestHandler getSubHandler(String path);
}

View File

@ -33,12 +33,13 @@ import org.apache.solr.util.stats.Timer;
import org.apache.solr.util.stats.TimerContext; import org.apache.solr.util.stats.TimerContext;
import java.net.URL; import java.net.URL;
import java.util.Map;
import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.atomic.AtomicLong;
/** /**
* *
*/ */
public abstract class RequestHandlerBase implements SolrRequestHandler, SolrInfoMBean { public abstract class RequestHandlerBase implements SolrRequestHandler, SolrInfoMBean, NestedRequestHandler {
protected NamedList initArgs = null; protected NamedList initArgs = null;
protected SolrParams defaults; protected SolrParams defaults;
@ -194,6 +195,41 @@ public abstract class RequestHandlerBase implements SolrRequestHandler, SolrInfo
return null; // this can be overridden, but not required return null; // this can be overridden, but not required
} }
@Override
public SolrRequestHandler getSubHandler(String path) {
return null;
}
/**
* Get the request handler registered to a given name.
*
* This function is thread safe.
*/
public static SolrRequestHandler getRequestHandler(String handlerName, Map<String, SolrRequestHandler> reqHandlers) {
if(handlerName == null) return null;
SolrRequestHandler handler = reqHandlers.get(handlerName);
int idx = 0;
if(handler == null) {
for (; ; ) {
idx = handlerName.indexOf('/', idx+1);
if (idx > 0) {
String firstPart = handlerName.substring(0, idx);
handler = reqHandlers.get(firstPart);
if (handler == null) continue;
if (handler instanceof NestedRequestHandler) {
return ((NestedRequestHandler) handler).getSubHandler(handlerName.substring(idx));
}
} else {
break;
}
}
}
return handler;
}
@Override @Override
public NamedList<Object> getStatistics() { public NamedList<Object> getStatistics() {
NamedList<Object> lst = new SimpleOrderedMap<>(); NamedList<Object> lst = new SimpleOrderedMap<>();

View File

@ -60,5 +60,7 @@ public interface SolrRequestHandler extends SolrInfoMBean {
* all interface obligations. * all interface obligations.
*/ */
public void handleRequest(SolrQueryRequest req, SolrQueryResponse rsp); public void handleRequest(SolrQueryRequest req, SolrQueryResponse rsp);
public static final String TYPE = "requestHandler";
} }

View File

@ -256,20 +256,12 @@ public class SolrDispatchFilter extends BaseSolrFilter {
boolean usingAliases = false; boolean usingAliases = false;
List<String> collectionsList = null; List<String> collectionsList = null;
// Check for the core admin collections url // Check for the core admin collections url
if( path.equals( "/admin/collections" ) ) { handler = cores.getRequestHandler(path);
handler = cores.getCollectionsHandler(); if( handler!= null ) {
solrReq = SolrRequestParsers.DEFAULT.parse(null,path, req); solrReq = SolrRequestParsers.DEFAULT.parse(null,path, req);
handleAdminRequest(req, response, handler, solrReq); handleAdminRequest(req, response, handler, solrReq);
return; return;
} } else {
// Check for the core admin info url
if( path.startsWith( "/admin/info" ) ) {
handler = cores.getInfoHandler();
solrReq = SolrRequestParsers.DEFAULT.parse(null,path, req);
handleAdminRequest(req, response, handler, solrReq);
return;
}
else {
//otherwise, we should find a core from the path //otherwise, we should find a core from the path
idx = path.indexOf( "/", 1 ); idx = path.indexOf( "/", 1 );
if( idx > 1 ) { if( idx > 1 ) {

View File

@ -52,6 +52,7 @@ import org.apache.solr.common.params.SolrParams;
import org.apache.solr.common.util.ContentStream; import org.apache.solr.common.util.ContentStream;
import org.apache.solr.common.util.ContentStreamBase; import org.apache.solr.common.util.ContentStreamBase;
import org.apache.solr.common.util.FastInputStream; import org.apache.solr.common.util.FastInputStream;
import org.apache.solr.core.CoreContainer;
import org.apache.solr.core.SolrConfig; import org.apache.solr.core.SolrConfig;
import org.apache.solr.core.SolrCore; import org.apache.solr.core.SolrCore;
import org.apache.solr.request.SolrQueryRequest; import org.apache.solr.request.SolrQueryRequest;
@ -149,6 +150,7 @@ public class SolrRequestParsers
// Handlers and login will want to know the path. If it contains a ':' // Handlers and login will want to know the path. If it contains a ':'
// the handler could use it for RESTful URLs // the handler could use it for RESTful URLs
sreq.getContext().put( "path", path ); sreq.getContext().put( "path", path );
sreq.getContext().put("httpMethod", req.getMethod());
if(addHttpRequestToContext) { if(addHttpRequestToContext) {
sreq.getContext().put("httpRequest", req); sreq.getContext().put("httpRequest", req);

View File

@ -60,5 +60,13 @@
</lst> </lst>
</requestHandler> </requestHandler>
<requestHandler name="/greedypath" class="DumpRequestHandler">
<lst name="defaults">
<str name="subpath">/some/path</str>
<str name="subpath">/some/other/path</str>
</lst>
</requestHandler>
</config> </config>

View File

@ -90,6 +90,13 @@ public class TestInitParams extends SolrTestCaseJ4 {
assertEquals(Arrays.asList("C1","C") ,def.getAll("c")); assertEquals(Arrays.asList("C1","C") ,def.getAll("c"));
} }
public void testNestedRequestHandler() {
assertNotNull(h.getCore().getRequestHandler("/greedypath"));
assertNotNull(h.getCore().getRequestHandler("/greedypath/some/path"));
assertNotNull( h.getCore().getRequestHandler("/greedypath/some/other/path"));
assertNull(h.getCore().getRequestHandler("/greedypath/unknownpath"));
}