mirror of https://github.com/apache/lucene.git
SOLR-1449: solrconfig.xml syntax to add classpath elements from outside of instanceDir
git-svn-id: https://svn.apache.org/repos/asf/lucene/solr/trunk@824364 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
fa623ae3c2
commit
afcfa3c1c2
|
@ -364,6 +364,10 @@ New Features
|
||||||
|
|
||||||
85. SOLR-1478: Enable sort by Lucene docid. (ehatcher)
|
85. SOLR-1478: Enable sort by Lucene docid. (ehatcher)
|
||||||
|
|
||||||
|
86. SOLR-1449: Add <lib> elements to solrconfig.xml to specifying additional
|
||||||
|
classpath directories and regular expressions. (hossman via yonik)
|
||||||
|
|
||||||
|
|
||||||
Optimizations
|
Optimizations
|
||||||
----------------------
|
----------------------
|
||||||
1. SOLR-374: Use IndexReader.reopen to save resources by re-using parts of the
|
1. SOLR-374: Use IndexReader.reopen to save resources by re-using parts of the
|
||||||
|
|
|
@ -205,7 +205,7 @@
|
||||||
<path refid="compile.classpath"/>
|
<path refid="compile.classpath"/>
|
||||||
<path refid="compile.classpath.solrj"/>
|
<path refid="compile.classpath.solrj"/>
|
||||||
<fileset dir="contrib">
|
<fileset dir="contrib">
|
||||||
<include name="**/lib/**.jar"/>
|
<include name="**/lib/**/*.jar"/>
|
||||||
</fileset>
|
</fileset>
|
||||||
<pathelement location="${dest}/client/solrj"/>
|
<pathelement location="${dest}/client/solrj"/>
|
||||||
</path>
|
</path>
|
||||||
|
@ -374,11 +374,7 @@
|
||||||
description="Runs the core unit tests."
|
description="Runs the core unit tests."
|
||||||
depends="test-core, test-contrib" />
|
depends="test-core, test-contrib" />
|
||||||
|
|
||||||
<target name="solr-cell-example" depends="compile">
|
<target name="junit" depends="compileTests,dist-contrib">
|
||||||
<ant antfile="contrib/extraction/build.xml" inheritall="false" target="example" />
|
|
||||||
</target>
|
|
||||||
|
|
||||||
<target name="junit" depends="compileTests,solr-cell-example">
|
|
||||||
|
|
||||||
<!-- no description so it doesn't show up in -projecthelp -->
|
<!-- no description so it doesn't show up in -projecthelp -->
|
||||||
<mkdir dir="${junit.output.dir}"/>
|
<mkdir dir="${junit.output.dir}"/>
|
||||||
|
|
|
@ -48,6 +48,10 @@
|
||||||
<target name="clean">
|
<target name="clean">
|
||||||
<delete failonerror="false" dir="${dest}"/>
|
<delete failonerror="false" dir="${dest}"/>
|
||||||
|
|
||||||
|
<!-- example doesn't create this anymore, but clean it up
|
||||||
|
if it's still there from an old build
|
||||||
|
-->
|
||||||
|
<delete dir="example/lib" />
|
||||||
</target>
|
</target>
|
||||||
<target name="clean-downloads">
|
<target name="clean-downloads">
|
||||||
<delete>
|
<delete>
|
||||||
|
@ -112,17 +116,11 @@
|
||||||
</solr-javac>
|
</solr-javac>
|
||||||
</target>
|
</target>
|
||||||
|
|
||||||
<target name="example" depends="build">
|
<target name="example" depends="build,dist">
|
||||||
<mkdir dir="${example.local}/lib"/>
|
<!-- this task use to copy lib's but that's no longer needed because
|
||||||
<copy file="${dest}/${fullnamever}.jar" todir="${example.local}/lib"/>
|
../lib and ../lib/downloads are now included explicitly by
|
||||||
<copy todir="${example.local}/lib">
|
example/conf/solrconfig.xml
|
||||||
<fileset dir="lib">
|
-->
|
||||||
<include name="*.jar"/>
|
|
||||||
</fileset>
|
|
||||||
<fileset dir="lib/downloads">
|
|
||||||
<include name="*.jar"/>
|
|
||||||
</fileset>
|
|
||||||
</copy>
|
|
||||||
</target>
|
</target>
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -26,6 +26,13 @@
|
||||||
-->
|
-->
|
||||||
<abortOnConfigurationError>${solr.abortOnConfigurationError:true}</abortOnConfigurationError>
|
<abortOnConfigurationError>${solr.abortOnConfigurationError:true}</abortOnConfigurationError>
|
||||||
|
|
||||||
|
<lib dir="../../../dist/" regex="apache-solr-clustering-(\d|\.)+-.*\.jar" />
|
||||||
|
<lib dir="../lib" />
|
||||||
|
<!-- these jars are not inlcuded in the release because of their licenses,
|
||||||
|
they will be downlodded when 'ant example' is run
|
||||||
|
-->
|
||||||
|
<lib dir="../lib/downloads/" />
|
||||||
|
|
||||||
<!-- Used to specify an alternate directory to hold all index data
|
<!-- Used to specify an alternate directory to hold all index data
|
||||||
other than the default ./data under the Solr home.
|
other than the default ./data under the Solr home.
|
||||||
If replication is in use, this should match the replication configuration. -->
|
If replication is in use, this should match the replication configuration. -->
|
||||||
|
@ -555,4 +562,4 @@
|
||||||
-->
|
-->
|
||||||
</admin>
|
</admin>
|
||||||
|
|
||||||
</config>
|
</config>
|
||||||
|
|
|
@ -73,6 +73,9 @@
|
||||||
</delete>
|
</delete>
|
||||||
<!-- Clean up examples -->
|
<!-- Clean up examples -->
|
||||||
<delete failonerror="false">
|
<delete failonerror="false">
|
||||||
|
<!-- we no longer copy things into this directory, but we still clean it up
|
||||||
|
the files are still there from a previous checkout
|
||||||
|
-->
|
||||||
<fileset dir="${example}/example-DIH/solr/mail/lib" includes="*.jar" />
|
<fileset dir="${example}/example-DIH/solr/mail/lib" includes="*.jar" />
|
||||||
</delete>
|
</delete>
|
||||||
</target>
|
</target>
|
||||||
|
@ -197,14 +200,11 @@
|
||||||
</sequential>
|
</sequential>
|
||||||
</target>
|
</target>
|
||||||
|
|
||||||
<target name="example" depends="build">
|
<target name="example" depends="build,dist">
|
||||||
<!-- Copy the jar into example-DIH/solr/mail/lib -->
|
<!--
|
||||||
<copy file="target/apache-${ant.project.name}-extras-${version}.jar" todir="${example}/example-DIH/solr/mail/lib"/>
|
this target use to copy libs, but that is no longer needed.
|
||||||
<copy todir="${example}/example-DIH/solr/mail/lib">
|
now we just depend on dist to ensure the extra's jar exists.
|
||||||
<fileset dir="lib">
|
-->
|
||||||
<include name="**/*.jar"/>
|
|
||||||
</fileset>
|
|
||||||
</copy>
|
|
||||||
</target>
|
</target>
|
||||||
|
|
||||||
</project>
|
</project>
|
||||||
|
|
|
@ -114,13 +114,7 @@
|
||||||
</target>
|
</target>
|
||||||
|
|
||||||
<target name="example" depends="build">
|
<target name="example" depends="build">
|
||||||
<!-- Copy the jar into example/solr/lib -->
|
<!-- :NOOP: this use to copy libs but now we can refer to them by path -->
|
||||||
<copy file="${dest}/${fullnamever}.jar" todir="${example}/solr/lib"/>
|
|
||||||
<copy todir="${example}/solr/lib">
|
|
||||||
<fileset dir="lib">
|
|
||||||
<include name="**/*.jar"/>
|
|
||||||
</fileset>
|
|
||||||
</copy>
|
|
||||||
</target>
|
</target>
|
||||||
|
|
||||||
<target name="javadoc">
|
<target name="javadoc">
|
||||||
|
@ -142,4 +136,4 @@
|
||||||
</target>
|
</target>
|
||||||
|
|
||||||
|
|
||||||
</project>
|
</project>
|
||||||
|
|
|
@ -25,6 +25,9 @@
|
||||||
-Dsolr.abortOnConfigurationError=false
|
-Dsolr.abortOnConfigurationError=false
|
||||||
-->
|
-->
|
||||||
<abortOnConfigurationError>${solr.abortOnConfigurationError:true}</abortOnConfigurationError>
|
<abortOnConfigurationError>${solr.abortOnConfigurationError:true}</abortOnConfigurationError>
|
||||||
|
|
||||||
|
<lib dir="../../../../contrib/dataimporthandler/lib/" regex=".*jar$" />
|
||||||
|
<lib dir="../../../../dist/" regex="apache-solr-dataimporthandler-extras.*jar" />
|
||||||
|
|
||||||
<indexDefaults>
|
<indexDefaults>
|
||||||
<!-- Values here affect all index writers and act as a default unless overridden. -->
|
<!-- Values here affect all index writers and act as a default unless overridden. -->
|
||||||
|
|
|
@ -45,7 +45,9 @@ The Solr Home directory typically contains the following subdirectories...
|
||||||
This directory is optional. If it exists, Solr will load any Jars
|
This directory is optional. If it exists, Solr will load any Jars
|
||||||
found in this directory and use them to resolve any "plugins"
|
found in this directory and use them to resolve any "plugins"
|
||||||
specified in your solrconfig.xml or schema.xml (ie: Analyzers,
|
specified in your solrconfig.xml or schema.xml (ie: Analyzers,
|
||||||
Request Handlers, etc...)
|
Request Handlers, etc...). Alternatively you can use the <lib>
|
||||||
|
syntax in solrconfig.xml to direct Solr to your plugins. See the
|
||||||
|
example solrconfig.xml file for details.
|
||||||
|
|
||||||
bin/
|
bin/
|
||||||
This directory is optional. It is the default location used for
|
This directory is optional. It is the default location used for
|
||||||
|
|
|
@ -32,6 +32,36 @@
|
||||||
-->
|
-->
|
||||||
<abortOnConfigurationError>${solr.abortOnConfigurationError:true}</abortOnConfigurationError>
|
<abortOnConfigurationError>${solr.abortOnConfigurationError:true}</abortOnConfigurationError>
|
||||||
|
|
||||||
|
<!-- lib directives can be used to instruct Solr to load an Jars identified
|
||||||
|
and use them to resolve any "plugins" specified in your solrconfig.xml or
|
||||||
|
schema.xml (ie: Analyzers, Request Handlers, etc...).
|
||||||
|
|
||||||
|
All directories and paths are resolved relative the instanceDir.
|
||||||
|
|
||||||
|
If a "./lib" directory exists in your instanceDir, all files found in it
|
||||||
|
are included as if you had used the following syntax...
|
||||||
|
|
||||||
|
<lib dir="./lib" />
|
||||||
|
-->
|
||||||
|
<!-- A dir option by itself adds any files found in the directory to the
|
||||||
|
classpath, this is useful for including all jars in a directory.
|
||||||
|
-->
|
||||||
|
<lib dir="../../contrib/extraction/lib" />
|
||||||
|
<!-- When a regex is specified in addition to a directory, only the files in that
|
||||||
|
directory which completely match the regex (anchored on both ends)
|
||||||
|
will be included.
|
||||||
|
-->
|
||||||
|
<lib dir="../../dist/" regex="apache-solr-cell-(\d|\.)+-.*\.jar" />
|
||||||
|
<!-- If a dir option (with or without a regex) is used and nothing is found
|
||||||
|
that matches, it will be ignored
|
||||||
|
-->
|
||||||
|
<lib dir="/total/crap/dir/ignored" />
|
||||||
|
<!-- an exact path can be used to specify a specific file. This will cause
|
||||||
|
a serious error to be logged if it can't be loaded.
|
||||||
|
-->
|
||||||
|
<lib path="../a-jar-that-does-not-exist.jar" />
|
||||||
|
|
||||||
|
|
||||||
<!-- Used to specify an alternate directory to hold all index data
|
<!-- Used to specify an alternate directory to hold all index data
|
||||||
other than the default ./data under the Solr home.
|
other than the default ./data under the Solr home.
|
||||||
If replication is in use, this should match the replication configuration. -->
|
If replication is in use, this should match the replication configuration. -->
|
||||||
|
|
|
@ -37,7 +37,7 @@ public class FileUtils {
|
||||||
* of "base")
|
* of "base")
|
||||||
* </p>
|
* </p>
|
||||||
*/
|
*/
|
||||||
public static File resolvePath(File base, String path) throws IOException {
|
public static File resolvePath(File base, String path) {
|
||||||
File r = new File(path);
|
File r = new File(path);
|
||||||
return r.isAbsolute() ? r : new File(base, path);
|
return r.isAbsolute() ? r : new File(base, path);
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,43 @@
|
||||||
|
/**
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.apache.solr.common.util;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileFilter;
|
||||||
|
import java.util.regex.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Accepts any file whose name matches the pattern
|
||||||
|
* @version $Id$
|
||||||
|
*/
|
||||||
|
public final class RegexFileFilter implements FileFilter {
|
||||||
|
|
||||||
|
final Pattern pattern;
|
||||||
|
public RegexFileFilter(String regex) {
|
||||||
|
this(Pattern.compile(regex));
|
||||||
|
}
|
||||||
|
public RegexFileFilter(Pattern regex) {
|
||||||
|
pattern = regex;
|
||||||
|
}
|
||||||
|
public boolean accept(File f) {
|
||||||
|
return pattern.matcher(f.getName()).matches();
|
||||||
|
}
|
||||||
|
public String toString() {
|
||||||
|
return "regex:" + pattern.toString();
|
||||||
|
}
|
||||||
|
}
|
|
@ -17,6 +17,8 @@
|
||||||
|
|
||||||
package org.apache.solr.core;
|
package org.apache.solr.core;
|
||||||
|
|
||||||
|
import org.apache.solr.common.util.DOMUtil;
|
||||||
|
import org.apache.solr.common.util.RegexFileFilter;
|
||||||
import org.apache.solr.common.util.NamedList;
|
import org.apache.solr.common.util.NamedList;
|
||||||
import org.apache.solr.handler.PingRequestHandler;
|
import org.apache.solr.handler.PingRequestHandler;
|
||||||
import org.apache.solr.handler.component.SearchComponent;
|
import org.apache.solr.handler.component.SearchComponent;
|
||||||
|
@ -49,6 +51,7 @@ import javax.xml.xpath.XPathConstants;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
|
import java.io.FileFilter;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
|
||||||
|
@ -125,6 +128,7 @@ public class SolrConfig extends Config {
|
||||||
SolrConfig(SolrResourceLoader loader, String name, InputStream is)
|
SolrConfig(SolrResourceLoader loader, String name, InputStream is)
|
||||||
throws ParserConfigurationException, IOException, SAXException {
|
throws ParserConfigurationException, IOException, SAXException {
|
||||||
super(loader, name, is, "/config/");
|
super(loader, name, is, "/config/");
|
||||||
|
initLibs();
|
||||||
defaultIndexConfig = new SolrIndexConfig(this, null, null);
|
defaultIndexConfig = new SolrIndexConfig(this, null, null);
|
||||||
mainIndexConfig = new SolrIndexConfig(this, "mainIndex", defaultIndexConfig);
|
mainIndexConfig = new SolrIndexConfig(this, "mainIndex", defaultIndexConfig);
|
||||||
reopenReaders = getBool("mainIndex/reopenReaders", true);
|
reopenReaders = getBool("mainIndex/reopenReaders", true);
|
||||||
|
@ -425,4 +429,31 @@ public class SolrConfig extends Config {
|
||||||
List<PluginInfo> result = pluginStore.get(type);
|
List<PluginInfo> result = pluginStore.get(type);
|
||||||
return result == null || result.isEmpty() ? null: result.get(0);
|
return result == null || result.isEmpty() ? null: result.get(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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");
|
||||||
|
|
||||||
|
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) {
|
||||||
|
// :TODO: add support for a simpler 'glob' mutually eclusive of regex
|
||||||
|
String regex = DOMUtil.getAttr(node, "regex");
|
||||||
|
FileFilter filter = (null == regex) ? null : new RegexFileFilter(regex);
|
||||||
|
getResourceLoader().addToClassLoader(baseDir, filter);
|
||||||
|
} else if (null != path) {
|
||||||
|
getResourceLoader().addToClassLoader(path);
|
||||||
|
} else {
|
||||||
|
throw new RuntimeException
|
||||||
|
("lib: missing mandatory attributes: 'dir' or 'path'");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,6 +19,7 @@ package org.apache.solr.core;
|
||||||
|
|
||||||
import java.io.BufferedReader;
|
import java.io.BufferedReader;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.io.FileFilter;
|
||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
@ -42,6 +43,7 @@ import javax.naming.NoInitialContextException;
|
||||||
import org.apache.solr.analysis.CharFilterFactory;
|
import org.apache.solr.analysis.CharFilterFactory;
|
||||||
import org.apache.solr.analysis.TokenFilterFactory;
|
import org.apache.solr.analysis.TokenFilterFactory;
|
||||||
import org.apache.solr.analysis.TokenizerFactory;
|
import org.apache.solr.analysis.TokenizerFactory;
|
||||||
|
import org.apache.solr.common.util.FileUtils;
|
||||||
import org.apache.solr.common.ResourceLoader;
|
import org.apache.solr.common.ResourceLoader;
|
||||||
import org.apache.solr.common.SolrException;
|
import org.apache.solr.common.SolrException;
|
||||||
import org.apache.solr.handler.component.SearchComponent;
|
import org.apache.solr.handler.component.SearchComponent;
|
||||||
|
@ -63,7 +65,7 @@ public class SolrResourceLoader implements ResourceLoader
|
||||||
static final String base = "org.apache" + "." + project;
|
static final String base = "org.apache" + "." + project;
|
||||||
static final String[] packages = {"","analysis.","schema.","handler.","search.","update.","core.","request.","update.processor.","util.", "spelling.", "handler.component.", "handler.dataimport"};
|
static final String[] packages = {"","analysis.","schema.","handler.","search.","update.","core.","request.","update.processor.","util.", "spelling.", "handler.component.", "handler.dataimport"};
|
||||||
|
|
||||||
private final ClassLoader classLoader;
|
private URLClassLoader classLoader;
|
||||||
private final String instanceDir;
|
private final String instanceDir;
|
||||||
private String dataDir;
|
private String dataDir;
|
||||||
|
|
||||||
|
@ -90,7 +92,10 @@ public class SolrResourceLoader implements ResourceLoader
|
||||||
this.instanceDir = normalizeDir(instanceDir);
|
this.instanceDir = normalizeDir(instanceDir);
|
||||||
}
|
}
|
||||||
log.info("Solr home set to '" + this.instanceDir + "'");
|
log.info("Solr home set to '" + this.instanceDir + "'");
|
||||||
this.classLoader = createClassLoader(new File(this.instanceDir + "lib/"), parent);
|
|
||||||
|
this.classLoader = createClassLoader(null, parent);
|
||||||
|
addToClassLoader("./lib/", null);
|
||||||
|
|
||||||
this.coreProperties = coreProperties;
|
this.coreProperties = coreProperties;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -106,28 +111,85 @@ public class SolrResourceLoader implements ResourceLoader
|
||||||
{
|
{
|
||||||
this(instanceDir, parent, null);
|
this(instanceDir, parent, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
static ClassLoader createClassLoader(File f, ClassLoader loader) {
|
|
||||||
if( loader == null ) {
|
|
||||||
loader = Thread.currentThread().getContextClassLoader();
|
|
||||||
}
|
|
||||||
if (f.canRead() && f.isDirectory()) {
|
|
||||||
File[] jarFiles = f.listFiles();
|
|
||||||
URL[] jars = new URL[jarFiles.length];
|
|
||||||
try {
|
|
||||||
for (int j = 0; j < jarFiles.length; j++) {
|
|
||||||
jars[j] = jarFiles[j].toURI().toURL();
|
|
||||||
log.info("Adding '" + jars[j].toString() + "' to Solr classloader");
|
|
||||||
}
|
|
||||||
return URLClassLoader.newInstance(jars, loader);
|
|
||||||
} catch (MalformedURLException e) {
|
|
||||||
SolrException.log(log,"Can't construct solr lib class loader", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
log.info("Reusing parent classloader");
|
|
||||||
return loader;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds every file/dir found in the baseDir which passes the specified Filter
|
||||||
|
* to the ClassLoader used by this ResourceLoader. This method <b>MUST</b>
|
||||||
|
* only be called prior to using this ResourceLoader to get any resources, otherwise
|
||||||
|
* it's behavior will be non-deterministic.
|
||||||
|
*
|
||||||
|
* @param baseDir base directory whose children (either jars or directories of
|
||||||
|
* classes) will be in the classpath, will be resolved relative
|
||||||
|
* the instance dir.
|
||||||
|
* @param filter The filter files must satisfy, if null all files will be accepted.
|
||||||
|
*/
|
||||||
|
void addToClassLoader(final String baseDir, final FileFilter filter) {
|
||||||
|
File base = FileUtils.resolvePath(new File(getInstanceDir()), baseDir);
|
||||||
|
this.classLoader = replaceClassLoader(classLoader, base, filter);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds the specific file/dir specified to the ClassLoader used by this
|
||||||
|
* ResourceLoader. This method <b>MUST</b>
|
||||||
|
* only be called prior to using this ResourceLoader to get any resources, otherwise
|
||||||
|
* it's behavior will be non-deterministic.
|
||||||
|
*
|
||||||
|
* @param path A jar file (or directory of classes) to be added to the classpath,
|
||||||
|
* will be resolved relative the instance dir.
|
||||||
|
*/
|
||||||
|
void addToClassLoader(final String path) {
|
||||||
|
final File file = FileUtils.resolvePath(new File(getInstanceDir()), path);
|
||||||
|
if (file.canRead()) {
|
||||||
|
this.classLoader = replaceClassLoader(classLoader, file.getParentFile(),
|
||||||
|
new FileFilter() {
|
||||||
|
public boolean accept(File pathname) {
|
||||||
|
return pathname.equals(file);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
log.error("Can't find (or read) file to add to classloader: " + file);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static URLClassLoader replaceClassLoader(final URLClassLoader oldLoader,
|
||||||
|
final File base,
|
||||||
|
final FileFilter filter) {
|
||||||
|
if (null != base && base.canRead() && base.isDirectory()) {
|
||||||
|
File[] files = base.listFiles(filter);
|
||||||
|
|
||||||
|
if (null == files || 0 == files.length) return oldLoader;
|
||||||
|
|
||||||
|
URL[] oldElements = oldLoader.getURLs();
|
||||||
|
URL[] elements = new URL[oldElements.length + files.length];
|
||||||
|
System.arraycopy(oldElements, 0, elements, 0, oldElements.length);
|
||||||
|
|
||||||
|
for (int j = 0; j < files.length; j++) {
|
||||||
|
try {
|
||||||
|
URL element = files[j].toURI().normalize().toURL();
|
||||||
|
log.info("Adding '" + element.toString() + "' to classloader");
|
||||||
|
elements[oldElements.length + j] = element;
|
||||||
|
} catch (MalformedURLException e) {
|
||||||
|
SolrException.log(log, "Can't add element to classloader: " + files[j], e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return URLClassLoader.newInstance(elements, oldLoader.getParent());
|
||||||
|
}
|
||||||
|
// are we still here?
|
||||||
|
return oldLoader;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convenience method for getting a new ClassLoader using all files found
|
||||||
|
* in the specified lib directory.
|
||||||
|
*/
|
||||||
|
static URLClassLoader createClassLoader(final File libDir, ClassLoader parent) {
|
||||||
|
if ( null == parent ) {
|
||||||
|
parent = Thread.currentThread().getContextClassLoader();
|
||||||
|
}
|
||||||
|
return replaceClassLoader(URLClassLoader.newInstance(new URL[0], parent),
|
||||||
|
libDir, null);
|
||||||
|
}
|
||||||
|
|
||||||
public SolrResourceLoader( String instanceDir )
|
public SolrResourceLoader( String instanceDir )
|
||||||
{
|
{
|
||||||
this( instanceDir, null, null );
|
this( instanceDir, null, null );
|
||||||
|
@ -553,6 +615,4 @@ public class SolrResourceLoader implements ResourceLoader
|
||||||
}
|
}
|
||||||
throw new SolrException( SolrException.ErrorCode.SERVER_ERROR, builder.toString() );
|
throw new SolrException( SolrException.ErrorCode.SERVER_ERROR, builder.toString() );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,120 +1,146 @@
|
||||||
/**
|
/**
|
||||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
* contributor license agreements. See the NOTICE file distributed with
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
* this work for additional information regarding copyright ownership.
|
* this work for additional information regarding copyright ownership.
|
||||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
* 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 not use this file except in compliance with
|
||||||
* the License. You may obtain a copy of the License at
|
* the License. You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.apache.solr.core;
|
package org.apache.solr.core;
|
||||||
|
|
||||||
import org.apache.lucene.index.IndexWriter;
|
import org.apache.lucene.index.IndexWriter;
|
||||||
import org.apache.solr.handler.admin.ShowFileRequestHandler;
|
import org.apache.solr.handler.admin.ShowFileRequestHandler;
|
||||||
import org.apache.solr.search.SolrIndexReader;
|
import org.apache.solr.search.SolrIndexReader;
|
||||||
import org.apache.solr.search.SolrIndexSearcher;
|
import org.apache.solr.search.SolrIndexSearcher;
|
||||||
import org.apache.solr.update.DirectUpdateHandler2;
|
import org.apache.solr.update.DirectUpdateHandler2;
|
||||||
import org.apache.solr.update.SolrIndexConfig;
|
import org.apache.solr.update.SolrIndexConfig;
|
||||||
import org.apache.solr.util.AbstractSolrTestCase;
|
import org.apache.solr.util.AbstractSolrTestCase;
|
||||||
import org.apache.solr.util.RefCounted;
|
import org.apache.solr.util.RefCounted;
|
||||||
import org.w3c.dom.Node;
|
import org.w3c.dom.Node;
|
||||||
import org.w3c.dom.NodeList;
|
import org.w3c.dom.NodeList;
|
||||||
|
|
||||||
import javax.xml.xpath.XPathConstants;
|
import javax.xml.xpath.XPathConstants;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
public class TestConfig extends AbstractSolrTestCase {
|
|
||||||
|
public class TestConfig extends AbstractSolrTestCase {
|
||||||
public String getSchemaFile() {
|
|
||||||
return "schema.xml";
|
public String getSchemaFile() {
|
||||||
}
|
return "schema.xml";
|
||||||
|
}
|
||||||
//public String getSolrConfigFile() { return "solrconfig.xml"; }
|
|
||||||
public String getSolrConfigFile() {
|
//public String getSolrConfigFile() { return "solrconfig.xml"; }
|
||||||
return "solrconfig-termindex.xml";
|
public String getSolrConfigFile() {
|
||||||
}
|
return "solrconfig-termindex.xml";
|
||||||
|
}
|
||||||
public void testJavaProperty() {
|
|
||||||
// property values defined in build.xml
|
public void testLib() throws IOException {
|
||||||
|
SolrResourceLoader loader = h.getCore().getResourceLoader();
|
||||||
String s = solrConfig.get("propTest");
|
InputStream data = null;
|
||||||
assertEquals("prefix-proptwo-suffix", s);
|
String[] expectedFiles = new String[] { "empty-file-main-lib.txt",
|
||||||
|
"empty-file-a1.txt",
|
||||||
s = solrConfig.get("propTest/@attr1", "default");
|
"empty-file-a2.txt",
|
||||||
assertEquals("propone-${literal}", s);
|
"empty-file-b1.txt",
|
||||||
|
"empty-file-b2.txt",
|
||||||
s = solrConfig.get("propTest/@attr2", "default");
|
"empty-file-c1.txt" };
|
||||||
assertEquals("default-from-config", s);
|
for (String f : expectedFiles) {
|
||||||
|
data = loader.openResource(f);
|
||||||
s = solrConfig.get("propTest[@attr2='default-from-config']", "default");
|
assertNotNull("Should have found file " + f, data);
|
||||||
assertEquals("prefix-proptwo-suffix", s);
|
data.close();
|
||||||
|
}
|
||||||
NodeList nl = (NodeList) solrConfig.evaluate("propTest", XPathConstants.NODESET);
|
String[] unexpectedFiles = new String[] { "empty-file-c2.txt",
|
||||||
assertEquals(1, nl.getLength());
|
"empty-file-d2.txt" };
|
||||||
assertEquals("prefix-proptwo-suffix", nl.item(0).getTextContent());
|
for (String f : unexpectedFiles) {
|
||||||
|
data = null;
|
||||||
Node node = solrConfig.getNode("propTest", true);
|
try {
|
||||||
assertEquals("prefix-proptwo-suffix", node.getTextContent());
|
data = loader.openResource(f);
|
||||||
}
|
} catch (Exception e) { /* :NOOP: (un)expected */ }
|
||||||
|
assertNull("should not have been able to find " + f, data);
|
||||||
public void testLucene23Upgrades() throws Exception {
|
}
|
||||||
double bufferSize = solrConfig.getDouble("indexDefaults/ramBufferSizeMB");
|
}
|
||||||
assertTrue(bufferSize + " does not equal: " + 32, bufferSize == 32);
|
|
||||||
String mergePolicy = solrConfig.get("indexDefaults/mergePolicy/@class");
|
public void testJavaProperty() {
|
||||||
assertTrue(mergePolicy + " is not equal to " + SolrIndexConfig.DEFAULT_MERGE_POLICY_CLASSNAME, mergePolicy.equals(SolrIndexConfig.DEFAULT_MERGE_POLICY_CLASSNAME) == true);
|
// property values defined in build.xml
|
||||||
String mergeSched = solrConfig.get("indexDefaults/mergeScheduler/@class");
|
|
||||||
assertTrue(mergeSched + " is not equal to " + SolrIndexConfig.DEFAULT_MERGE_SCHEDULER_CLASSNAME, mergeSched.equals(SolrIndexConfig.DEFAULT_MERGE_SCHEDULER_CLASSNAME) == true);
|
String s = solrConfig.get("propTest");
|
||||||
boolean luceneAutoCommit = solrConfig.getBool("indexDefaults/luceneAutoCommit");
|
assertEquals("prefix-proptwo-suffix", s);
|
||||||
assertTrue(luceneAutoCommit + " does not equal: " + false, luceneAutoCommit == false);
|
|
||||||
}
|
s = solrConfig.get("propTest/@attr1", "default");
|
||||||
|
assertEquals("propone-${literal}", s);
|
||||||
// sometime if the config referes to old things, it must be replaced with new stuff
|
|
||||||
public void testAutomaticDeprecationSupport() {
|
s = solrConfig.get("propTest/@attr2", "default");
|
||||||
// make sure the "admin/file" handler is registered
|
assertEquals("default-from-config", s);
|
||||||
ShowFileRequestHandler handler = (ShowFileRequestHandler) h.getCore().getRequestHandler("/admin/file");
|
|
||||||
assertTrue("file handler should have been automatically registered", handler != null);
|
s = solrConfig.get("propTest[@attr2='default-from-config']", "default");
|
||||||
|
assertEquals("prefix-proptwo-suffix", s);
|
||||||
//System.out.println( handler.getHiddenFiles() );
|
|
||||||
// should not contain: <gettableFiles>solrconfig.xml scheam.xml admin-extra.html</gettableFiles>
|
NodeList nl = (NodeList) solrConfig.evaluate("propTest", XPathConstants.NODESET);
|
||||||
assertFalse(handler.getHiddenFiles().contains("scheam.xml".toUpperCase()));
|
assertEquals(1, nl.getLength());
|
||||||
assertTrue(handler.getHiddenFiles().contains("PROTWORDS.TXT"));
|
assertEquals("prefix-proptwo-suffix", nl.item(0).getTextContent());
|
||||||
}
|
|
||||||
|
Node node = solrConfig.getNode("propTest", true);
|
||||||
public void testTermIndexInterval() throws Exception {
|
assertEquals("prefix-proptwo-suffix", node.getTextContent());
|
||||||
class ExposeWriterHandler extends DirectUpdateHandler2 {
|
}
|
||||||
public ExposeWriterHandler() throws IOException {
|
|
||||||
super(h.getCore());
|
public void testLucene23Upgrades() throws Exception {
|
||||||
}
|
double bufferSize = solrConfig.getDouble("indexDefaults/ramBufferSizeMB");
|
||||||
|
assertTrue(bufferSize + " does not equal: " + 32, bufferSize == 32);
|
||||||
public IndexWriter getWriter() throws IOException {
|
String mergePolicy = solrConfig.get("indexDefaults/mergePolicy/@class");
|
||||||
forceOpenWriter();
|
assertTrue(mergePolicy + " is not equal to " + SolrIndexConfig.DEFAULT_MERGE_POLICY_CLASSNAME, mergePolicy.equals(SolrIndexConfig.DEFAULT_MERGE_POLICY_CLASSNAME) == true);
|
||||||
return writer;
|
String mergeSched = solrConfig.get("indexDefaults/mergeScheduler/@class");
|
||||||
}
|
assertTrue(mergeSched + " is not equal to " + SolrIndexConfig.DEFAULT_MERGE_SCHEDULER_CLASSNAME, mergeSched.equals(SolrIndexConfig.DEFAULT_MERGE_SCHEDULER_CLASSNAME) == true);
|
||||||
}
|
boolean luceneAutoCommit = solrConfig.getBool("indexDefaults/luceneAutoCommit");
|
||||||
|
assertTrue(luceneAutoCommit + " does not equal: " + false, luceneAutoCommit == false);
|
||||||
IndexWriter writer = new ExposeWriterHandler().getWriter();
|
}
|
||||||
int interval = writer.getTermIndexInterval();
|
|
||||||
assertEquals(256, interval);
|
// sometime if the config referes to old things, it must be replaced with new stuff
|
||||||
}
|
public void testAutomaticDeprecationSupport() {
|
||||||
|
// make sure the "admin/file" handler is registered
|
||||||
public void testTermIndexDivisor() throws Exception {
|
ShowFileRequestHandler handler = (ShowFileRequestHandler) h.getCore().getRequestHandler("/admin/file");
|
||||||
IndexReaderFactory irf = h.getCore().getIndexReaderFactory();
|
assertTrue("file handler should have been automatically registered", handler != null);
|
||||||
StandardIndexReaderFactory sirf = (StandardIndexReaderFactory) irf;
|
|
||||||
assertEquals(12, sirf.termInfosIndexDivisor);
|
//System.out.println( handler.getHiddenFiles() );
|
||||||
RefCounted<SolrIndexSearcher> refCounted = h.getCore().getSearcher();
|
// should not contain: <gettableFiles>solrconfig.xml scheam.xml admin-extra.html</gettableFiles>
|
||||||
SolrIndexReader solrReader = refCounted.get().getReader();
|
assertFalse(handler.getHiddenFiles().contains("scheam.xml".toUpperCase()));
|
||||||
assertEquals(12, solrReader.getTermInfosIndexDivisor());
|
assertTrue(handler.getHiddenFiles().contains("PROTWORDS.TXT"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testTermIndexInterval() throws Exception {
|
||||||
}
|
class ExposeWriterHandler extends DirectUpdateHandler2 {
|
||||||
|
public ExposeWriterHandler() throws IOException {
|
||||||
|
super(h.getCore());
|
||||||
|
}
|
||||||
|
|
||||||
|
public IndexWriter getWriter() throws IOException {
|
||||||
|
forceOpenWriter();
|
||||||
|
return writer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
IndexWriter writer = new ExposeWriterHandler().getWriter();
|
||||||
|
int interval = writer.getTermIndexInterval();
|
||||||
|
assertEquals(256, interval);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testTermIndexDivisor() throws Exception {
|
||||||
|
IndexReaderFactory irf = h.getCore().getIndexReaderFactory();
|
||||||
|
StandardIndexReaderFactory sirf = (StandardIndexReaderFactory) irf;
|
||||||
|
assertEquals(12, sirf.termInfosIndexDivisor);
|
||||||
|
RefCounted<SolrIndexSearcher> refCounted = h.getCore().getSearcher();
|
||||||
|
SolrIndexReader solrReader = refCounted.get().getReader();
|
||||||
|
assertEquals(12, solrReader.getTermInfosIndexDivisor());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,18 @@
|
||||||
|
<!--
|
||||||
|
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.
|
||||||
|
-->
|
||||||
|
|
||||||
|
Items under this directory are used by TestConfig.testLibs()
|
|
@ -0,0 +1 @@
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
|
|
@ -24,6 +24,12 @@
|
||||||
|
|
||||||
<config>
|
<config>
|
||||||
|
|
||||||
|
<!-- see TestConfig.testLib() -->
|
||||||
|
<lib dir="../lib-dirs/a" />
|
||||||
|
<lib dir="../lib-dirs/b" regex="b." />
|
||||||
|
<lib dir="../lib-dirs/c" regex="c1" />
|
||||||
|
<lib path="../lib-dirs/d/d1/" />
|
||||||
|
|
||||||
<jmx />
|
<jmx />
|
||||||
|
|
||||||
<!-- Used to specify an alternate directory to hold all index data.
|
<!-- Used to specify an alternate directory to hold all index data.
|
||||||
|
|
|
@ -0,0 +1,18 @@
|
||||||
|
<!--
|
||||||
|
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.
|
||||||
|
-->
|
||||||
|
|
||||||
|
Items under this directory are used by TestConfig.testLibs()
|
|
@ -0,0 +1 @@
|
||||||
|
|
Loading…
Reference in New Issue