You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucene.apache.org by sa...@apache.org on 2014/03/14 15:05:49 UTC
svn commit: r1577540 - in /lucene/dev/trunk/solr: ./
core/src/java/org/apache/solr/rest/schema/analysis/
core/src/test-files/solr/collection1/conf/
core/src/test/org/apache/solr/rest/
core/src/test/org/apache/solr/rest/schema/analysis/ example/solr/col...
Author: sarowe
Date: Fri Mar 14 14:05:49 2014
New Revision: 1577540
URL: http://svn.apache.org/r1577540
Log:
Create a stopword filter factory that is (re)configurable, and capable of reporting its configuration, via REST API
Added:
lucene/dev/trunk/solr/core/src/java/org/apache/solr/rest/schema/analysis/BaseManagedTokenFilterFactory.java (with props)
lucene/dev/trunk/solr/core/src/java/org/apache/solr/rest/schema/analysis/ManagedStopFilterFactory.java (with props)
lucene/dev/trunk/solr/core/src/test/org/apache/solr/rest/schema/analysis/
lucene/dev/trunk/solr/core/src/test/org/apache/solr/rest/schema/analysis/TestManagedStopFilterFactory.java (with props)
lucene/dev/trunk/solr/example/solr/collection1/conf/_schema_analysis_stopwords_english.json (with props)
Modified:
lucene/dev/trunk/solr/CHANGES.txt
lucene/dev/trunk/solr/core/src/test-files/solr/collection1/conf/schema-rest.xml
lucene/dev/trunk/solr/core/src/test/org/apache/solr/rest/SolrRestletTestBase.java
lucene/dev/trunk/solr/example/solr/collection1/conf/schema.xml
lucene/dev/trunk/solr/test-framework/src/java/org/apache/solr/util/BaseTestHarness.java
lucene/dev/trunk/solr/test-framework/src/java/org/apache/solr/util/RestTestHarness.java
Modified: lucene/dev/trunk/solr/CHANGES.txt
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/CHANGES.txt?rev=1577540&r1=1577539&r2=1577540&view=diff
==============================================================================
--- lucene/dev/trunk/solr/CHANGES.txt (original)
+++ lucene/dev/trunk/solr/CHANGES.txt Fri Mar 14 14:05:49 2014
@@ -119,6 +119,10 @@ New Features
* SOLR-5653: Create a RestManager to provide REST API endpoints for
reconfigurable plugins. (Tim Potter, Steve Rowe)
+* SOLR-5655: Create a stopword filter factory that is (re)configurable,
+ and capable of reporting its configuration, via REST API.
+ (Tim Potter via Steve Rowe)
+
* SOLR-5477: Async execution of OverseerCollectionProcessor(CollectionsAPI)
tasks. (Anshum Gupta)
Added: lucene/dev/trunk/solr/core/src/java/org/apache/solr/rest/schema/analysis/BaseManagedTokenFilterFactory.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/core/src/java/org/apache/solr/rest/schema/analysis/BaseManagedTokenFilterFactory.java?rev=1577540&view=auto
==============================================================================
--- lucene/dev/trunk/solr/core/src/java/org/apache/solr/rest/schema/analysis/BaseManagedTokenFilterFactory.java (added)
+++ lucene/dev/trunk/solr/core/src/java/org/apache/solr/rest/schema/analysis/BaseManagedTokenFilterFactory.java Fri Mar 14 14:05:49 2014
@@ -0,0 +1,82 @@
+package org.apache.solr.rest.schema.analysis;
+/*
+ * 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.util.Map;
+
+import org.apache.lucene.analysis.util.ResourceLoader;
+import org.apache.lucene.analysis.util.ResourceLoaderAware;
+import org.apache.lucene.analysis.util.TokenFilterFactory;
+import org.apache.solr.core.SolrResourceLoader;
+import org.apache.solr.rest.ManagedResource;
+import org.apache.solr.rest.ManagedResourceObserver;
+
+/**
+ * Abstract based class for implementing TokenFilterFactory objects that
+ * are managed by the REST API. Specifically, this base class is useful
+ * for token filters that have configuration and data that needs to be
+ * updated programmatically, such as to support a UI for adding synonyms.
+ */
+public abstract class BaseManagedTokenFilterFactory extends TokenFilterFactory
+ implements ResourceLoaderAware, ManagedResourceObserver
+{
+
+ protected String handle;
+
+ protected BaseManagedTokenFilterFactory(Map<String,String> args) {
+ super(args);
+ handle = require(args, "managed");
+
+ if (!args.isEmpty()) {
+ throw new IllegalArgumentException("Unknown parameters: " + args);
+ }
+ }
+
+ /**
+ * Registers an endpoint with the RestManager so that this component can be
+ * managed using the REST API. This method can be invoked before all the
+ * resources the {@link org.apache.solr.rest.RestManager} needs to initialize
+ * a {@link ManagedResource} are available, so this simply registers the need
+ * to be managed at a specific endpoint and lets the RestManager deal with
+ * initialization when ready.
+ */
+ @Override
+ public void inform(ResourceLoader loader) throws IOException {
+ SolrResourceLoader solrResourceLoader = (SolrResourceLoader)loader;
+
+ // here we want to register that we need to be managed
+ // at a specified path and the ManagedResource impl class
+ // that should be used to manage this component
+ solrResourceLoader.getManagedResourceRegistry().
+ registerManagedResource(getResourceId(), getManagedResourceImplClass(), this);
+ }
+
+ /**
+ * Let the concrete analysis component decide the path it wishes to be managed at.
+ */
+ protected abstract String getResourceId();
+
+ /**
+ * Let the concrete analysis component determine the ManagedResource implementation.
+ * As there can be many instances of the same analysis component in a schema, this
+ * class should not presume to create ManagedResource. For instance, there may be
+ * 10 instances of the ManagedStopFilterFactory that use the same set of English
+ * stop words and we don't want 10 copies of the ManagedWordSetResource in the same core.
+ */
+ protected abstract Class<? extends ManagedResource> getManagedResourceImplClass();
+}
Added: lucene/dev/trunk/solr/core/src/java/org/apache/solr/rest/schema/analysis/ManagedStopFilterFactory.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/core/src/java/org/apache/solr/rest/schema/analysis/ManagedStopFilterFactory.java?rev=1577540&view=auto
==============================================================================
--- lucene/dev/trunk/solr/core/src/java/org/apache/solr/rest/schema/analysis/ManagedStopFilterFactory.java (added)
+++ lucene/dev/trunk/solr/core/src/java/org/apache/solr/rest/schema/analysis/ManagedStopFilterFactory.java Fri Mar 14 14:05:49 2014
@@ -0,0 +1,99 @@
+package org.apache.solr.rest.schema.analysis;
+/*
+ * 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.util.Map;
+import java.util.Set;
+
+import org.apache.lucene.analysis.TokenStream;
+import org.apache.lucene.analysis.core.StopFilter;
+import org.apache.lucene.analysis.util.CharArraySet;
+import org.apache.solr.common.SolrException;
+import org.apache.solr.common.util.NamedList;
+import org.apache.solr.rest.ManagedResource;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * TokenFilterFactory that uses the ManagedWordSetResource implementation
+ * for managing stop words using the REST API.
+ */
+public class ManagedStopFilterFactory extends BaseManagedTokenFilterFactory {
+
+ public static final Logger log = LoggerFactory.getLogger(ManagedStopFilterFactory.class);
+
+ // this only gets changed once during core initialization and not every
+ // time an update is made to the underlying managed word set.
+ private CharArraySet stopWords = null;
+
+ /**
+ * Initialize the managed "handle"
+ */
+ public ManagedStopFilterFactory(Map<String,String> args) {
+ super(args);
+ }
+
+ /**
+ * This analysis component knows the most logical "path"
+ * for which to manage stop words from.
+ */
+ @Override
+ public String getResourceId() {
+ return "/schema/analysis/stopwords/" + handle;
+ }
+
+ /**
+ * Returns the implementation class for managing stop words.
+ */
+ protected Class<? extends ManagedResource> getManagedResourceImplClass() {
+ return ManagedWordSetResource.class;
+ }
+
+ /**
+ * Callback invoked by the {@link ManagedResource} instance to trigger this
+ * class to create the CharArraySet used to create the StopFilter using the
+ * wordset managed by {@link ManagedWordSetResource}. Keep in mind that
+ * a schema.xml may reuse the same {@link ManagedStopFilterFactory} many
+ * times for different field types; behind the scenes all instances of this
+ * class/handle combination share the same managed data, hence the need for
+ * a listener/callback scheme.
+ */
+ @Override
+ public void onManagedResourceInitialized(NamedList<?> args, ManagedResource res)
+ throws SolrException {
+
+ Set<String> managedWords = ((ManagedWordSetResource)res).getWordSet();
+
+ // first thing is to rebuild the Lucene CharArraySet from our managedWords set
+ // which is slightly inefficient to do for every instance of the managed filter
+ // but ManagedResource's don't have access to the luceneMatchVersion
+ boolean ignoreCase = args.getBooleanArg("ignoreCase");
+ stopWords = new CharArraySet(luceneMatchVersion, managedWords.size(), ignoreCase);
+ stopWords.addAll(managedWords);
+ }
+
+ /**
+ * Returns a StopFilter based on our managed stop word set.
+ */
+ @Override
+ public TokenStream create(TokenStream input) {
+ if (stopWords == null) {
+ throw new IllegalStateException("Managed stopwords not initialized correctly!");
+ }
+ return new StopFilter(luceneMatchVersion, input, stopWords);
+ }
+}
Modified: lucene/dev/trunk/solr/core/src/test-files/solr/collection1/conf/schema-rest.xml
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/core/src/test-files/solr/collection1/conf/schema-rest.xml?rev=1577540&r1=1577539&r2=1577540&view=diff
==============================================================================
--- lucene/dev/trunk/solr/core/src/test-files/solr/collection1/conf/schema-rest.xml (original)
+++ lucene/dev/trunk/solr/core/src/test-files/solr/collection1/conf/schema-rest.xml Fri Mar 14 14:05:49 2014
@@ -452,6 +452,14 @@
<!-- A specialized field for geospatial search. If indexed, this fieldType must not be multivalued. -->
<fieldType name="location" class="solr.LatLonType" subFieldSuffix="_coordinate"/>
+ <!-- Field type where stopwords are managed by the REST API -->
+ <fieldtype name="managed_en" class="solr.TextField">
+ <analyzer>
+ <tokenizer class="solr.StandardTokenizerFactory"/>
+ <filter class="solr.ManagedStopFilterFactory" managed="english" />
+ </analyzer>
+ </fieldtype>
+
</types>
Modified: lucene/dev/trunk/solr/core/src/test/org/apache/solr/rest/SolrRestletTestBase.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/core/src/test/org/apache/solr/rest/SolrRestletTestBase.java?rev=1577540&r1=1577539&r2=1577540&view=diff
==============================================================================
--- lucene/dev/trunk/solr/core/src/test/org/apache/solr/rest/SolrRestletTestBase.java (original)
+++ lucene/dev/trunk/solr/core/src/test/org/apache/solr/rest/SolrRestletTestBase.java Fri Mar 14 14:05:49 2014
@@ -25,8 +25,14 @@ import java.util.SortedMap;
import java.util.TreeMap;
/**
- * Base class for Solr Restlet-based tests. Creates test harness,
- * including "extra" servlets for all Solr Restlet Application subclasses.
+ * Base class for Solr Restlet-based tests. Creates jetty and test harness
+ * with solrconfig.xml and schema-rest.xml, including "extra" servlets for
+ * all Solr Restlet Application subclasses.
+ *
+ * Use RestTestBase instead if you need to specialize the solrconfig,
+ * the schema, or jetty/test harness creation; otherwise you'll get
+ * imbalanced SolrIndexSearcher closes/opens and a suite-level failure
+ * for a zombie thread.
*/
abstract public class SolrRestletTestBase extends RestTestBase {
Added: lucene/dev/trunk/solr/core/src/test/org/apache/solr/rest/schema/analysis/TestManagedStopFilterFactory.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/core/src/test/org/apache/solr/rest/schema/analysis/TestManagedStopFilterFactory.java?rev=1577540&view=auto
==============================================================================
--- lucene/dev/trunk/solr/core/src/test/org/apache/solr/rest/schema/analysis/TestManagedStopFilterFactory.java (added)
+++ lucene/dev/trunk/solr/core/src/test/org/apache/solr/rest/schema/analysis/TestManagedStopFilterFactory.java Fri Mar 14 14:05:49 2014
@@ -0,0 +1,191 @@
+package org.apache.solr.rest.schema.analysis;
+/*
+ * 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.File;
+import java.util.Arrays;
+import java.util.SortedMap;
+import java.util.TreeMap;
+
+import org.apache.commons.io.FileUtils;
+import org.apache.solr.util.RestTestBase;
+import org.eclipse.jetty.servlet.ServletHolder;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.noggit.JSONUtil;
+import org.restlet.ext.servlet.ServerServlet;
+
+/**
+ * Test the REST API for managing stop words, which is pretty basic:
+ * GET: returns the list of stop words or a single word if it exists
+ * PUT: add some words to the current list
+ */
+public class TestManagedStopFilterFactory extends RestTestBase {
+ private static File tmpSolrHome;
+ private static File tmpConfDir;
+
+ private static final String collection = "collection1";
+ private static final String confDir = collection + "/conf";
+
+ @Before
+ public void before() throws Exception {
+ createTempDir();
+ tmpSolrHome = new File(TEMP_DIR + File.separator + TestManagedStopFilterFactory.class.getSimpleName()
+ + System.currentTimeMillis());
+ tmpConfDir = new File(tmpSolrHome, confDir);
+ FileUtils.copyDirectory(new File(TEST_HOME()), tmpSolrHome.getAbsoluteFile());
+
+ final SortedMap<ServletHolder,String> extraServlets = new TreeMap<>();
+ final ServletHolder solrRestApi = new ServletHolder("SolrSchemaRestApi", ServerServlet.class);
+ solrRestApi.setInitParameter("org.restlet.application", "org.apache.solr.rest.SolrSchemaRestApi");
+ extraServlets.put(solrRestApi, "/schema/*"); // '/schema/*' matches '/schema', '/schema/', and '/schema/whatever...'
+
+ System.setProperty("managed.schema.mutable", "true");
+ System.setProperty("enable.update.log", "false");
+
+ createJettyAndHarness(tmpSolrHome.getAbsolutePath(), "solrconfig-managed-schema.xml", "schema-rest.xml",
+ "/solr", true, extraServlets);
+ }
+
+ @After
+ private void after() throws Exception {
+ jetty.stop();
+ jetty = null;
+ FileUtils.deleteDirectory(tmpSolrHome);
+ System.clearProperty("managed.schema.mutable");
+ System.clearProperty("enable.update.log");
+ }
+
+
+ /**
+ * Test adding managed stopwords to an endpoint defined in the schema,
+ * then adding docs containing a stopword before and after removing
+ * the stopword from the managed stopwords set.
+ */
+ @Test
+ public void testManagedStopwords() throws Exception {
+ // invalid endpoint
+ //// TODO: This returns HTML vs JSON because the exception is thrown
+ //// from the init method of ManagedEndpoint ... need a better solution
+ // assertJQ("/schema/analysis/stopwords/bogus", "/error/code==404");
+
+ // this endpoint depends on at least one field type containing the following
+ // declaration in the schema-rest.xml:
+ //
+ // <filter class="solr.ManagedStopFilterFactory" managed="english" />
+ //
+ String endpoint = "/schema/analysis/stopwords/english";
+
+ // test the initial GET request returns the default stopwords settings
+ assertJQ(endpoint,
+ "/wordSet/initArgs/ignoreCase==false",
+ "/wordSet/managedList==[]");
+
+ // add some stopwords and verify they were added
+ assertJPut(endpoint,
+ JSONUtil.toJSON(Arrays.asList("a", "an", "the")),
+ "/responseHeader/status==0");
+
+ // test requesting a specific stop word that exists / does not exist
+ assertJQ(endpoint + "/the", "/the=='the'");
+ // not exist - 404
+ assertJQ(endpoint + "/foo", "/error/code==404");
+ // wrong case - 404
+ assertJQ(endpoint + "/An", "/error/code==404");
+
+ // update the ignoreCase initArg to true and make sure case is ignored
+ String updateIgnoreCase =
+ "{ 'initArgs':{ 'ignoreCase':true }, "
+ + "'managedList':['A','a','AN','an','THE','the','of','OF'] }";
+ assertJPut(endpoint, json(updateIgnoreCase), "/responseHeader/status==0");
+
+ assertJQ(endpoint,
+ "/wordSet/initArgs/ignoreCase==true",
+ "/wordSet/managedList==['a','an','of','the']");
+
+ // verify ignoreCase applies when requesting a word
+ assertJQ("/schema/analysis/stopwords/english/The", "/The=='the'");
+
+ // verify the resource supports XML writer type (wt) as well as JSON
+ assertQ(endpoint,
+ "count(/response/lst[@name='wordSet']/arr[@name='managedList']/*) = 4",
+ "(/response/lst[@name='wordSet']/arr[@name='managedList']/str)[1] = 'a'",
+ "(/response/lst[@name='wordSet']/arr[@name='managedList']/str)[2] = 'an'",
+ "(/response/lst[@name='wordSet']/arr[@name='managedList']/str)[3] = 'of'",
+ "(/response/lst[@name='wordSet']/arr[@name='managedList']/str)[4] = 'the'");
+
+ restTestHarness.reload(); // make the word set available
+
+ String newFieldName = "managed_en_field";
+ // make sure the new field doesn't already exist
+ assertQ("/schema/fields/" + newFieldName + "?indent=on&wt=xml",
+ "count(/response/lst[@name='field']) = 0",
+ "/response/lst[@name='responseHeader']/int[@name='status'] = '404'",
+ "/response/lst[@name='error']/int[@name='code'] = '404'");
+
+ // add the new field
+ assertJPut("/schema/fields/" + newFieldName, json("{'type':'managed_en'}"),
+ "/responseHeader/status==0");
+
+ // make sure the new field exists now
+ assertQ("/schema/fields/" + newFieldName + "?indent=on&wt=xml",
+ "count(/response/lst[@name='field']) = 1",
+ "/response/lst[@name='responseHeader']/int[@name='status'] = '0'");
+
+ assertU(adoc(newFieldName, "This is the one", "id", "6"));
+ assertU(commit());
+
+ assertQ("/select?q=" + newFieldName + ":This",
+ "/response/lst[@name='responseHeader']/int[@name='status'] = '0'",
+ "/response/result[@name='response'][@numFound='1']",
+ "/response/result[@name='response']/doc/str[@name='id'][.='6']");
+
+ assertQ("/select?q=%7B%21raw%20f=" + newFieldName + "%7Dthe",
+ "/response/lst[@name='responseHeader']/int[@name='status'] = '0'",
+ "/response/result[@name='response'][@numFound='0']");
+
+ // verify delete works
+ assertJDelete(endpoint + "/the", "/responseHeader/status==0");
+
+ // verify that removing 'the' is not yet in effect
+ assertU(adoc(newFieldName, "This is the other one", "id", "7"));
+ assertU(commit());
+
+ assertQ("/select?q=%7B%21raw%20f=" + newFieldName + "%7Dthe",
+ "/response/lst[@name='responseHeader']/int[@name='status'] = '0'",
+ "/response/result[@name='response'][@numFound='0']");
+
+ restTestHarness.reload();
+
+ // verify that after reloading, removing 'the' has taken effect
+ assertU(adoc(newFieldName, "This is the other other one", "id", "8"));
+ assertU(commit());
+
+ assertQ("/select?q=%7B%21raw%20f=" + newFieldName + "%7Dthe",
+ "/response/lst[@name='responseHeader']/int[@name='status'] = '0'",
+ "/response/result[@name='response'][@numFound='1']",
+ "/response/result[@name='response']/doc/str[@name='id'][.='8']");
+
+ assertJQ(endpoint,
+ "/wordSet/initArgs/ignoreCase==true",
+ "/wordSet/managedList==['a','an','of']");
+
+ // should fail with 404 as foo doesn't exist
+ assertJDelete(endpoint + "/foo", "/error/code==404");
+ }
+}
Added: lucene/dev/trunk/solr/example/solr/collection1/conf/_schema_analysis_stopwords_english.json
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/example/solr/collection1/conf/_schema_analysis_stopwords_english.json?rev=1577540&view=auto
==============================================================================
--- lucene/dev/trunk/solr/example/solr/collection1/conf/_schema_analysis_stopwords_english.json (added)
+++ lucene/dev/trunk/solr/example/solr/collection1/conf/_schema_analysis_stopwords_english.json Fri Mar 14 14:05:49 2014
@@ -0,0 +1,38 @@
+{
+ "initArgs":{"ignoreCase":true},
+ "managedList":[
+ "a",
+ "an",
+ "and",
+ "are",
+ "as",
+ "at",
+ "be",
+ "but",
+ "by",
+ "for",
+ "if",
+ "in",
+ "into",
+ "is",
+ "it",
+ "no",
+ "not",
+ "of",
+ "on",
+ "or",
+ "stopworda",
+ "stopwordb",
+ "such",
+ "that",
+ "the",
+ "their",
+ "then",
+ "there",
+ "these",
+ "they",
+ "this",
+ "to",
+ "was",
+ "will",
+ "with"]}
Modified: lucene/dev/trunk/solr/example/solr/collection1/conf/schema.xml
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/example/solr/collection1/conf/schema.xml?rev=1577540&r1=1577539&r2=1577540&view=diff
==============================================================================
--- lucene/dev/trunk/solr/example/solr/collection1/conf/schema.xml (original)
+++ lucene/dev/trunk/solr/example/solr/collection1/conf/schema.xml Fri Mar 14 14:05:49 2014
@@ -448,6 +448,14 @@
</analyzer>
</fieldType>
+ <!-- A text type for English text where stopwords and synonyms are managed using the REST API -->
+ <fieldType name="managed_en" class="solr.TextField" positionIncrementGap="100">
+ <analyzer>
+ <tokenizer class="solr.StandardTokenizerFactory"/>
+ <filter class="solr.ManagedStopFilterFactory" managed="english" />
+ </analyzer>
+ </fieldType>
+
<!-- A general text field that has reasonable, generic
cross-language defaults: it tokenizes with StandardTokenizer,
removes stop words from case-insensitive "stopwords.txt"
Modified: lucene/dev/trunk/solr/test-framework/src/java/org/apache/solr/util/BaseTestHarness.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/test-framework/src/java/org/apache/solr/util/BaseTestHarness.java?rev=1577540&r1=1577539&r2=1577540&view=diff
==============================================================================
--- lucene/dev/trunk/solr/test-framework/src/java/org/apache/solr/util/BaseTestHarness.java (original)
+++ lucene/dev/trunk/solr/test-framework/src/java/org/apache/solr/util/BaseTestHarness.java Fri Mar 14 14:05:49 2014
@@ -21,6 +21,7 @@ import org.apache.solr.common.util.XML;
import org.w3c.dom.Document;
import org.xml.sax.SAXException;
+import javax.xml.namespace.QName;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.xpath.XPath;
@@ -97,6 +98,24 @@ abstract public class BaseTestHarness {
return null;
}
+ public static Object evaluateXPath(String xml, String xpath, QName returnType)
+ throws XPathExpressionException, SAXException {
+ if (null == xpath) return null;
+
+ Document document = null;
+ try {
+ document = getXmlDocumentBuilder().parse(new ByteArrayInputStream
+ (xml.getBytes("UTF-8")));
+ } catch (UnsupportedEncodingException e1) {
+ throw new RuntimeException("Totally weird UTF-8 exception", e1);
+ } catch (IOException e2) {
+ throw new RuntimeException("Totally weird io exception", e2);
+ }
+
+ xpath = xpath.trim();
+ return getXpath().evaluate(xpath.trim(), document, returnType);
+ }
+
/**
* A helper that creates an xml <doc> containing all of the
* fields and values specified
Modified: lucene/dev/trunk/solr/test-framework/src/java/org/apache/solr/util/RestTestHarness.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/test-framework/src/java/org/apache/solr/util/RestTestHarness.java?rev=1577540&r1=1577539&r2=1577540&view=diff
==============================================================================
--- lucene/dev/trunk/solr/test-framework/src/java/org/apache/solr/util/RestTestHarness.java (original)
+++ lucene/dev/trunk/solr/test-framework/src/java/org/apache/solr/util/RestTestHarness.java Fri Mar 14 14:05:49 2014
@@ -19,6 +19,7 @@ package org.apache.solr.util;
import java.io.IOException;
import java.net.URLEncoder;
+import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpressionException;
import org.apache.http.HttpEntity;
@@ -149,15 +150,22 @@ public class RestTestHarness extends Bas
}
}
-
+
+ /**
+ * Reloads the first core listed in the response to the core admin handler STATUS command
+ */
@Override
public void reload() throws Exception {
- String xml = checkResponseStatus("/admin/cores?action=RELOAD", "0");
+ String coreName = (String)evaluateXPath
+ (query("/admin/cores?action=STATUS"),
+ "//lst[@name='status']/lst[1]/str[@name='name']",
+ XPathConstants.STRING);
+ String xml = checkResponseStatus("/admin/cores?action=RELOAD&core=" + coreName, "0");
if (null != xml) {
throw new RuntimeException("RELOAD failed:\n" + xml);
}
}
-
+
/**
* Processes an "update" (add, commit or optimize) and
* returns the response as a String.