mirror of https://github.com/apache/lucene.git
SOLR-7073: Add an API to add a jar to a collection's classpath
git-svn-id: https://svn.apache.org/repos/asf/lucene/dev/trunk@1664797 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
29b23f9166
commit
b221a53496
|
@ -84,6 +84,9 @@ Upgrading from Solr 5.0
|
|||
* The signature of SolrDispatchFilter.createCoreContainer() has changed to take
|
||||
(String,Properties) arguments
|
||||
|
||||
* Deprecated the 'lib' option added to create-requesthandler as part of SOLR-6801 in 5.0 release.
|
||||
Please use the add-runtimelib command
|
||||
|
||||
Detailed Change List
|
||||
----------------------
|
||||
|
||||
|
@ -136,6 +139,8 @@ New Features
|
|||
* SOLR-7155: All SolrClient methods now take an optional 'collection' argument
|
||||
(Alan Woodward)
|
||||
|
||||
* SOLR-7073: Support adding a jar to a collections classpath (Noble Paul)
|
||||
|
||||
Bug Fixes
|
||||
----------------------
|
||||
|
||||
|
|
|
@ -39,7 +39,6 @@ import org.apache.solr.common.params.UpdateParams;
|
|||
import org.apache.solr.core.CoreContainer;
|
||||
import org.apache.solr.core.CoreDescriptor;
|
||||
import org.apache.solr.core.DirectoryFactory.DirContext;
|
||||
import org.apache.solr.core.RequestHandlers.LazyRequestHandlerWrapper;
|
||||
import org.apache.solr.core.SolrCore;
|
||||
import org.apache.solr.handler.ReplicationHandler;
|
||||
import org.apache.solr.request.LocalSolrQueryRequest;
|
||||
|
@ -146,9 +145,6 @@ public class RecoveryStrategy extends Thread implements ClosableThread {
|
|||
|
||||
// use rep handler directly, so we can do this sync rather than async
|
||||
SolrRequestHandler handler = core.getRequestHandler(REPLICATION_HANDLER);
|
||||
if (handler instanceof LazyRequestHandlerWrapper) {
|
||||
handler = ((LazyRequestHandlerWrapper) handler).getWrappedHandler();
|
||||
}
|
||||
ReplicationHandler replicationHandler = (ReplicationHandler) handler;
|
||||
|
||||
if (replicationHandler == null) {
|
||||
|
|
|
@ -41,7 +41,6 @@ import org.slf4j.LoggerFactory;
|
|||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
|
@ -108,13 +107,13 @@ public class CoreContainer {
|
|||
public static final String COLLECTIONS_HANDLER_PATH = "/admin/collections";
|
||||
public static final String INFO_HANDLER_PATH = "/admin/info";
|
||||
|
||||
private Map<String, SolrRequestHandler> containerHandlers = new HashMap<>();
|
||||
private PluginRegistry<SolrRequestHandler> containerHandlers = new PluginRegistry<>(SolrRequestHandler.class, null);
|
||||
|
||||
public SolrRequestHandler getRequestHandler(String path) {
|
||||
return RequestHandlerBase.getRequestHandler(path, containerHandlers);
|
||||
}
|
||||
|
||||
public Map<String, SolrRequestHandler> getRequestHandlers(){
|
||||
public PluginRegistry<SolrRequestHandler> getRequestHandlers() {
|
||||
return this.containerHandlers;
|
||||
}
|
||||
|
||||
|
|
|
@ -45,7 +45,7 @@ import static org.apache.solr.common.cloud.ZkNodeProps.makeMap;
|
|||
import static org.apache.solr.core.PluginInfo.DEFAULTS;
|
||||
import static org.apache.solr.core.PluginInfo.INVARIANTS;
|
||||
|
||||
public class PluginsRegistry {
|
||||
public class ImplicitPlugins {
|
||||
|
||||
public static List<PluginInfo> getHandlers(SolrCore solrCore){
|
||||
List<PluginInfo> implicits = new ArrayList<>();
|
||||
|
@ -88,4 +88,5 @@ public class PluginsRegistry {
|
|||
Map m = makeMap("name", name, "class", clz.getName());
|
||||
return new PluginInfo(SolrRequestHandler.TYPE, m, new NamedList<>(singletonMap(DEFAULTS, new NamedList(defaults))),null);
|
||||
}
|
||||
public static final String IMPLICIT = "implicit";
|
||||
}
|
|
@ -24,7 +24,6 @@ import java.io.ByteArrayInputStream;
|
|||
import java.io.IOException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
|
@ -43,7 +42,6 @@ import org.apache.solr.common.cloud.ClusterState;
|
|||
import org.apache.solr.common.cloud.DocCollection;
|
||||
import org.apache.solr.common.cloud.Replica;
|
||||
import org.apache.solr.common.cloud.Slice;
|
||||
import org.apache.solr.common.cloud.ZkCoreNodeProps;
|
||||
import org.apache.solr.common.cloud.ZkStateReader;
|
||||
import org.apache.solr.handler.admin.CollectionsHandler;
|
||||
import org.apache.solr.util.SimplePostTool;
|
||||
|
@ -76,37 +74,16 @@ public class JarRepository {
|
|||
}
|
||||
|
||||
/**
|
||||
* Returns the contents of a jar and increments a reference count. Please return the same object to decerease the refcount
|
||||
* Returns the contents of a jar and increments a reference count. Please return the same object to decrease the refcount
|
||||
*
|
||||
* @param key it is a combination of blobname and version like blobName/version
|
||||
* @return The reference of a jar
|
||||
*/
|
||||
public JarContentRef getJarIncRef(String key) throws IOException {
|
||||
public JarContentRef getJarIncRef(String key) {
|
||||
JarContent jar = jars.get(key);
|
||||
if (jar == null) {
|
||||
if (this.coreContainer.isZooKeeperAware()) {
|
||||
ZkStateReader zkStateReader = this.coreContainer.getZkController().getZkStateReader();
|
||||
ClusterState cs = zkStateReader.getClusterState();
|
||||
DocCollection coll = cs.getCollectionOrNull(CollectionsHandler.SYSTEM_COLL);
|
||||
if (coll == null) throw new SolrException(SERVICE_UNAVAILABLE, ".system collection not available");
|
||||
ArrayList<Slice> slices = new ArrayList<>(coll.getActiveSlices());
|
||||
if (slices.isEmpty()) throw new SolrException(SERVICE_UNAVAILABLE, "No active slices for .system collection");
|
||||
Collections.shuffle(slices, RANDOM); //do load balancing
|
||||
|
||||
Replica replica = null;
|
||||
for (Slice slice : slices) {
|
||||
List<Replica> replicas = new ArrayList<>(slice.getReplicasMap().values());
|
||||
Collections.shuffle(replicas, RANDOM);
|
||||
for (Replica r : replicas) {
|
||||
if (ZkStateReader.ACTIVE.equals(r.getStr(ZkStateReader.STATE_PROP))) {
|
||||
replica = r;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (replica == null) {
|
||||
throw new SolrException(SERVICE_UNAVAILABLE, ".no active replica available for .system collection");
|
||||
}
|
||||
Replica replica = getSystemCollReplica();
|
||||
String url = replica.getStr(BASE_URL_PROP) + "/.system/blob/" + key + "?wt=filestream";
|
||||
|
||||
HttpClient httpClient = coreContainer.getUpdateShardHandler().getHttpClient();
|
||||
|
@ -119,6 +96,12 @@ public class JarRepository {
|
|||
throw new SolrException(SolrException.ErrorCode.NOT_FOUND, "no such blob or version available: " + key);
|
||||
}
|
||||
b = SimplePostTool.inputStreamToByteArray(entity.getEntity().getContent());
|
||||
} catch (Exception e) {
|
||||
if (e instanceof SolrException) {
|
||||
throw (SolrException) e;
|
||||
} else {
|
||||
throw new SolrException(SolrException.ErrorCode.NOT_FOUND, "could not load : " + key, e);
|
||||
}
|
||||
} finally {
|
||||
httpGet.releaseConnection();
|
||||
}
|
||||
|
@ -138,6 +121,36 @@ public class JarRepository {
|
|||
|
||||
}
|
||||
|
||||
private Replica getSystemCollReplica() {
|
||||
ZkStateReader zkStateReader = this.coreContainer.getZkController().getZkStateReader();
|
||||
ClusterState cs = zkStateReader.getClusterState();
|
||||
DocCollection coll = cs.getCollectionOrNull(CollectionsHandler.SYSTEM_COLL);
|
||||
if (coll == null) throw new SolrException(SERVICE_UNAVAILABLE, ".system collection not available");
|
||||
ArrayList<Slice> slices = new ArrayList<>(coll.getActiveSlices());
|
||||
if (slices.isEmpty()) throw new SolrException(SERVICE_UNAVAILABLE, "No active slices for .system collection");
|
||||
Collections.shuffle(slices, RANDOM); //do load balancing
|
||||
|
||||
Replica replica = null;
|
||||
for (Slice slice : slices) {
|
||||
List<Replica> replicas = new ArrayList<>(slice.getReplicasMap().values());
|
||||
Collections.shuffle(replicas, RANDOM);
|
||||
for (Replica r : replicas) {
|
||||
if (ZkStateReader.ACTIVE.equals(r.getStr(ZkStateReader.STATE_PROP))) {
|
||||
if(zkStateReader.getClusterState().getLiveNodes().contains(r.get(ZkStateReader.NODE_NAME_PROP))){
|
||||
replica = r;
|
||||
break;
|
||||
} else {
|
||||
log.info("replica {} says it is active but not a member of live nodes", r.get(ZkStateReader.NODE_NAME_PROP));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (replica == null) {
|
||||
throw new SolrException(SERVICE_UNAVAILABLE, ".no active replica available for .system collection");
|
||||
}
|
||||
return replica;
|
||||
}
|
||||
|
||||
/**
|
||||
* This is to decrement a ref count
|
||||
*
|
||||
|
|
|
@ -0,0 +1,180 @@
|
|||
package org.apache.solr.core;
|
||||
|
||||
/*
|
||||
* 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 java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.security.CodeSource;
|
||||
import java.security.ProtectionDomain;
|
||||
import java.security.cert.Certificate;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
import org.apache.lucene.analysis.util.ResourceLoader;
|
||||
import org.apache.solr.common.SolrException;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
|
||||
public class MemClassLoader extends ClassLoader implements AutoCloseable, ResourceLoader {
|
||||
static final Logger log = LoggerFactory.getLogger(MemClassLoader.class);
|
||||
private boolean allJarsLoaded = false;
|
||||
private final SolrResourceLoader parentLoader;
|
||||
private List<PluginRegistry.RuntimeLib> libs = new ArrayList<>();
|
||||
private Map<String, Class> classCache = new HashMap<>();
|
||||
|
||||
|
||||
public MemClassLoader(List<PluginRegistry.RuntimeLib> libs, SolrResourceLoader resourceLoader) {
|
||||
this.parentLoader = resourceLoader;
|
||||
this.libs = libs;
|
||||
}
|
||||
|
||||
|
||||
public synchronized void loadJars() {
|
||||
if (allJarsLoaded) return;
|
||||
|
||||
for (PluginRegistry.RuntimeLib lib : libs) {
|
||||
try {
|
||||
lib.loadJar();
|
||||
} catch (Exception exception) {
|
||||
if (exception instanceof SolrException) throw (SolrException) exception;
|
||||
throw new SolrException(SolrException.ErrorCode.SERVER_ERROR, "Atleast one runtimeLib could not be loaded", exception);
|
||||
}
|
||||
}
|
||||
allJarsLoaded = true;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected Class<?> findClass(String name) throws ClassNotFoundException {
|
||||
if(!allJarsLoaded ) loadJars();
|
||||
try {
|
||||
return parentLoader.findClass(name, Object.class);
|
||||
} catch (Exception e) {
|
||||
return loadFromRuntimeLibs(name);
|
||||
}
|
||||
}
|
||||
|
||||
private synchronized Class<?> loadFromRuntimeLibs(String name) throws ClassNotFoundException {
|
||||
Class result = classCache.get(name);
|
||||
if(result != null)
|
||||
return result;
|
||||
AtomicReference<String> jarName = new AtomicReference<>();
|
||||
ByteBuffer buf = null;
|
||||
try {
|
||||
buf = getByteBuffer(name, jarName);
|
||||
} catch (Exception e) {
|
||||
throw new ClassNotFoundException("class could not be loaded " + name, e);
|
||||
}
|
||||
if (buf == null) throw new ClassNotFoundException("Class not found :" + name);
|
||||
ProtectionDomain defaultDomain = null;
|
||||
//using the default protection domain, with no permissions
|
||||
try {
|
||||
defaultDomain = new ProtectionDomain(new CodeSource(new URL("http://localhost/.system/blob/" + jarName.get()), (Certificate[]) null),
|
||||
null);
|
||||
} catch (MalformedURLException mue) {
|
||||
throw new ClassNotFoundException("Unexpected exception ", mue);
|
||||
//should not happen
|
||||
}
|
||||
log.info("Defining_class {} from runtime jar {} ", name, jarName);
|
||||
|
||||
result = defineClass(name, buf.array(), buf.arrayOffset(), buf.limit(), defaultDomain);
|
||||
classCache.put(name, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
private ByteBuffer getByteBuffer(String name, AtomicReference<String> jarName) throws Exception {
|
||||
if (!allJarsLoaded) {
|
||||
loadJars();
|
||||
|
||||
}
|
||||
|
||||
String path = name.replace('.', '/').concat(".class");
|
||||
ByteBuffer buf = null;
|
||||
for (PluginRegistry.RuntimeLib lib : libs) {
|
||||
try {
|
||||
buf = lib.getFileContent(path);
|
||||
if (buf != null) {
|
||||
jarName.set(lib.name);
|
||||
break;
|
||||
}
|
||||
} catch (Exception exp) {
|
||||
throw new ClassNotFoundException("Unable to load class :" + name, exp);
|
||||
}
|
||||
}
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws Exception {
|
||||
for (PluginRegistry.RuntimeLib lib : libs) {
|
||||
try {
|
||||
lib.close();
|
||||
} catch (Exception e) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public InputStream openResource(String resource) throws IOException {
|
||||
AtomicReference<String> jarName = new AtomicReference<>();
|
||||
try {
|
||||
ByteBuffer buf = getByteBuffer(resource, jarName);
|
||||
if (buf == null) throw new IOException("Resource could not be found " + resource);
|
||||
} catch (Exception e) {
|
||||
throw new IOException("Resource could not be found " + resource, e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> Class<? extends T> findClass(String cname, Class<T> expectedType) {
|
||||
if(!allJarsLoaded ) loadJars();
|
||||
try {
|
||||
return findClass(cname).asSubclass(expectedType);
|
||||
} catch (Exception e) {
|
||||
if (e instanceof SolrException) {
|
||||
throw (SolrException) e;
|
||||
} else {
|
||||
throw new SolrException(SolrException.ErrorCode.SERVER_ERROR, "error loading class " + cname, e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T newInstance(String cname, Class<T> expectedType) {
|
||||
try {
|
||||
return findClass(cname, expectedType).newInstance();
|
||||
} catch (SolrException e) {
|
||||
throw e;
|
||||
} catch (Exception e) {
|
||||
throw new SolrException(SolrException.ErrorCode.SERVER_ERROR, "error instantiating class :" + cname, e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,371 @@
|
|||
package org.apache.solr.core;
|
||||
|
||||
/*
|
||||
* 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 java.io.IOException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.lucene.analysis.util.ResourceLoader;
|
||||
import org.apache.lucene.analysis.util.ResourceLoaderAware;
|
||||
import org.apache.solr.common.SolrException;
|
||||
import org.apache.solr.handler.RequestHandlerBase;
|
||||
import org.apache.solr.handler.component.SearchComponent;
|
||||
import org.apache.solr.request.SolrRequestHandler;
|
||||
import org.apache.solr.util.plugin.NamedListInitializedPlugin;
|
||||
import org.apache.solr.util.plugin.PluginInfoInitialized;
|
||||
import org.apache.solr.util.plugin.SolrCoreAware;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import static java.util.Collections.singletonList;
|
||||
|
||||
/**
|
||||
* This manages the lifecycle of a set of plugin of the same type .
|
||||
*/
|
||||
public class PluginRegistry<T> implements AutoCloseable {
|
||||
public static Logger log = LoggerFactory.getLogger(PluginRegistry.class);
|
||||
|
||||
private Map<String, PluginHolder<T>> registry = new HashMap<>();
|
||||
private Map<String, PluginHolder<T>> immutableRegistry = Collections.unmodifiableMap(registry);
|
||||
private String def;
|
||||
private Class klass;
|
||||
private SolrCore core;
|
||||
private SolrConfig.SolrPluginInfo meta;
|
||||
|
||||
public PluginRegistry(Class<T> klass, SolrCore core) {
|
||||
this.core = core;
|
||||
this.klass = klass;
|
||||
meta = SolrConfig.classVsSolrPluginInfo.get(klass.getName());
|
||||
if (meta == null) {
|
||||
throw new SolrException(SolrException.ErrorCode.SERVER_ERROR, "Unknown Plugin : " + klass.getName());
|
||||
}
|
||||
}
|
||||
|
||||
static void initInstance(Object inst, PluginInfo info, SolrCore core) {
|
||||
if (inst instanceof PluginInfoInitialized) {
|
||||
((PluginInfoInitialized) inst).init(info);
|
||||
} else if (inst instanceof NamedListInitializedPlugin) {
|
||||
((NamedListInitializedPlugin) inst).init(info.initArgs);
|
||||
} else if (inst instanceof SolrRequestHandler) {
|
||||
((SolrRequestHandler) inst).init(info.initArgs);
|
||||
}
|
||||
if (inst instanceof SearchComponent) {
|
||||
((SearchComponent) inst).setName(info.name);
|
||||
}
|
||||
if (inst instanceof RequestHandlerBase) {
|
||||
((RequestHandlerBase) inst).setPluginInfo(info);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
PluginHolder<T> createPlugin(PluginInfo info, SolrCore core) {
|
||||
if ("true".equals(String.valueOf(info.attributes.get("runtimeLib")))) {
|
||||
log.info(" {} : '{}' created with runtimeLib=true ", meta.tag, info.name);
|
||||
return new LazyPluginHolder<>(meta, info, core, core.getMemClassLoader());
|
||||
} else if ("lazy".equals(info.attributes.get("startup")) && meta.options.contains(SolrConfig.PluginOpts.LAZY)) {
|
||||
log.info("{} : '{}' created with startup=lazy ", meta.tag, info.name);
|
||||
return new LazyPluginHolder<T>(meta, info, core, core.getResourceLoader());
|
||||
} else {
|
||||
T inst = core.createInstance(info.className, (Class<T>) meta.clazz, meta.tag, null, core.getResourceLoader());
|
||||
initInstance(inst, info, core);
|
||||
return new PluginHolder<>(info, inst);
|
||||
}
|
||||
}
|
||||
|
||||
boolean alias(String src, String target) {
|
||||
PluginHolder<T> a = registry.get(src);
|
||||
if (a == null) return false;
|
||||
PluginHolder<T> b = registry.get(target);
|
||||
if (b != null) return false;
|
||||
registry.put(target, a);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a plugin by name. If the plugin is not already instantiated, it is
|
||||
* done here
|
||||
*/
|
||||
public T get(String name) {
|
||||
PluginHolder<T> result = registry.get(name);
|
||||
return result == null ? null : result.get();
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches a plugin by name , or the default
|
||||
*
|
||||
* @param name name using which it is registered
|
||||
* @param useDefault Return the default , if a plugin by that name does not exist
|
||||
*/
|
||||
public T get(String name, boolean useDefault) {
|
||||
T result = get(name);
|
||||
if (useDefault && result == null) return get(def);
|
||||
return result;
|
||||
}
|
||||
|
||||
public Set<String> keySet() {
|
||||
return immutableRegistry.keySet();
|
||||
}
|
||||
|
||||
/**
|
||||
* register a plugin by a name
|
||||
*/
|
||||
public T put(String name, T plugin) {
|
||||
if (plugin == null) return null;
|
||||
PluginHolder<T> old = put(name, new PluginHolder<T>(null, plugin));
|
||||
return old == null ? null : old.get();
|
||||
}
|
||||
|
||||
|
||||
PluginHolder<T> put(String name, PluginHolder<T> plugin) {
|
||||
PluginHolder<T> old = registry.put(name, plugin);
|
||||
if (plugin.pluginInfo != null && plugin.pluginInfo.isDefault()) {
|
||||
setDefault(name);
|
||||
}
|
||||
if (plugin.isLoaded()) registerMBean(plugin.get(), core, name);
|
||||
return old;
|
||||
}
|
||||
|
||||
void setDefault(String def) {
|
||||
if (!registry.containsKey(def)) return;
|
||||
if (this.def != null) log.warn("Multiple defaults for : " + meta.tag);
|
||||
this.def = def;
|
||||
}
|
||||
|
||||
public Map<String, PluginHolder<T>> getRegistry() {
|
||||
return immutableRegistry;
|
||||
}
|
||||
|
||||
public boolean contains(String name) {
|
||||
return registry.containsKey(name);
|
||||
}
|
||||
|
||||
String getDefault() {
|
||||
return def;
|
||||
}
|
||||
|
||||
T remove(String name) {
|
||||
PluginHolder<T> removed = registry.remove(name);
|
||||
return removed == null ? null : removed.get();
|
||||
}
|
||||
|
||||
void init(Map<String, T> defaults, SolrCore solrCore) {
|
||||
init(defaults, solrCore, solrCore.getSolrConfig().getPluginInfos(klass.getName()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the plugins after reading the meta data from {@link org.apache.solr.core.SolrConfig}.
|
||||
*
|
||||
* @param defaults These will be registered if not explicitly specified
|
||||
*/
|
||||
void init(Map<String, T> defaults, SolrCore solrCore, List<PluginInfo> infos) {
|
||||
core = solrCore;
|
||||
for (PluginInfo info : infos) {
|
||||
PluginHolder<T> o = createPlugin(info, solrCore);
|
||||
String name = info.name;
|
||||
if (meta.clazz.equals(SolrRequestHandler.class)) name = RequestHandlers.normalize(info.name);
|
||||
PluginHolder<T> old = put(name, o);
|
||||
if (old != null) log.warn("Multiple entries of {} with name {}", meta.tag, name);
|
||||
}
|
||||
for (Map.Entry<String, T> e : defaults.entrySet()) {
|
||||
if (!contains(e.getKey())) {
|
||||
put(e.getKey(), new PluginHolder<T>(null, e.getValue()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* To check if a plugin by a specified name is already loaded
|
||||
*/
|
||||
public boolean isLoaded(String name) {
|
||||
PluginHolder<T> result = registry.get(name);
|
||||
if (result == null) return false;
|
||||
return result.isLoaded();
|
||||
}
|
||||
|
||||
private static void registerMBean(Object inst, SolrCore core, String pluginKey) {
|
||||
if (core == null) return;
|
||||
if (inst instanceof SolrInfoMBean) {
|
||||
SolrInfoMBean mBean = (SolrInfoMBean) inst;
|
||||
String name = (inst instanceof SolrRequestHandler) ? pluginKey : mBean.getName();
|
||||
core.registerInfoBean(name, mBean);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Close this registry. This will in turn call a close on all the contained plugins
|
||||
*/
|
||||
@Override
|
||||
public void close() {
|
||||
for (Map.Entry<String, PluginHolder<T>> e : registry.entrySet()) {
|
||||
try {
|
||||
e.getValue().close();
|
||||
} catch (Exception exp) {
|
||||
log.error("Error closing plugin " + e.getKey() + " of type : " + meta.tag, exp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An indirect reference to a plugin. It just wraps a plugin instance.
|
||||
* subclasses may choose to lazily load the plugin
|
||||
*/
|
||||
public static class PluginHolder<T> implements AutoCloseable {
|
||||
protected T inst;
|
||||
protected final PluginInfo pluginInfo;
|
||||
|
||||
public PluginHolder(PluginInfo info) {
|
||||
this.pluginInfo = info;
|
||||
}
|
||||
|
||||
public PluginHolder(PluginInfo info, T inst) {
|
||||
this.inst = inst;
|
||||
this.pluginInfo = info;
|
||||
}
|
||||
|
||||
public T get() {
|
||||
return inst;
|
||||
}
|
||||
|
||||
public boolean isLoaded() {
|
||||
return inst != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws Exception {
|
||||
if (inst != null && inst instanceof AutoCloseable) ((AutoCloseable) inst).close();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A class that loads plugins Lazily. When the get() method is invoked
|
||||
* the Plugin is initialized and returned.
|
||||
*/
|
||||
public static class LazyPluginHolder<T> extends PluginHolder<T> {
|
||||
private final SolrConfig.SolrPluginInfo pluginMeta;
|
||||
protected SolrException solrException;
|
||||
private final SolrCore core;
|
||||
protected ResourceLoader resourceLoader;
|
||||
|
||||
|
||||
LazyPluginHolder(SolrConfig.SolrPluginInfo pluginMeta, PluginInfo pluginInfo, SolrCore core, ResourceLoader loader) {
|
||||
super(pluginInfo);
|
||||
this.pluginMeta = pluginMeta;
|
||||
this.core = core;
|
||||
this.resourceLoader = loader;
|
||||
}
|
||||
|
||||
@Override
|
||||
public T get() {
|
||||
if (inst != null) return inst;
|
||||
if (solrException != null) throw solrException;
|
||||
createInst();
|
||||
registerMBean(inst, core, pluginInfo.name);
|
||||
return inst;
|
||||
}
|
||||
|
||||
protected synchronized void createInst() {
|
||||
if (inst != null) return;
|
||||
log.info("Going to create a new {} with {} ", pluginMeta.tag, pluginInfo.toString());
|
||||
if (resourceLoader instanceof MemClassLoader) {
|
||||
MemClassLoader loader = (MemClassLoader) resourceLoader;
|
||||
loader.loadJars();
|
||||
}
|
||||
Class<T> clazz = (Class<T>) pluginMeta.clazz;
|
||||
inst = core.createInstance(pluginInfo.className, clazz, pluginMeta.tag, null, resourceLoader);
|
||||
initInstance(inst, pluginInfo, core);
|
||||
if (inst instanceof SolrCoreAware) {
|
||||
SolrResourceLoader.assertAwareCompatibility(SolrCoreAware.class, inst);
|
||||
((SolrCoreAware) inst).inform(core);
|
||||
}
|
||||
if (inst instanceof ResourceLoaderAware) {
|
||||
SolrResourceLoader.assertAwareCompatibility(ResourceLoaderAware.class, inst);
|
||||
try {
|
||||
((ResourceLoaderAware) inst).inform(core.getResourceLoader());
|
||||
} catch (IOException e) {
|
||||
throw new SolrException(SolrException.ErrorCode.SERVER_ERROR, "error initializing component", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* This represents a Runtime Jar. A jar requires two details , name and version
|
||||
*/
|
||||
public static class RuntimeLib implements PluginInfoInitialized, AutoCloseable {
|
||||
String name;
|
||||
String version;
|
||||
private JarRepository.JarContentRef jarContent;
|
||||
private final JarRepository jarRepository;
|
||||
|
||||
@Override
|
||||
public void init(PluginInfo info) {
|
||||
name = info.attributes.get("name");
|
||||
Object v = info.attributes.get("version");
|
||||
if (name == null || v == null) {
|
||||
throw new SolrException(SolrException.ErrorCode.SERVER_ERROR, "runtimeLib must have name and version");
|
||||
}
|
||||
version = String.valueOf(v);
|
||||
}
|
||||
|
||||
public RuntimeLib(SolrCore core) {
|
||||
jarRepository = core.getCoreDescriptor().getCoreContainer().getJarRepository();
|
||||
}
|
||||
|
||||
|
||||
void loadJar() {
|
||||
if (jarContent != null) return;
|
||||
synchronized (this) {
|
||||
if (jarContent != null) return;
|
||||
jarContent = jarRepository.getJarIncRef(name + "/" + version);
|
||||
}
|
||||
}
|
||||
|
||||
public ByteBuffer getFileContent(String entryName) throws IOException {
|
||||
if (jarContent == null)
|
||||
throw new SolrException(SolrException.ErrorCode.SERVER_ERROR, "jar not available: " + name + "/" + version);
|
||||
return jarContent.jar.getFileContent(entryName);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws Exception {
|
||||
if (jarContent != null) jarRepository.decrementJarRefCount(jarContent);
|
||||
}
|
||||
|
||||
public static List<RuntimeLib> getLibObjects(SolrCore core, List<PluginInfo> libs) {
|
||||
List<RuntimeLib> l = new ArrayList<>(libs.size());
|
||||
for (PluginInfo lib : libs) {
|
||||
RuntimeLib rtl = new RuntimeLib(core);
|
||||
rtl.init(lib);
|
||||
l.add(rtl);
|
||||
}
|
||||
return l;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -17,41 +17,14 @@
|
|||
|
||||
package org.apache.solr.core;
|
||||
|
||||
import java.io.Closeable;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.security.BasicPermission;
|
||||
import java.security.CodeSource;
|
||||
import java.security.Permissions;
|
||||
import java.security.ProtectionDomain;
|
||||
import java.security.SecureClassLoader;
|
||||
import java.security.cert.Certificate;
|
||||
import java.text.MessageFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.jar.JarFile;
|
||||
|
||||
import org.apache.solr.client.solrj.SolrRequest;
|
||||
import org.apache.solr.common.SolrException;
|
||||
import org.apache.solr.common.SolrException.ErrorCode;
|
||||
import org.apache.solr.common.util.NamedList;
|
||||
import org.apache.solr.common.util.SimpleOrderedMap;
|
||||
import org.apache.solr.common.util.StrUtils;
|
||||
import org.apache.solr.handler.RequestHandlerBase;
|
||||
import org.apache.solr.request.SolrQueryRequest;
|
||||
import org.apache.solr.request.SolrQueryRequestBase;
|
||||
import org.apache.solr.request.SolrRequestHandler;
|
||||
import org.apache.solr.response.SolrQueryResponse;
|
||||
import org.apache.solr.util.plugin.PluginInfoInitialized;
|
||||
import org.apache.solr.util.plugin.SolrCoreAware;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
|
@ -61,13 +34,8 @@ public final class RequestHandlers {
|
|||
public static Logger log = LoggerFactory.getLogger(RequestHandlers.class);
|
||||
|
||||
protected final SolrCore core;
|
||||
// Use a synchronized map - since the handlers can be changed at runtime,
|
||||
// the map implementation should be thread safe
|
||||
private final Map<String, SolrRequestHandler> handlers =
|
||||
new ConcurrentHashMap<>() ;
|
||||
private final Map<String, SolrRequestHandler> immutableHandlers = Collections.unmodifiableMap(handlers) ;
|
||||
|
||||
public static final boolean disableExternalLib = Boolean.parseBoolean(System.getProperty("disable.external.lib", "false"));
|
||||
final PluginRegistry<SolrRequestHandler> handlers;
|
||||
|
||||
/**
|
||||
* Trim the trailing '/' if it's there, and convert null to empty string.
|
||||
|
@ -89,6 +57,7 @@ public final class RequestHandlers {
|
|||
|
||||
public RequestHandlers(SolrCore core) {
|
||||
this.core = core;
|
||||
handlers = new PluginRegistry<>(SolrRequestHandler.class, core);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -98,17 +67,6 @@ public final class RequestHandlers {
|
|||
return handlers.get(normalize(handlerName));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return a Map of all registered handlers of the specified type.
|
||||
*/
|
||||
public <T extends SolrRequestHandler> Map<String,T> getAll(Class<T> clazz) {
|
||||
Map<String,T> result = new HashMap<>(7);
|
||||
for (Map.Entry<String,SolrRequestHandler> e : handlers.entrySet()) {
|
||||
if(clazz.isInstance(e.getValue())) result.put(e.getKey(), clazz.cast(e.getValue()));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handlers must be initialized before calling this function. As soon as this is
|
||||
* called, the handler can immediately accept requests.
|
||||
|
@ -118,22 +76,20 @@ public final class RequestHandlers {
|
|||
* @return the previous handler at the given path or null
|
||||
*/
|
||||
public SolrRequestHandler register( String handlerName, SolrRequestHandler handler ) {
|
||||
String norm = normalize( handlerName );
|
||||
String norm = normalize(handlerName);
|
||||
if (handler == null) {
|
||||
return handlers.remove(norm);
|
||||
}
|
||||
SolrRequestHandler old = handlers.put(norm, handler);
|
||||
if (0 != norm.length() && handler instanceof SolrInfoMBean) {
|
||||
core.getInfoRegistry().put(handlerName, handler);
|
||||
}
|
||||
return old;
|
||||
return handlers.put(norm, handler);
|
||||
// return register(handlerName, new PluginRegistry.PluginHolder<>(null, handler));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns an unmodifiable Map containing the registered handlers
|
||||
*/
|
||||
public Map<String,SolrRequestHandler> getRequestHandlers() {
|
||||
return immutableHandlers;
|
||||
public PluginRegistry<SolrRequestHandler> getRequestHandlers() {
|
||||
return handlers;
|
||||
}
|
||||
|
||||
|
||||
|
@ -157,66 +113,28 @@ public final class RequestHandlers {
|
|||
* Handlers will be registered and initialized in the order they appear in solrconfig.xml
|
||||
*/
|
||||
|
||||
void initHandlersFromConfig(SolrConfig config){
|
||||
List<PluginInfo> implicits = PluginsRegistry.getHandlers(core);
|
||||
void initHandlersFromConfig(SolrConfig config) {
|
||||
List<PluginInfo> implicits = ImplicitPlugins.getHandlers(core);
|
||||
// use link map so we iterate in the same order
|
||||
Map<PluginInfo,SolrRequestHandler> handlers = new LinkedHashMap<>();
|
||||
Map<String, PluginInfo> infoMap= new LinkedHashMap<>();
|
||||
//deduping implicit and explicit requesthandlers
|
||||
for (PluginInfo info : implicits) infoMap.put(info.name,info);
|
||||
for (PluginInfo info : config.getPluginInfos(SolrRequestHandler.class.getName())) infoMap.put(info.name, info);
|
||||
ArrayList<PluginInfo> infos = new ArrayList<>(infoMap.values());
|
||||
|
||||
List<PluginInfo> modifiedInfos = new ArrayList<>();
|
||||
for (PluginInfo info : infos) {
|
||||
try {
|
||||
SolrRequestHandler requestHandler;
|
||||
String startup = info.attributes.get("startup");
|
||||
String lib = info.attributes.get("lib");
|
||||
if (lib != null) {
|
||||
requestHandler = new DynamicLazyRequestHandlerWrapper(core);
|
||||
} else if (startup != null) {
|
||||
if ("lazy".equals(startup)) {
|
||||
log.info("adding lazy requestHandler: " + info.className);
|
||||
requestHandler = new LazyRequestHandlerWrapper(core);
|
||||
} else {
|
||||
throw new Exception("Unknown startup value: '" + startup + "' for: " + info.className);
|
||||
}
|
||||
} else {
|
||||
requestHandler = core.createRequestHandler(info.className);
|
||||
}
|
||||
if (requestHandler instanceof RequestHandlerBase) ((RequestHandlerBase) requestHandler).setPluginInfo(info);
|
||||
|
||||
handlers.put(info, requestHandler);
|
||||
SolrRequestHandler old = register(info.name, requestHandler);
|
||||
if (old != null) {
|
||||
log.warn("Multiple requestHandler registered to the same name: " + info.name + " ignoring: " + old.getClass().getName());
|
||||
}
|
||||
if (info.isDefault()) {
|
||||
old = register("", requestHandler);
|
||||
if (old != null) log.warn("Multiple default requestHandler registered" + " ignoring: " + old.getClass().getName());
|
||||
}
|
||||
log.info("created " + info.name + ": " + info.className);
|
||||
} catch (Exception ex) {
|
||||
throw new SolrException
|
||||
(ErrorCode.SERVER_ERROR, "RequestHandler init failure", ex);
|
||||
modifiedInfos.add(applyInitParams(config, info));
|
||||
}
|
||||
handlers.init(Collections.emptyMap(),core, modifiedInfos);
|
||||
handlers.alias(handlers.getDefault(), "");
|
||||
log.info("Registered paths: {}" , StrUtils.join(new ArrayList<>(handlers.keySet()) , ',' ));
|
||||
if(!handlers.alias( "/select","")){
|
||||
if(!handlers.alias( "standard","")){
|
||||
log.warn("no default request handler is registered (either '/select' or 'standard')");
|
||||
}
|
||||
}
|
||||
|
||||
// we've now registered all handlers, time to init them in the same order
|
||||
for (Map.Entry<PluginInfo,SolrRequestHandler> entry : handlers.entrySet()) {
|
||||
PluginInfo info = entry.getKey();
|
||||
SolrRequestHandler requestHandler = entry.getValue();
|
||||
info = applyInitParams(config, info);
|
||||
if (requestHandler instanceof PluginInfoInitialized) {
|
||||
((PluginInfoInitialized) requestHandler).init(info);
|
||||
} else{
|
||||
requestHandler.init(info.initArgs);
|
||||
}
|
||||
}
|
||||
|
||||
if(get("") == null) register("", get("/select"));//defacto default handler
|
||||
if(get("") == null) register("", get("standard"));//old default handler name; TODO remove?
|
||||
if(get("") == null)
|
||||
log.warn("no default request handler is registered (either '/select' or 'standard')");
|
||||
}
|
||||
|
||||
private PluginInfo applyInitParams(SolrConfig config, PluginInfo info) {
|
||||
|
@ -239,328 +157,8 @@ public final class RequestHandlers {
|
|||
return info;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* The <code>LazyRequestHandlerWrapper</code> wraps any {@link SolrRequestHandler}.
|
||||
* Rather then instantiate and initialize the handler on startup, this wrapper waits
|
||||
* until it is actually called. This should only be used for handlers that are
|
||||
* unlikely to be used in the normal lifecycle.
|
||||
*
|
||||
* You can enable lazy loading in solrconfig.xml using:
|
||||
*
|
||||
* <pre>
|
||||
* <requestHandler name="..." class="..." startup="lazy">
|
||||
* ...
|
||||
* </requestHandler>
|
||||
* </pre>
|
||||
*
|
||||
* This is a private class - if there is a real need for it to be public, it could
|
||||
* move
|
||||
*
|
||||
* @since solr 1.2
|
||||
*/
|
||||
public static class LazyRequestHandlerWrapper implements SolrRequestHandler, AutoCloseable, PluginInfoInitialized {
|
||||
private final SolrCore core;
|
||||
String _className;
|
||||
SolrRequestHandler _handler;
|
||||
PluginInfo _pluginInfo;
|
||||
|
||||
public LazyRequestHandlerWrapper(SolrCore core) {
|
||||
this.core = core;
|
||||
_handler = null; // don't initialize
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(NamedList args) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Wait for the first request before initializing the wrapped handler
|
||||
*/
|
||||
@Override
|
||||
public void handleRequest(SolrQueryRequest req, SolrQueryResponse rsp) {
|
||||
SolrRequestHandler handler = _handler;
|
||||
if (handler == null) {
|
||||
handler = getWrappedHandler();
|
||||
}
|
||||
handler.handleRequest(req, rsp);
|
||||
}
|
||||
|
||||
public synchronized SolrRequestHandler getWrappedHandler() {
|
||||
if (_handler == null) {
|
||||
try {
|
||||
SolrRequestHandler handler = createRequestHandler();
|
||||
if (handler instanceof PluginInfoInitialized) {
|
||||
((PluginInfoInitialized) handler).init(_pluginInfo);
|
||||
} else {
|
||||
handler.init(_pluginInfo.initArgs);
|
||||
}
|
||||
|
||||
if (handler instanceof PluginInfoInitialized) {
|
||||
((PluginInfoInitialized) handler).init(_pluginInfo);
|
||||
} else {
|
||||
handler.init(_pluginInfo.initArgs);
|
||||
}
|
||||
|
||||
|
||||
if (handler instanceof SolrCoreAware) {
|
||||
((SolrCoreAware) handler).inform(core);
|
||||
}
|
||||
if (handler instanceof RequestHandlerBase) ((RequestHandlerBase) handler).setPluginInfo(_pluginInfo);
|
||||
_handler = handler;
|
||||
} catch (Exception ex) {
|
||||
throw new SolrException(SolrException.ErrorCode.SERVER_ERROR, "lazy loading error", ex);
|
||||
}
|
||||
}
|
||||
return _handler;
|
||||
}
|
||||
|
||||
protected SolrRequestHandler createRequestHandler() {
|
||||
return core.createRequestHandler(_className);
|
||||
}
|
||||
|
||||
public String getHandlerClass() {
|
||||
return _className;
|
||||
}
|
||||
|
||||
//////////////////////// SolrInfoMBeans methods //////////////////////
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "Lazy[" + _className + "]";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
if (_handler == null) {
|
||||
return getName();
|
||||
}
|
||||
return _handler.getDescription();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getVersion() {
|
||||
if (_handler != null) {
|
||||
return _handler.getVersion();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSource() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public URL[] getDocs() {
|
||||
if (_handler == null) {
|
||||
return null;
|
||||
}
|
||||
return _handler.getDocs();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Category getCategory() {
|
||||
return Category.QUERYHANDLER;
|
||||
}
|
||||
|
||||
@Override
|
||||
public NamedList getStatistics() {
|
||||
if (_handler != null) {
|
||||
return _handler.getStatistics();
|
||||
}
|
||||
NamedList<String> lst = new SimpleOrderedMap<>();
|
||||
lst.add("note", "not initialized yet");
|
||||
return lst;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws Exception {
|
||||
if (_handler == null) return;
|
||||
if (_handler instanceof AutoCloseable && !(_handler instanceof DynamicLazyRequestHandlerWrapper)) {
|
||||
((AutoCloseable) _handler).close();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(PluginInfo info) {
|
||||
_pluginInfo = info;
|
||||
_className = info.className;
|
||||
}
|
||||
}
|
||||
|
||||
public static class DynamicLazyRequestHandlerWrapper extends LazyRequestHandlerWrapper {
|
||||
private String lib;
|
||||
private String key;
|
||||
private String version;
|
||||
private CoreContainer coreContainer;
|
||||
private SolrResourceLoader solrResourceLoader;
|
||||
private MemClassLoader classLoader;
|
||||
private boolean _closed = false;
|
||||
boolean unrecoverable = false;
|
||||
String errMsg = null;
|
||||
private Exception exception;
|
||||
|
||||
|
||||
public DynamicLazyRequestHandlerWrapper(SolrCore core) {
|
||||
super(core);
|
||||
this.coreContainer = core.getCoreDescriptor().getCoreContainer();
|
||||
this.solrResourceLoader = core.getResourceLoader();
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(PluginInfo info) {
|
||||
super.init(info);
|
||||
this.lib = _pluginInfo.attributes.get("lib");
|
||||
|
||||
if (disableExternalLib) {
|
||||
errMsg = "ERROR external library loading is disabled";
|
||||
unrecoverable = true;
|
||||
_handler = this;
|
||||
log.error(errMsg);
|
||||
return;
|
||||
}
|
||||
|
||||
if (_pluginInfo.attributes.get("version") == null) {
|
||||
errMsg = "ERROR 'lib' attribute must be accompanied with version also";
|
||||
unrecoverable = true;
|
||||
_handler = this;
|
||||
log.error(errMsg);
|
||||
return;
|
||||
}
|
||||
version = String.valueOf(_pluginInfo.attributes.get("version"));
|
||||
classLoader = new MemClassLoader(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleRequest(SolrQueryRequest req, SolrQueryResponse rsp) {
|
||||
if (unrecoverable) {
|
||||
rsp.add("error", errMsg);
|
||||
if (exception != null) rsp.setException(exception);
|
||||
return;
|
||||
}
|
||||
try {
|
||||
classLoader.checkJarAvailable();
|
||||
} catch (SolrException e) {
|
||||
rsp.add("error", "Jar could not be loaded");
|
||||
rsp.setException(e);
|
||||
return;
|
||||
} catch (IOException e) {
|
||||
unrecoverable = true;
|
||||
errMsg = "Could not load jar";
|
||||
exception = e;
|
||||
handleRequest(req, rsp);
|
||||
return;
|
||||
}
|
||||
|
||||
super.handleRequest(req, rsp);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected SolrRequestHandler createRequestHandler() {
|
||||
try {
|
||||
Class clazz = classLoader.findClass(_className);
|
||||
Constructor<?>[] cons = clazz.getConstructors();
|
||||
for (Constructor<?> con : cons) {
|
||||
Class<?>[] types = con.getParameterTypes();
|
||||
if (types.length == 1 && types[0] == SolrCore.class) {
|
||||
return SolrRequestHandler.class.cast(con.newInstance(this));
|
||||
}
|
||||
}
|
||||
return (SolrRequestHandler) clazz.newInstance();
|
||||
} catch (Exception e) {
|
||||
unrecoverable = true;
|
||||
errMsg = MessageFormat.format("class {0} could not be loaded ", _className);
|
||||
this.exception = e;
|
||||
return this;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws Exception {
|
||||
super.close();
|
||||
if (_closed) return;
|
||||
if (classLoader != null) classLoader.releaseJar();
|
||||
_closed = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static class MemClassLoader extends ClassLoader {
|
||||
private JarRepository.JarContentRef jarContent;
|
||||
private final DynamicLazyRequestHandlerWrapper handlerWrapper;
|
||||
|
||||
public MemClassLoader(DynamicLazyRequestHandlerWrapper handlerWrapper) {
|
||||
super(handlerWrapper.solrResourceLoader.classLoader);
|
||||
this.handlerWrapper = handlerWrapper;
|
||||
|
||||
}
|
||||
|
||||
boolean checkJarAvailable() throws IOException {
|
||||
if (jarContent != null) return true;
|
||||
|
||||
try {
|
||||
synchronized (this) {
|
||||
jarContent = handlerWrapper.coreContainer.getJarRepository().getJarIncRef(handlerWrapper.lib + "/" + handlerWrapper.version);
|
||||
return true;
|
||||
}
|
||||
} catch (SolrException se) {
|
||||
throw se;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Class<?> findClass(String name) throws ClassNotFoundException {
|
||||
try {
|
||||
return super.findClass(name);
|
||||
} catch (ClassNotFoundException e) {
|
||||
String path = name.replace('.', '/').concat(".class");
|
||||
ByteBuffer buf = null;
|
||||
try {
|
||||
if (jarContent == null) checkJarAvailable();
|
||||
buf = jarContent.jar.getFileContent(path);
|
||||
if (buf == null) throw new ClassNotFoundException("class not found in loaded jar" + name);
|
||||
} catch (IOException e1) {
|
||||
throw new ClassNotFoundException("class not found " + name, e1);
|
||||
|
||||
}
|
||||
|
||||
ProtectionDomain defaultDomain = null;
|
||||
|
||||
//using the default protection domain, with no permissions
|
||||
try {
|
||||
defaultDomain = new ProtectionDomain(new CodeSource(new URL("http://localhost/.system/blob/" + handlerWrapper.lib), (Certificate[]) null),
|
||||
null);
|
||||
} catch (MalformedURLException e1) {
|
||||
//should not happen
|
||||
}
|
||||
return defineClass(name, buf.array(), buf.arrayOffset(), buf.limit(), defaultDomain);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void releaseJar() {
|
||||
handlerWrapper.coreContainer.getJarRepository().decrementJarRefCount(jarContent);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void close() {
|
||||
for (Map.Entry<String, SolrRequestHandler> e : handlers.entrySet()) {
|
||||
if (e.getValue() instanceof AutoCloseable) {
|
||||
try {
|
||||
((AutoCloseable) e.getValue()).close();
|
||||
} catch (Exception exp) {
|
||||
log.error("Error closing requestHandler " + e.getKey(), exp);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
handlers.close();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -26,6 +26,7 @@ import org.apache.solr.cloud.ZkSolrResourceLoader;
|
|||
import org.apache.solr.common.SolrException;
|
||||
import org.apache.solr.common.SolrException.ErrorCode;
|
||||
import org.apache.solr.common.cloud.ZkNodeProps;
|
||||
import org.apache.solr.common.util.NamedList;
|
||||
import org.apache.solr.handler.component.SearchComponent;
|
||||
import org.apache.solr.request.SolrRequestHandler;
|
||||
import org.apache.solr.response.QueryResponseWriter;
|
||||
|
@ -45,8 +46,6 @@ import org.apache.solr.update.processor.UpdateRequestProcessorChain;
|
|||
import org.apache.solr.util.DOMUtil;
|
||||
import org.apache.solr.util.FileUtils;
|
||||
import org.apache.solr.util.RegexFileFilter;
|
||||
import org.apache.zookeeper.KeeperException;
|
||||
import org.apache.zookeeper.data.Stat;
|
||||
import org.noggit.JSONParser;
|
||||
import org.noggit.ObjectBuilder;
|
||||
import org.slf4j.Logger;
|
||||
|
@ -77,10 +76,14 @@ import java.util.Set;
|
|||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import static java.util.Collections.unmodifiableMap;
|
||||
import static org.apache.solr.common.params.CoreAdminParams.NAME;
|
||||
import static org.apache.solr.core.SolrConfig.PluginOpts.LAZY;
|
||||
import static org.apache.solr.core.SolrConfig.PluginOpts.MULTI_OK;
|
||||
import static org.apache.solr.core.SolrConfig.PluginOpts.NOOP;
|
||||
import static org.apache.solr.core.SolrConfig.PluginOpts.REQUIRE_CLASS;
|
||||
import static org.apache.solr.core.SolrConfig.PluginOpts.REQUIRE_NAME;
|
||||
import static org.apache.solr.schema.FieldType.CLASS_NAME;
|
||||
|
||||
|
||||
/**
|
||||
|
@ -99,6 +102,7 @@ public class SolrConfig extends Config implements MapSerializable{
|
|||
MULTI_OK,
|
||||
REQUIRE_NAME,
|
||||
REQUIRE_CLASS,
|
||||
LAZY,
|
||||
// EnumSet.of and/or EnumSet.copyOf(Collection) are anoying
|
||||
// because of type determination
|
||||
NOOP
|
||||
|
@ -296,9 +300,9 @@ public class SolrConfig extends Config implements MapSerializable{
|
|||
}
|
||||
|
||||
public static final List<SolrPluginInfo> plugins = ImmutableList.<SolrPluginInfo>builder()
|
||||
.add(new SolrPluginInfo(SolrRequestHandler.class, SolrRequestHandler.TYPE, REQUIRE_NAME, REQUIRE_CLASS, MULTI_OK))
|
||||
.add(new SolrPluginInfo(SolrRequestHandler.class, SolrRequestHandler.TYPE, REQUIRE_NAME, REQUIRE_CLASS, MULTI_OK, LAZY))
|
||||
.add(new SolrPluginInfo(QParserPlugin.class, "queryParser", REQUIRE_NAME, REQUIRE_CLASS, MULTI_OK))
|
||||
.add(new SolrPluginInfo(QueryResponseWriter.class, "queryResponseWriter", REQUIRE_NAME, REQUIRE_CLASS, MULTI_OK))
|
||||
.add(new SolrPluginInfo(QueryResponseWriter.class, "queryResponseWriter", REQUIRE_NAME, REQUIRE_CLASS, MULTI_OK, LAZY))
|
||||
.add(new SolrPluginInfo(ValueSourceParser.class, "valueSourceParser", REQUIRE_NAME, REQUIRE_CLASS, MULTI_OK))
|
||||
.add(new SolrPluginInfo(TransformerFactory.class, "transformer", REQUIRE_NAME, REQUIRE_CLASS, MULTI_OK))
|
||||
.add(new SolrPluginInfo(SearchComponent.class, "searchComponent", REQUIRE_NAME, REQUIRE_CLASS, MULTI_OK))
|
||||
|
@ -307,6 +311,7 @@ public class SolrConfig extends Config implements MapSerializable{
|
|||
// and even then -- only if there is a single SpellCheckComponent
|
||||
// because of queryConverter.setIndexAnalyzer
|
||||
.add(new SolrPluginInfo(QueryConverter.class, "queryConverter", REQUIRE_NAME, REQUIRE_CLASS))
|
||||
.add(new SolrPluginInfo(PluginRegistry.RuntimeLib.class, "runtimeLib", REQUIRE_NAME, MULTI_OK))
|
||||
// this is hackish, since it picks up all SolrEventListeners,
|
||||
// regardless of when/how/why they are used (or even if they are
|
||||
// declared outside of the appropriate context) but there's no nice
|
||||
|
@ -323,10 +328,11 @@ public class SolrConfig extends Config implements MapSerializable{
|
|||
.add(new SolrPluginInfo(InitParams.class, InitParams.TYPE, MULTI_OK))
|
||||
.add(new SolrPluginInfo(StatsCache.class, "statsCache", REQUIRE_CLASS))
|
||||
.build();
|
||||
private static final Map<String, SolrPluginInfo> clsVsInfo = new HashMap<>();
|
||||
|
||||
public static final Map<String, SolrPluginInfo> classVsSolrPluginInfo;
|
||||
static {
|
||||
for (SolrPluginInfo plugin : plugins) clsVsInfo.put(plugin.clazz.getName(), plugin);
|
||||
Map<String, SolrPluginInfo> map = new HashMap<>();
|
||||
for (SolrPluginInfo plugin : plugins) map.put(plugin.clazz.getName(), plugin);
|
||||
classVsSolrPluginInfo = Collections.unmodifiableMap(map);
|
||||
}
|
||||
|
||||
public static class SolrPluginInfo{
|
||||
|
@ -634,7 +640,7 @@ public class SolrConfig extends Config implements MapSerializable{
|
|||
*/
|
||||
public List<PluginInfo> getPluginInfos(String type) {
|
||||
List<PluginInfo> result = pluginStore.get(type);
|
||||
SolrPluginInfo info = clsVsInfo.get(type);
|
||||
SolrPluginInfo info = classVsSolrPluginInfo.get(type);
|
||||
if (info != null && info.options.contains(REQUIRE_NAME)) {
|
||||
Map<String, Map> infos = overlay.getNamedPlugins(info.tag);
|
||||
if (!infos.isEmpty()) {
|
||||
|
@ -664,14 +670,14 @@ public class SolrConfig extends Config implements MapSerializable{
|
|||
private void initLibs() {
|
||||
NodeList nodes = (NodeList) evaluate("lib", XPathConstants.NODESET);
|
||||
if (nodes == null || nodes.getLength() == 0) return;
|
||||
|
||||
|
||||
log.info("Adding specified lib dirs to ClassLoader");
|
||||
SolrResourceLoader loader = getResourceLoader();
|
||||
|
||||
|
||||
try {
|
||||
for (int i = 0; i < nodes.getLength(); i++) {
|
||||
Node node = nodes.item(i);
|
||||
|
||||
|
||||
String baseDir = DOMUtil.getAttr(node, "dir");
|
||||
String path = DOMUtil.getAttr(node, "path");
|
||||
if (null != baseDir) {
|
||||
|
@ -696,7 +702,7 @@ public class SolrConfig extends Config implements MapSerializable{
|
|||
loader.reloadLuceneSPI();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public int getMultipartUploadLimitKB() {
|
||||
return multipartUploadLimitKB;
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -22,8 +22,7 @@ import org.apache.solr.common.params.SolrParams;
|
|||
import org.apache.solr.common.util.NamedList;
|
||||
import org.apache.solr.common.util.SimpleOrderedMap;
|
||||
import org.apache.solr.core.PluginInfo;
|
||||
import org.apache.solr.core.RequestHandlers;
|
||||
import org.apache.solr.core.RequestParams;
|
||||
import org.apache.solr.core.PluginRegistry;
|
||||
import org.apache.solr.core.SolrCore;
|
||||
import org.apache.solr.core.SolrInfoMBean;
|
||||
import org.apache.solr.request.SolrQueryRequest;
|
||||
|
@ -215,7 +214,7 @@ public abstract class RequestHandlerBase implements SolrRequestHandler, SolrInfo
|
|||
*
|
||||
* This function is thread safe.
|
||||
*/
|
||||
public static SolrRequestHandler getRequestHandler(String handlerName, Map<String, SolrRequestHandler> reqHandlers) {
|
||||
public static SolrRequestHandler getRequestHandler(String handlerName, PluginRegistry<SolrRequestHandler> reqHandlers) {
|
||||
if(handlerName == null) return null;
|
||||
SolrRequestHandler handler = reqHandlers.get(handlerName);
|
||||
int idx = 0;
|
||||
|
@ -226,9 +225,6 @@ public abstract class RequestHandlerBase implements SolrRequestHandler, SolrInfo
|
|||
String firstPart = handlerName.substring(0, idx);
|
||||
handler = reqHandlers.get(firstPart);
|
||||
if (handler == null) continue;
|
||||
if(handler instanceof RequestHandlers.LazyRequestHandlerWrapper) {
|
||||
handler = ((RequestHandlers.LazyRequestHandlerWrapper)handler).getWrappedHandler();
|
||||
}
|
||||
if (handler instanceof NestedRequestHandler) {
|
||||
return ((NestedRequestHandler) handler).getSubHandler(handlerName.substring(idx));
|
||||
}
|
||||
|
|
|
@ -43,19 +43,14 @@ import org.apache.solr.common.util.ContentStream;
|
|||
import org.apache.solr.common.util.StrUtils;
|
||||
import org.apache.solr.core.ConfigOverlay;
|
||||
import org.apache.solr.core.PluginInfo;
|
||||
import org.apache.solr.core.PluginsRegistry;
|
||||
import org.apache.solr.core.ImplicitPlugins;
|
||||
import org.apache.solr.core.RequestParams;
|
||||
import org.apache.solr.core.SolrConfig;
|
||||
import org.apache.solr.core.SolrCore;
|
||||
import org.apache.solr.core.SolrResourceLoader;
|
||||
import org.apache.solr.handler.component.SearchComponent;
|
||||
import org.apache.solr.request.SolrQueryRequest;
|
||||
import org.apache.solr.request.SolrRequestHandler;
|
||||
import org.apache.solr.response.SolrQueryResponse;
|
||||
import org.apache.solr.response.transform.TransformerFactory;
|
||||
import org.apache.solr.schema.SchemaManager;
|
||||
import org.apache.solr.search.QParserPlugin;
|
||||
import org.apache.solr.search.ValueSourceParser;
|
||||
import org.apache.solr.util.CommandOperation;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
@ -64,6 +59,7 @@ import static java.text.MessageFormat.format;
|
|||
import static java.util.Collections.singletonList;
|
||||
import static org.apache.solr.common.params.CoreAdminParams.NAME;
|
||||
import static org.apache.solr.core.ConfigOverlay.NOT_EDITABLE;
|
||||
import static org.apache.solr.core.SolrConfig.PluginOpts.REQUIRE_CLASS;
|
||||
import static org.apache.solr.core.SolrConfig.PluginOpts.REQUIRE_NAME;
|
||||
import static org.apache.solr.schema.FieldType.CLASS_NAME;
|
||||
|
||||
|
@ -152,7 +148,7 @@ public class SolrConfigHandler extends RequestHandlerBase {
|
|||
Map<String, Object> map = req.getCore().getSolrConfig().toMap();
|
||||
Map reqHandlers = (Map) map.get(SolrRequestHandler.TYPE);
|
||||
if (reqHandlers == null) map.put(SolrRequestHandler.TYPE, reqHandlers = new LinkedHashMap<>());
|
||||
List<PluginInfo> plugins = PluginsRegistry.getHandlers(req.getCore());
|
||||
List<PluginInfo> plugins = ImplicitPlugins.getHandlers(req.getCore());
|
||||
for (PluginInfo plugin : plugins) {
|
||||
if (SolrRequestHandler.TYPE.equals(plugin.type)) {
|
||||
if (!reqHandlers.containsKey(plugin.name)) {
|
||||
|
@ -316,7 +312,7 @@ public class SolrConfigHandler extends RequestHandlerBase {
|
|||
if ("delete".equals(prefix)) {
|
||||
overlay = deleteNamedComponent(op, overlay, info.tag);
|
||||
} else {
|
||||
overlay = updateNamedPlugin(info, op, overlay, prefix.equals("create"));
|
||||
overlay = updateNamedPlugin(info, op, overlay, prefix.equals("create") || prefix.equals("add"));
|
||||
}
|
||||
} else {
|
||||
op.addError(MessageFormat.format("Unknown operation ''{0}'' ", op.name));
|
||||
|
@ -359,7 +355,7 @@ public class SolrConfigHandler extends RequestHandlerBase {
|
|||
|
||||
private ConfigOverlay updateNamedPlugin(SolrConfig.SolrPluginInfo info, CommandOperation op, ConfigOverlay overlay, boolean isCeate) {
|
||||
String name = op.getStr(NAME);
|
||||
String clz = op.getStr(CLASS_NAME);
|
||||
String clz = info.options.contains(REQUIRE_CLASS) ? op.getStr(CLASS_NAME) : op.getStr(CLASS_NAME, null);
|
||||
op.getMap(PluginInfo.DEFAULTS, null);
|
||||
op.getMap(PluginInfo.INVARIANTS, null);
|
||||
op.getMap(PluginInfo.APPENDS, null);
|
||||
|
@ -383,10 +379,11 @@ public class SolrConfigHandler extends RequestHandlerBase {
|
|||
}
|
||||
|
||||
private boolean verifyClass(CommandOperation op, String clz, Class expected) {
|
||||
if (op.getStr("lib", null) == null) {
|
||||
if (clz == null) return true;
|
||||
if ( !"true".equals(String.valueOf(op.getStr("runtimeLib", null)))) {
|
||||
//this is not dynamically loaded so we can verify the class right away
|
||||
try {
|
||||
SolrCore.createInstance(clz, expected, expected.getSimpleName(), req.getCore());
|
||||
req.getCore().createInitInstance(new PluginInfo(SolrRequestHandler.TYPE, op.getDataMap()), expected, clz, "");
|
||||
} catch (Exception e) {
|
||||
op.addError(e.getMessage());
|
||||
return false;
|
||||
|
@ -522,6 +519,6 @@ public class SolrConfigHandler extends RequestHandlerBase {
|
|||
public static final String SET = "set";
|
||||
public static final String UPDATE = "update";
|
||||
public static final String CREATE = "create";
|
||||
private static Set<String> cmdPrefixes = ImmutableSet.of(CREATE, UPDATE, "delete");
|
||||
private static Set<String> cmdPrefixes = ImmutableSet.of(CREATE, UPDATE, "delete", "add");
|
||||
|
||||
}
|
||||
|
|
|
@ -23,6 +23,7 @@ import java.util.Map;
|
|||
import org.apache.solr.common.SolrException;
|
||||
import org.apache.solr.common.util.NamedList;
|
||||
import org.apache.solr.core.SolrCore;
|
||||
import org.apache.solr.handler.RequestHandlerBase;
|
||||
import org.apache.solr.request.SolrQueryRequest;
|
||||
import org.apache.solr.request.SolrRequestHandler;
|
||||
import org.apache.solr.response.SolrQueryResponse;
|
||||
|
@ -38,7 +39,7 @@ import org.slf4j.LoggerFactory;
|
|||
* the plugins registered by this class are iplicitly registered by the system
|
||||
*/
|
||||
@Deprecated
|
||||
public class AdminHandlers implements SolrCoreAware, SolrRequestHandler
|
||||
public class AdminHandlers extends RequestHandlerBase implements SolrCoreAware
|
||||
{
|
||||
public static Logger log = LoggerFactory.getLogger(AdminHandlers.class);
|
||||
NamedList initArgs = null;
|
||||
|
@ -61,17 +62,12 @@ public class AdminHandlers implements SolrCoreAware, SolrRequestHandler
|
|||
public void init(NamedList args) {
|
||||
this.initArgs = args;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void inform(SolrCore core)
|
||||
{
|
||||
String path = null;
|
||||
for( Map.Entry<String, SolrRequestHandler> entry : core.getRequestHandlers().entrySet() ) {
|
||||
if( entry.getValue() == this ) {
|
||||
path = entry.getKey();
|
||||
break;
|
||||
}
|
||||
}
|
||||
path = getPluginInfo().name;
|
||||
if( path == null ) {
|
||||
throw new SolrException( SolrException.ErrorCode.SERVER_ERROR,
|
||||
"The AdminHandler is not registered with the current core." );
|
||||
|
@ -109,9 +105,9 @@ public class AdminHandlers implements SolrCoreAware, SolrRequestHandler
|
|||
log.warn("<requestHandler name=\"/admin/\" \n class=\"solr.admin.AdminHandlers\" /> is deprecated . It is not required anymore");
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public void handleRequest(SolrQueryRequest req, SolrQueryResponse rsp) {
|
||||
public void handleRequestBody(SolrQueryRequest req, SolrQueryResponse rsp) {
|
||||
throw new SolrException( SolrException.ErrorCode.SERVER_ERROR,
|
||||
"The AdminHandler should never be called directly" );
|
||||
}
|
||||
|
|
|
@ -19,6 +19,9 @@ package org.apache.solr.handler.component;
|
|||
|
||||
import java.io.IOException;
|
||||
import java.net.URL;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.solr.common.util.NamedList;
|
||||
import org.apache.solr.core.SolrInfoMBean;
|
||||
|
@ -122,4 +125,21 @@ public abstract class SearchComponent implements SolrInfoMBean, NamedListInitial
|
|||
public NamedList getStatistics() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static final Map<String, Class<? extends SearchComponent>> standard_components;
|
||||
;
|
||||
|
||||
static {
|
||||
HashMap<String, Class<? extends SearchComponent>> map = new HashMap<>();
|
||||
map.put(HighlightComponent.COMPONENT_NAME, HighlightComponent.class);
|
||||
map.put(QueryComponent.COMPONENT_NAME, QueryComponent.class);
|
||||
map.put(FacetComponent.COMPONENT_NAME, FacetComponent.class);
|
||||
map.put(MoreLikeThisComponent.COMPONENT_NAME, MoreLikeThisComponent.class);
|
||||
map.put(StatsComponent.COMPONENT_NAME, StatsComponent.class);
|
||||
map.put(DebugComponent.COMPONENT_NAME, DebugComponent.class);
|
||||
map.put(RealTimeGetComponent.COMPONENT_NAME, RealTimeGetComponent.class);
|
||||
map.put(ExpandComponent.COMPONENT_NAME, ExpandComponent.class);
|
||||
standard_components = Collections.unmodifiableMap(map);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -26,6 +26,9 @@ import org.apache.solr.search.mlt.MLTQParserPlugin;
|
|||
import org.apache.solr.util.plugin.NamedListInitializedPlugin;
|
||||
|
||||
import java.net.URL;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public abstract class QParserPlugin implements NamedListInitializedPlugin, SolrInfoMBean {
|
||||
/** internal use - name of the default parser */
|
||||
|
@ -38,35 +41,39 @@ public abstract class QParserPlugin implements NamedListInitializedPlugin, SolrI
|
|||
* This result to NPE during initialization.
|
||||
* For every plugin, listed here, NAME field has to be final and static.
|
||||
*/
|
||||
public static final Object[] standardPlugins = {
|
||||
LuceneQParserPlugin.NAME, LuceneQParserPlugin.class,
|
||||
OldLuceneQParserPlugin.NAME, OldLuceneQParserPlugin.class,
|
||||
FunctionQParserPlugin.NAME, FunctionQParserPlugin.class,
|
||||
PrefixQParserPlugin.NAME, PrefixQParserPlugin.class,
|
||||
BoostQParserPlugin.NAME, BoostQParserPlugin.class,
|
||||
DisMaxQParserPlugin.NAME, DisMaxQParserPlugin.class,
|
||||
ExtendedDismaxQParserPlugin.NAME, ExtendedDismaxQParserPlugin.class,
|
||||
FieldQParserPlugin.NAME, FieldQParserPlugin.class,
|
||||
RawQParserPlugin.NAME, RawQParserPlugin.class,
|
||||
TermQParserPlugin.NAME, TermQParserPlugin.class,
|
||||
TermsQParserPlugin.NAME, TermsQParserPlugin.class,
|
||||
NestedQParserPlugin.NAME, NestedQParserPlugin.class,
|
||||
FunctionRangeQParserPlugin.NAME, FunctionRangeQParserPlugin.class,
|
||||
SpatialFilterQParserPlugin.NAME, SpatialFilterQParserPlugin.class,
|
||||
SpatialBoxQParserPlugin.NAME, SpatialBoxQParserPlugin.class,
|
||||
JoinQParserPlugin.NAME, JoinQParserPlugin.class,
|
||||
SurroundQParserPlugin.NAME, SurroundQParserPlugin.class,
|
||||
SwitchQParserPlugin.NAME, SwitchQParserPlugin.class,
|
||||
MaxScoreQParserPlugin.NAME, MaxScoreQParserPlugin.class,
|
||||
BlockJoinParentQParserPlugin.NAME, BlockJoinParentQParserPlugin.class,
|
||||
BlockJoinChildQParserPlugin.NAME, BlockJoinChildQParserPlugin.class,
|
||||
CollapsingQParserPlugin.NAME, CollapsingQParserPlugin.class,
|
||||
SimpleQParserPlugin.NAME, SimpleQParserPlugin.class,
|
||||
ComplexPhraseQParserPlugin.NAME, ComplexPhraseQParserPlugin.class,
|
||||
ReRankQParserPlugin.NAME, ReRankQParserPlugin.class,
|
||||
ExportQParserPlugin.NAME, ExportQParserPlugin.class,
|
||||
MLTQParserPlugin.NAME, MLTQParserPlugin.class
|
||||
};
|
||||
public static final Map<String, Class<? extends QParserPlugin>> standardPlugins;
|
||||
|
||||
static {
|
||||
HashMap<String, Class<? extends QParserPlugin>> map = new HashMap<>();
|
||||
map.put(LuceneQParserPlugin.NAME, LuceneQParserPlugin.class);
|
||||
map.put(OldLuceneQParserPlugin.NAME, OldLuceneQParserPlugin.class);
|
||||
map.put(FunctionQParserPlugin.NAME, FunctionQParserPlugin.class);
|
||||
map.put(PrefixQParserPlugin.NAME, PrefixQParserPlugin.class);
|
||||
map.put(BoostQParserPlugin.NAME, BoostQParserPlugin.class);
|
||||
map.put(DisMaxQParserPlugin.NAME, DisMaxQParserPlugin.class);
|
||||
map.put(ExtendedDismaxQParserPlugin.NAME, ExtendedDismaxQParserPlugin.class);
|
||||
map.put(FieldQParserPlugin.NAME, FieldQParserPlugin.class);
|
||||
map.put(RawQParserPlugin.NAME, RawQParserPlugin.class);
|
||||
map.put(TermQParserPlugin.NAME, TermQParserPlugin.class);
|
||||
map.put(TermsQParserPlugin.NAME, TermsQParserPlugin.class);
|
||||
map.put(NestedQParserPlugin.NAME, NestedQParserPlugin.class);
|
||||
map.put(FunctionRangeQParserPlugin.NAME, FunctionRangeQParserPlugin.class);
|
||||
map.put(SpatialFilterQParserPlugin.NAME, SpatialFilterQParserPlugin.class);
|
||||
map.put(SpatialBoxQParserPlugin.NAME, SpatialBoxQParserPlugin.class);
|
||||
map.put(JoinQParserPlugin.NAME, JoinQParserPlugin.class);
|
||||
map.put(SurroundQParserPlugin.NAME, SurroundQParserPlugin.class);
|
||||
map.put(SwitchQParserPlugin.NAME, SwitchQParserPlugin.class);
|
||||
map.put(MaxScoreQParserPlugin.NAME, MaxScoreQParserPlugin.class);
|
||||
map.put(BlockJoinParentQParserPlugin.NAME, BlockJoinParentQParserPlugin.class);
|
||||
map.put(BlockJoinChildQParserPlugin.NAME, BlockJoinChildQParserPlugin.class);
|
||||
map.put(CollapsingQParserPlugin.NAME, CollapsingQParserPlugin.class);
|
||||
map.put(SimpleQParserPlugin.NAME, SimpleQParserPlugin.class);
|
||||
map.put(ComplexPhraseQParserPlugin.NAME, ComplexPhraseQParserPlugin.class);
|
||||
map.put(ReRankQParserPlugin.NAME, ReRankQParserPlugin.class);
|
||||
map.put(ExportQParserPlugin.NAME, ExportQParserPlugin.class);
|
||||
map.put(MLTQParserPlugin.NAME, MLTQParserPlugin.class);
|
||||
standardPlugins = Collections.unmodifiableMap(map);
|
||||
}
|
||||
|
||||
/** return a {@link QParser} */
|
||||
public abstract QParser createParser(String qstr, SolrParams localParams, SolrParams params, SolrQueryRequest req);
|
||||
|
|
|
@ -52,8 +52,8 @@ public class CommandOperation {
|
|||
Object obj = getRootPrimitive();
|
||||
return obj == def ? null : String.valueOf(obj);
|
||||
}
|
||||
String s = (String) getMapVal(key);
|
||||
return s == null ? def : s;
|
||||
Object o = getMapVal(key);
|
||||
return o == null ? def : String.valueOf(o);
|
||||
}
|
||||
|
||||
public Map<String, Object> getDataMap() {
|
||||
|
|
|
@ -19,16 +19,13 @@ package org.apache.solr;
|
|||
|
||||
import java.io.IOException;
|
||||
import java.io.Writer;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.solr.common.params.CommonParams;
|
||||
import org.apache.solr.common.util.NamedList;
|
||||
import org.apache.solr.core.PluginInfo;
|
||||
import org.apache.solr.core.SolrCore;
|
||||
import org.apache.solr.core.PluginRegistry;
|
||||
import org.apache.solr.request.SolrQueryRequest;
|
||||
import org.apache.solr.response.QueryResponseWriter;
|
||||
import org.apache.solr.response.SolrQueryResponse;
|
||||
import org.apache.solr.response.XMLResponseWriter;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
|
@ -94,11 +91,12 @@ public class OutputWriterTest extends SolrTestCaseJ4 {
|
|||
}
|
||||
|
||||
public void testLazy() {
|
||||
QueryResponseWriter qrw = h.getCore().getQueryResponseWriter("useless");
|
||||
assertTrue("Should be a lazy class", qrw instanceof SolrCore.LazyQueryResponseWriterWrapper);
|
||||
PluginRegistry.PluginHolder<QueryResponseWriter> qrw = h.getCore().getResponseWriters().getRegistry().get("useless");
|
||||
assertTrue("Should be a lazy class", qrw instanceof PluginRegistry.LazyPluginHolder);
|
||||
|
||||
qrw = h.getCore().getQueryResponseWriter("xml");
|
||||
assertTrue("Should not be a lazy class", qrw instanceof XMLResponseWriter);
|
||||
qrw = h.getCore().getResponseWriters().getRegistry().get("xml");
|
||||
assertTrue("Should not be a lazy class", qrw.isLoaded());
|
||||
assertTrue("Should not be a lazy class", qrw.getClass() == PluginRegistry.PluginHolder.class);
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -23,11 +23,41 @@ import java.io.IOException;
|
|||
import org.apache.solr.handler.DumpRequestHandler;
|
||||
import org.apache.solr.request.SolrQueryRequest;
|
||||
import org.apache.solr.response.SolrQueryResponse;
|
||||
import org.apache.solr.util.plugin.SolrCoreAware;
|
||||
|
||||
public class BlobStoreTestRequestHandler extends DumpRequestHandler implements Runnable, SolrCoreAware{
|
||||
|
||||
private SolrCore core;
|
||||
|
||||
private long version = 1;
|
||||
private String watchedVal = null;
|
||||
|
||||
public class BlobStoreTestRequestHandler extends DumpRequestHandler{
|
||||
@Override
|
||||
public void handleRequestBody(SolrQueryRequest req, SolrQueryResponse rsp) throws IOException {
|
||||
super.handleRequestBody(req, rsp);
|
||||
rsp.add("class", this.getClass().getName());
|
||||
rsp.add("x",watchedVal);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
RequestParams p = core.getSolrConfig().getRequestParams();
|
||||
RequestParams.VersionedParams v = p.getParams("watched");
|
||||
if(v== null){
|
||||
watchedVal = null;
|
||||
version=-1;
|
||||
return;
|
||||
}
|
||||
if(v.getVersion() != version){
|
||||
watchedVal = v.getMap().get("x");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void inform(SolrCore core) {
|
||||
this.core = core;
|
||||
core.addConfListener(this);
|
||||
run();
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,68 +0,0 @@
|
|||
package org.apache.solr.core;
|
||||
|
||||
/*
|
||||
* 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 java.io.IOException;
|
||||
|
||||
import org.apache.solr.request.SolrQueryRequest;
|
||||
import org.apache.solr.response.SolrQueryResponse;
|
||||
import org.apache.solr.util.plugin.SolrCoreAware;
|
||||
|
||||
public class BlobStoreTestRequestHandlerV2 extends BlobStoreTestRequestHandler implements Runnable, SolrCoreAware{
|
||||
|
||||
private SolrCore core;
|
||||
|
||||
private long version = 1;
|
||||
private String watchedVal = null;
|
||||
|
||||
@Override
|
||||
public void handleRequestBody(SolrQueryRequest req, SolrQueryResponse rsp) throws IOException {
|
||||
super.handleRequestBody(req, rsp);
|
||||
rsp.add("class", this.getClass().getName());
|
||||
rsp.add("x",watchedVal);
|
||||
/* try {
|
||||
Class.forName("org.apache.solr.core.BlobStoreTestRequestHandler");
|
||||
} catch (ClassNotFoundException e) {
|
||||
rsp.add("e", ClassNotFoundException.class.getSimpleName());
|
||||
}*/
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
RequestParams p = core.getSolrConfig().getRequestParams();
|
||||
RequestParams.VersionedParams v = p.getParams("watched");
|
||||
if(v== null){
|
||||
watchedVal = null;
|
||||
version=-1;
|
||||
return;
|
||||
}
|
||||
if(v.getVersion() != version){
|
||||
watchedVal = v.getMap().get("x");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void inform(SolrCore core) {
|
||||
this.core = core;
|
||||
core.addConfListener(this);
|
||||
run();
|
||||
|
||||
}
|
||||
}
|
|
@ -19,7 +19,6 @@ package org.apache.solr.core;
|
|||
|
||||
import org.apache.solr.SolrTestCaseJ4;
|
||||
import org.apache.solr.common.util.NamedList;
|
||||
import org.apache.solr.handler.StandardRequestHandler;
|
||||
import org.apache.solr.request.SolrRequestHandler;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
@ -49,8 +48,8 @@ public class RequestHandlersTest extends SolrTestCaseJ4 {
|
|||
@Test
|
||||
public void testLazyLoading() {
|
||||
SolrCore core = h.getCore();
|
||||
SolrRequestHandler handler = core.getRequestHandler( "lazy" );
|
||||
assertFalse( handler instanceof StandardRequestHandler );
|
||||
PluginRegistry.PluginHolder<SolrRequestHandler> handler = core.getRequestHandlers().getRegistry().get("lazy");
|
||||
assertFalse(handler.isLoaded());
|
||||
|
||||
assertU(adoc("id", "42",
|
||||
"name", "Zapp Brannigan"));
|
||||
|
|
|
@ -26,10 +26,13 @@ import org.apache.solr.handler.TestBlobHandler;
|
|||
import org.apache.solr.util.RESTfulServerProvider;
|
||||
import org.apache.solr.util.RestTestHarness;
|
||||
import org.apache.solr.util.SimplePostTool;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
@ -40,6 +43,9 @@ import java.util.Map;
|
|||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipOutputStream;
|
||||
|
||||
import static java.util.Arrays.asList;
|
||||
import static org.apache.solr.handler.TestSolrConfigHandlerCloud.compareValues;
|
||||
|
||||
public class TestDynamicLoading extends AbstractFullDistribZkTestBase {
|
||||
static final Logger log = LoggerFactory.getLogger(TestDynamicLoading.class);
|
||||
private List<RestTestHarness> restTestHarnesses = new ArrayList<>();
|
||||
|
@ -56,6 +62,11 @@ public class TestDynamicLoading extends AbstractFullDistribZkTestBase {
|
|||
}
|
||||
}
|
||||
|
||||
@BeforeClass
|
||||
public static void enableRuntimeLib() throws Exception {
|
||||
System.setProperty("enable.runtime.lib", "true");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void distribTearDown() throws Exception {
|
||||
super.distribTearDown();
|
||||
|
@ -66,51 +77,56 @@ public class TestDynamicLoading extends AbstractFullDistribZkTestBase {
|
|||
|
||||
@Test
|
||||
public void testDynamicLoading() throws Exception {
|
||||
System.setProperty("enable.runtime.lib", "true");
|
||||
setupHarnesses();
|
||||
|
||||
String blobName = "colltest";
|
||||
boolean success = false;
|
||||
|
||||
|
||||
HttpSolrClient randomClient = (HttpSolrClient) clients.get(random().nextInt(clients.size()));
|
||||
String baseURL = randomClient.getBaseURL();
|
||||
baseURL = baseURL.substring(0, baseURL.lastIndexOf('/'));
|
||||
String payload = "{\n" +
|
||||
"'create-requesthandler' : { 'name' : '/test1', 'class': 'org.apache.solr.core.BlobStoreTestRequestHandler' , 'lib':'test','version':'1'}\n" +
|
||||
"'add-runtimelib' : { 'name' : 'colltest' ,'version':1}\n" +
|
||||
"}";
|
||||
RestTestHarness client = restTestHarnesses.get(random().nextInt(restTestHarnesses.size()));
|
||||
TestSolrConfigHandler.runConfigCommand(client, "/config?wt=json", payload);
|
||||
TestSolrConfigHandler.testForResponseElement(client,
|
||||
null,
|
||||
"/config/overlay?wt=json",
|
||||
null,
|
||||
Arrays.asList("overlay", "runtimeLib", blobName, "version"),
|
||||
1l, 10);
|
||||
|
||||
|
||||
payload = "{\n" +
|
||||
"'create-requesthandler' : { 'name' : '/test1', 'class': 'org.apache.solr.core.BlobStoreTestRequestHandler' , 'runtimeLib' : true }\n" +
|
||||
"}";
|
||||
|
||||
client = restTestHarnesses.get(random().nextInt(restTestHarnesses.size()));
|
||||
TestSolrConfigHandler.runConfigCommand(client,"/config?wt=json",payload);
|
||||
TestSolrConfigHandler.testForResponseElement(client,
|
||||
null,
|
||||
"/config/overlay?wt=json",
|
||||
null,
|
||||
Arrays.asList("overlay", "requestHandler", "/test1", "lib"),
|
||||
"test",10);
|
||||
Arrays.asList("overlay", "requestHandler", "/test1", "class"),
|
||||
"org.apache.solr.core.BlobStoreTestRequestHandler",10);
|
||||
|
||||
Map map = TestSolrConfigHandler.getRespMap("/test1?wt=json", client);
|
||||
|
||||
assertNotNull(map = (Map) map.get("error"));
|
||||
assertEquals(".system collection not available", map.get("msg"));
|
||||
assertNotNull(TestBlobHandler.getAsString(map), map = (Map) map.get("error"));
|
||||
assertEquals(TestBlobHandler.getAsString(map), ".system collection not available", map.get("msg"));
|
||||
|
||||
|
||||
HttpSolrClient randomClient = (HttpSolrClient) clients.get(random().nextInt(clients.size()));
|
||||
String baseURL = randomClient.getBaseURL();
|
||||
baseURL = baseURL.substring(0, baseURL.lastIndexOf('/'));
|
||||
TestBlobHandler.createSystemCollection(new HttpSolrClient(baseURL, randomClient.getHttpClient()));
|
||||
waitForRecoveriesToFinish(".system", true);
|
||||
|
||||
map = TestSolrConfigHandler.getRespMap("/test1?wt=json", client);
|
||||
|
||||
|
||||
assertNotNull(map = (Map) map.get("error"));
|
||||
assertEquals("no such blob or version available: test/1", map.get("msg"));
|
||||
ByteBuffer jar = generateZip( TestDynamicLoading.class,BlobStoreTestRequestHandler.class);
|
||||
TestBlobHandler.postAndCheck(cloudClient, baseURL, jar,1);
|
||||
|
||||
boolean success= false;
|
||||
for(int i=0;i<50;i++) {
|
||||
map = TestSolrConfigHandler.getRespMap("/test1?wt=json", client);
|
||||
if(BlobStoreTestRequestHandler.class.getName().equals(map.get("class"))){
|
||||
success = true;
|
||||
break;
|
||||
}
|
||||
Thread.sleep(100);
|
||||
}
|
||||
assertTrue(new String( ZkStateReader.toJSON(map) , StandardCharsets.UTF_8), success );
|
||||
|
||||
jar = generateZip( TestDynamicLoading.class,BlobStoreTestRequestHandlerV2.class);
|
||||
TestBlobHandler.postAndCheck(cloudClient, baseURL, jar,2);
|
||||
|
||||
assertEquals("full output " + TestBlobHandler.getAsString(map), "no such blob or version available: colltest/1" , map.get("msg"));
|
||||
payload = " {\n" +
|
||||
" 'set' : {'watched': {" +
|
||||
" 'x':'X val',\n" +
|
||||
|
@ -129,30 +145,7 @@ public class TestDynamicLoading extends AbstractFullDistribZkTestBase {
|
|||
10);
|
||||
|
||||
|
||||
payload = "{\n" +
|
||||
"'update-requesthandler' : { 'name' : '/test1', 'class': 'org.apache.solr.core.BlobStoreTestRequestHandlerV2' , 'lib':'test','version':2}\n" +
|
||||
"}";
|
||||
|
||||
client = restTestHarnesses.get(random().nextInt(restTestHarnesses.size()));
|
||||
TestSolrConfigHandler.runConfigCommand(client,"/config?wt=json",payload);
|
||||
TestSolrConfigHandler.testForResponseElement(client,
|
||||
null,
|
||||
"/config/overlay?wt=json",
|
||||
null,
|
||||
Arrays.asList("overlay", "requestHandler", "/test1", "version"),
|
||||
2l,10);
|
||||
|
||||
success= false;
|
||||
for(int i=0;i<100;i++) {
|
||||
map = TestSolrConfigHandler.getRespMap("/test1?wt=json", client);
|
||||
if(BlobStoreTestRequestHandlerV2.class.getName().equals(map.get("class"))) {
|
||||
success = true;
|
||||
break;
|
||||
}
|
||||
Thread.sleep(100);
|
||||
}
|
||||
|
||||
assertTrue("New version of class is not loaded " + new String(ZkStateReader.toJSON(map), StandardCharsets.UTF_8), success);
|
||||
|
||||
for(int i=0;i<100;i++) {
|
||||
map = TestSolrConfigHandler.getRespMap("/test1?wt=json", client);
|
||||
|
@ -162,6 +155,101 @@ public class TestDynamicLoading extends AbstractFullDistribZkTestBase {
|
|||
}
|
||||
Thread.sleep(100);
|
||||
}
|
||||
ByteBuffer jar = null;
|
||||
|
||||
// jar = persistZip("/tmp/runtimelibs.jar", TestDynamicLoading.class, RuntimeLibReqHandler.class, RuntimeLibResponseWriter.class, RuntimeLibSearchComponent.class);
|
||||
// if(true) return;
|
||||
|
||||
jar = getFileContent("runtimecode/runtimelibs.jar");
|
||||
TestBlobHandler.postAndCheck(cloudClient, baseURL, blobName, jar, 1);
|
||||
|
||||
payload = "{\n" +
|
||||
"'create-requesthandler' : { 'name' : '/runtime', 'class': 'org.apache.solr.core.RuntimeLibReqHandler' , 'runtimeLib':true }," +
|
||||
"'create-searchcomponent' : { 'name' : 'get', 'class': 'org.apache.solr.core.RuntimeLibSearchComponent' , 'runtimeLib':true }," +
|
||||
"'create-queryResponseWriter' : { 'name' : 'json1', 'class': 'org.apache.solr.core.RuntimeLibResponseWriter' , 'runtimeLib':true }" +
|
||||
"}";
|
||||
client = restTestHarnesses.get(random().nextInt(restTestHarnesses.size()));
|
||||
TestSolrConfigHandler.runConfigCommand(client, "/config?wt=json", payload);
|
||||
|
||||
Map result = TestSolrConfigHandler.testForResponseElement(client,
|
||||
null,
|
||||
"/config/overlay?wt=json",
|
||||
null,
|
||||
Arrays.asList("overlay", "requestHandler", "/runtime", "class"),
|
||||
"org.apache.solr.core.RuntimeLibReqHandler", 10);
|
||||
compareValues(result, "org.apache.solr.core.RuntimeLibResponseWriter", asList("overlay", "queryResponseWriter", "json1", "class"));
|
||||
compareValues(result, "org.apache.solr.core.RuntimeLibSearchComponent", asList("overlay", "searchComponent", "get", "class"));
|
||||
|
||||
result = TestSolrConfigHandler.testForResponseElement(client,
|
||||
null,
|
||||
"/runtime?wt=json",
|
||||
null,
|
||||
Arrays.asList("class"),
|
||||
"org.apache.solr.core.RuntimeLibReqHandler", 10);
|
||||
compareValues(result, MemClassLoader.class.getName(), asList( "loader"));
|
||||
|
||||
result = TestSolrConfigHandler.testForResponseElement(client,
|
||||
null,
|
||||
"/runtime?wt=json1",
|
||||
null,
|
||||
Arrays.asList("wt"),
|
||||
"org.apache.solr.core.RuntimeLibResponseWriter", 10);
|
||||
compareValues(result, MemClassLoader.class.getName(), asList( "loader"));
|
||||
|
||||
result = TestSolrConfigHandler.testForResponseElement(client,
|
||||
null,
|
||||
"/get?abc=xyz",
|
||||
null,
|
||||
Arrays.asList("get"),
|
||||
"org.apache.solr.core.RuntimeLibSearchComponent", 10);
|
||||
compareValues(result, MemClassLoader.class.getName(), asList( "loader"));
|
||||
|
||||
jar = getFileContent("runtimecode/runtimelibs_v2.jar");
|
||||
TestBlobHandler.postAndCheck(cloudClient, baseURL, blobName, jar, 2);
|
||||
payload = "{\n" +
|
||||
"'update-runtimelib' : { 'name' : 'colltest' ,'version':2}\n" +
|
||||
"}";
|
||||
client = restTestHarnesses.get(random().nextInt(restTestHarnesses.size()));
|
||||
TestSolrConfigHandler.runConfigCommand(client, "/config?wt=json", payload);
|
||||
TestSolrConfigHandler.testForResponseElement(client,
|
||||
null,
|
||||
"/config/overlay?wt=json",
|
||||
null,
|
||||
Arrays.asList("overlay", "runtimeLib", blobName, "version"),
|
||||
2l, 10);
|
||||
|
||||
result = TestSolrConfigHandler.testForResponseElement(client,
|
||||
null,
|
||||
"/get?abc=xyz",
|
||||
null,
|
||||
Arrays.asList("Version"),
|
||||
"2", 10);
|
||||
|
||||
|
||||
payload = " {\n" +
|
||||
" 'set' : {'watched': {" +
|
||||
" 'x':'X val',\n" +
|
||||
" 'y': 'Y val'}\n" +
|
||||
" }\n" +
|
||||
" }";
|
||||
|
||||
TestSolrConfigHandler.runConfigCommand(client,"/config/params?wt=json",payload);
|
||||
TestSolrConfigHandler.testForResponseElement(
|
||||
client,
|
||||
null,
|
||||
"/config/params?wt=json",
|
||||
cloudClient,
|
||||
Arrays.asList("response", "params", "watched", "x"),
|
||||
"X val",
|
||||
10);
|
||||
result = TestSolrConfigHandler.testForResponseElement(
|
||||
client,
|
||||
null,
|
||||
"/test1?wt=json",
|
||||
cloudClient,
|
||||
Arrays.asList("x"),
|
||||
"X val",
|
||||
10);
|
||||
|
||||
payload = " {\n" +
|
||||
" 'set' : {'watched': {" +
|
||||
|
@ -171,17 +259,33 @@ public class TestDynamicLoading extends AbstractFullDistribZkTestBase {
|
|||
" }";
|
||||
|
||||
TestSolrConfigHandler.runConfigCommand(client,"/config/params?wt=json",payload);
|
||||
for(int i=0;i<50;i++) {
|
||||
map = TestSolrConfigHandler.getRespMap("/test1?wt=json", client);
|
||||
if("X val changed".equals(map.get("x"))){
|
||||
success = true;
|
||||
break;
|
||||
}
|
||||
Thread.sleep(100);
|
||||
result = TestSolrConfigHandler.testForResponseElement(
|
||||
client,
|
||||
null,
|
||||
"/test1?wt=json",
|
||||
cloudClient,
|
||||
Arrays.asList("x"),
|
||||
"X val changed",
|
||||
10);
|
||||
}
|
||||
|
||||
private ByteBuffer getFileContent(String f) throws IOException {
|
||||
ByteBuffer jar;
|
||||
try (FileInputStream fis = new FileInputStream(getFile(f))) {
|
||||
byte[] buf = new byte[fis.available()];
|
||||
fis.read(buf);
|
||||
jar = ByteBuffer.wrap(buf);
|
||||
}
|
||||
assertTrue("listener did not get triggered" + new String(ZkStateReader.toJSON(map), StandardCharsets.UTF_8), success);
|
||||
|
||||
return jar;
|
||||
}
|
||||
|
||||
public static ByteBuffer persistZip(String loc, Class... classes) throws IOException {
|
||||
ByteBuffer jar = generateZip(classes);
|
||||
try (FileOutputStream fos = new FileOutputStream(loc)){
|
||||
fos.write(jar.array(), 0, jar.limit());
|
||||
fos.flush();
|
||||
}
|
||||
return jar;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -86,8 +86,9 @@ public class TestBlobHandler extends AbstractFullDistribZkTestBase {
|
|||
for (int i = 0; i < bytarr.length; i++) bytarr[i]= (byte) (i % 127);
|
||||
byte[] bytarr2 = new byte[2048];
|
||||
for (int i = 0; i < bytarr2.length; i++) bytarr2[i]= (byte) (i % 127);
|
||||
postAndCheck(cloudClient, baseUrl, ByteBuffer.wrap( bytarr), 1);
|
||||
postAndCheck(cloudClient, baseUrl, ByteBuffer.wrap( bytarr2), 2);
|
||||
String blobName = "test";
|
||||
postAndCheck(cloudClient, baseUrl, blobName, ByteBuffer.wrap(bytarr), 1);
|
||||
postAndCheck(cloudClient, baseUrl, blobName, ByteBuffer.wrap(bytarr2), 2);
|
||||
|
||||
url = baseUrl + "/.system/blob/test/1";
|
||||
map = TestSolrConfigHandlerConcurrent.getAsMap(url,cloudClient);
|
||||
|
@ -123,8 +124,8 @@ public class TestBlobHandler extends AbstractFullDistribZkTestBase {
|
|||
DirectUpdateHandler2.commitOnClose = true;
|
||||
}
|
||||
|
||||
public static void postAndCheck(CloudSolrClient cloudClient, String baseUrl, ByteBuffer bytes, int count) throws Exception {
|
||||
postData(cloudClient, baseUrl, bytes);
|
||||
public static void postAndCheck(CloudSolrClient cloudClient, String baseUrl, String blobName, ByteBuffer bytes, int count) throws Exception {
|
||||
postData(cloudClient, baseUrl, blobName, bytes);
|
||||
|
||||
String url;
|
||||
Map map = null;
|
||||
|
@ -132,7 +133,7 @@ public class TestBlobHandler extends AbstractFullDistribZkTestBase {
|
|||
long start = System.currentTimeMillis();
|
||||
int i=0;
|
||||
for(;i<150;i++) {//15 secs
|
||||
url = baseUrl + "/.system/blob/test";
|
||||
url = baseUrl + "/.system/blob/" + blobName;
|
||||
map = TestSolrConfigHandlerConcurrent.getAsMap(url, cloudClient);
|
||||
String numFound = String.valueOf(ConfigOverlay.getObjectByPath(map, false, Arrays.asList("response", "numFound")));
|
||||
if(!(""+count).equals(numFound)) {
|
||||
|
@ -171,12 +172,12 @@ public class TestBlobHandler extends AbstractFullDistribZkTestBase {
|
|||
|
||||
}
|
||||
|
||||
public static void postData(CloudSolrClient cloudClient, String baseUrl, ByteBuffer bytarr) throws IOException {
|
||||
public static void postData(CloudSolrClient cloudClient, String baseUrl, String blobName, ByteBuffer bytarr) throws IOException {
|
||||
HttpPost httpPost = null;
|
||||
HttpEntity entity;
|
||||
String response = null;
|
||||
try {
|
||||
httpPost = new HttpPost(baseUrl+"/.system/blob/test");
|
||||
httpPost = new HttpPost(baseUrl + "/.system/blob/" + blobName);
|
||||
httpPost.setHeader("Content-Type","application/octet-stream");
|
||||
httpPost.setEntity(new ByteArrayEntity(bytarr.array(), bytarr.arrayOffset(), bytarr.limit()));
|
||||
entity = cloudClient.getLbClient().getHttpClient().execute(httpPost).getEntity();
|
||||
|
|
|
@ -180,7 +180,11 @@ public class SpellCheckComponentTest extends SolrTestCaseJ4 {
|
|||
request = req("qt", "spellCheckCompRH", "q", "*:*", "spellcheck.q", "ttle",
|
||||
"spellcheck", "true", "spellcheck.dictionary", "default",
|
||||
"spellcheck.reload", "true");
|
||||
ResponseBuilder rb = new ResponseBuilder(request, new SolrQueryResponse(), new ArrayList(h.getCore().getSearchComponents().values()));
|
||||
List<SearchComponent> components = new ArrayList<>();
|
||||
for (String name : h.getCore().getSearchComponents().keySet()) {
|
||||
components.add(h.getCore().getSearchComponent(name));
|
||||
}
|
||||
ResponseBuilder rb = new ResponseBuilder(request, new SolrQueryResponse(), components);
|
||||
checker.prepare(rb);
|
||||
|
||||
try {
|
||||
|
|
|
@ -55,11 +55,7 @@ public class QueryEqualityTest extends SolrTestCaseJ4 {
|
|||
public static void afterClassParserCoverageTest() {
|
||||
|
||||
if ( ! doAssertParserCoverage) return;
|
||||
|
||||
for (int i=0; i < QParserPlugin.standardPlugins.length; i+=2) {
|
||||
assertTrue("qparser #"+i+" name not a string",
|
||||
QParserPlugin.standardPlugins[i] instanceof String);
|
||||
final String name = (String)QParserPlugin.standardPlugins[i];
|
||||
for (String name : QParserPlugin.standardPlugins.keySet()) {
|
||||
assertTrue("testParserCoverage was run w/o any other method explicitly testing qparser: " + name, qParsersTested.contains(name));
|
||||
}
|
||||
|
||||
|
|
|
@ -24,7 +24,6 @@ import java.lang.reflect.Field;
|
|||
import java.lang.reflect.Modifier;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
|
@ -48,15 +47,13 @@ public class TestStandardQParsers extends LuceneTestCase {
|
|||
*/
|
||||
@Test
|
||||
public void testRegisteredName() throws Exception {
|
||||
Map<String, Class<QParserPlugin>> standardPlugins = getStandardQParsers();
|
||||
List<String> notStatic = new ArrayList<>(QParserPlugin.standardPlugins.size());
|
||||
List<String> notFinal = new ArrayList<>(QParserPlugin.standardPlugins.size());
|
||||
List<String> mismatch = new ArrayList<>(QParserPlugin.standardPlugins.size());
|
||||
|
||||
List<String> notStatic = new ArrayList<>(standardPlugins.size());
|
||||
List<String> notFinal = new ArrayList<>(standardPlugins.size());
|
||||
List<String> mismatch = new ArrayList<>(standardPlugins.size());
|
||||
|
||||
for (Map.Entry<String,Class<QParserPlugin>> pair : standardPlugins.entrySet()) {
|
||||
for (Map.Entry<String, Class<? extends QParserPlugin>> pair : QParserPlugin.standardPlugins.entrySet()) {
|
||||
String regName = pair.getKey();
|
||||
Class<QParserPlugin> clazz = pair.getValue();
|
||||
Class<? extends QParserPlugin> clazz = pair.getValue();
|
||||
|
||||
Field nameField = clazz.getField(FIELD_NAME);
|
||||
int modifiers = nameField.getModifiers();
|
||||
|
@ -79,30 +76,8 @@ public class TestStandardQParsers extends LuceneTestCase {
|
|||
|
||||
assertTrue("DEFAULT_QTYPE is not in the standard set of registered names: " +
|
||||
QParserPlugin.DEFAULT_QTYPE,
|
||||
standardPlugins.keySet().contains(QParserPlugin.DEFAULT_QTYPE));
|
||||
QParserPlugin.standardPlugins.keySet().contains(QParserPlugin.DEFAULT_QTYPE));
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Get standard query parsers registered by default.
|
||||
*
|
||||
* @see org.apache.solr.search.QParserPlugin#standardPlugins
|
||||
* @return Map of classes extending QParserPlugin keyed by the registered name
|
||||
*/
|
||||
private Map<String,Class<QParserPlugin>> getStandardQParsers() {
|
||||
Object[] standardPluginsValue = QParserPlugin.standardPlugins;
|
||||
|
||||
Map<String, Class<QParserPlugin>> standardPlugins
|
||||
= new HashMap<>(standardPluginsValue.length / 2);
|
||||
|
||||
for (int i = 0; i < standardPluginsValue.length; i += 2) {
|
||||
@SuppressWarnings("unchecked")
|
||||
String registeredName = (String) standardPluginsValue[i];
|
||||
@SuppressWarnings("unchecked")
|
||||
Class<QParserPlugin> clazz = (Class<QParserPlugin>) standardPluginsValue[i + 1];
|
||||
standardPlugins.put(registeredName, clazz);
|
||||
}
|
||||
return standardPlugins;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue