mirror of https://github.com/apache/lucene.git
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:
parent
50b2e81e1c
commit
c1fb329601
|
@ -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
|
||||||
----------------------
|
----------------------
|
||||||
|
|
||||||
|
|
|
@ -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());
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -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");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
|
@ -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<>();
|
||||||
|
|
|
@ -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";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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 ) {
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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"));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue