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/12 22:52:51 UTC
svn commit: r1576939 [2/2] - in /lucene/dev/trunk/solr:
core/src/java/org/apache/solr/core/ core/src/java/org/apache/solr/rest/
core/src/java/org/apache/solr/rest/schema/
core/src/java/org/apache/solr/rest/schema/analysis/
core/src/java/org/apache/solr...
Added: lucene/dev/trunk/solr/core/src/java/org/apache/solr/rest/SolrConfigRestApi.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/core/src/java/org/apache/solr/rest/SolrConfigRestApi.java?rev=1576939&view=auto
==============================================================================
--- lucene/dev/trunk/solr/core/src/java/org/apache/solr/rest/SolrConfigRestApi.java (added)
+++ lucene/dev/trunk/solr/core/src/java/org/apache/solr/rest/SolrConfigRestApi.java Wed Mar 12 21:52:49 2014
@@ -0,0 +1,75 @@
+package org.apache.solr.rest;
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import org.apache.solr.request.SolrRequestInfo;
+import org.restlet.Application;
+import org.restlet.Restlet;
+import org.restlet.routing.Router;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.Collections;
+import java.util.Set;
+
+/**
+ * Restlet servlet handling /<context>/<collection>/config/* URL paths
+ */
+public class SolrConfigRestApi extends Application {
+ public static final Logger log = LoggerFactory.getLogger(SolrConfigRestApi.class);
+
+ private Router router;
+
+ public SolrConfigRestApi() {
+ router = new Router(getContext());
+ }
+
+ /**
+ * TODO: If and when this API has reserved endpoints, add them to the set returned here.
+ * @see SolrSchemaRestApi#getReservedEndpoints()
+ */
+ public static Set<String> getReservedEndpoints() {
+ return Collections.emptySet();
+ }
+
+ @Override
+ public void stop() throws Exception {
+ if (null != router) {
+ router.stop();
+ }
+ }
+
+ /**
+ * Bind URL paths to the appropriate ServerResource subclass.
+ */
+ @Override
+ public synchronized Restlet createInboundRoot() {
+
+ log.info("createInboundRoot started for /config");
+
+ router.attachDefault(RestManager.ManagedEndpoint.class);
+
+ // attach all the dynamically registered /config resources
+ RestManager restManager =
+ RestManager.getRestManager(SolrRequestInfo.getRequestInfo());
+ restManager.attachManagedResources(RestManager.CONFIG_BASE_PATH, router);
+
+ log.info("createInboundRoot complete for /config");
+
+ return router;
+ }
+}
Copied: lucene/dev/trunk/solr/core/src/java/org/apache/solr/rest/SolrSchemaRestApi.java (from r1574954, lucene/dev/trunk/solr/core/src/java/org/apache/solr/rest/SolrRestApi.java)
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/core/src/java/org/apache/solr/rest/SolrSchemaRestApi.java?p2=lucene/dev/trunk/solr/core/src/java/org/apache/solr/rest/SolrSchemaRestApi.java&p1=lucene/dev/trunk/solr/core/src/java/org/apache/solr/rest/SolrRestApi.java&r1=1574954&r2=1576939&rev=1576939&view=diff
==============================================================================
--- lucene/dev/trunk/solr/core/src/java/org/apache/solr/rest/SolrRestApi.java (original)
+++ lucene/dev/trunk/solr/core/src/java/org/apache/solr/rest/SolrSchemaRestApi.java Wed Mar 12 21:52:49 2014
@@ -16,8 +16,8 @@ package org.apache.solr.rest;
* limitations under the License.
*/
+import org.apache.solr.request.SolrRequestInfo;
import org.apache.solr.rest.schema.CopyFieldCollectionResource;
-import org.apache.solr.rest.schema.DefaultSchemaResource;
import org.apache.solr.rest.schema.SchemaResource;
import org.apache.solr.rest.schema.DefaultSearchFieldResource;
import org.apache.solr.rest.schema.DynamicFieldCollectionResource;
@@ -39,10 +39,16 @@ import org.restlet.routing.Router;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import java.util.Collections;
+import java.util.HashSet;
import java.util.Locale;
+import java.util.Set;
-public class SolrRestApi extends Application {
- public static final Logger log = LoggerFactory.getLogger(SolrRestApi.class);
+/**
+ * Restlet servlet handling /<context>/<collection>/schema/* URL paths
+ */
+public class SolrSchemaRestApi extends Application {
+ public static final Logger log = LoggerFactory.getLogger(SolrSchemaRestApi.class);
public static final String FIELDS_PATH = "/" + IndexSchema.FIELDS;
public static final String DYNAMIC_FIELDS = IndexSchema.DYNAMIC_FIELDS.toLowerCase(Locale.ROOT);
@@ -73,9 +79,28 @@ public class SolrRestApi extends Applica
public static final String UNIQUE_KEY_FIELD = IndexSchema.UNIQUE_KEY.toLowerCase(Locale.ROOT);
public static final String UNIQUE_KEY_FIELD_PATH = "/" + UNIQUE_KEY_FIELD;
+ /**
+ * Returns reserved endpoints under /schema
+ */
+ public static Set<String> getReservedEndpoints() {
+ Set<String> reservedEndpoints = new HashSet<>();
+ reservedEndpoints.add(RestManager.SCHEMA_BASE_PATH + FIELDS_PATH);
+ reservedEndpoints.add(RestManager.SCHEMA_BASE_PATH + DYNAMIC_FIELDS_PATH);
+ reservedEndpoints.add(RestManager.SCHEMA_BASE_PATH + FIELDTYPES_PATH);
+ reservedEndpoints.add(RestManager.SCHEMA_BASE_PATH + NAME_PATH);
+ reservedEndpoints.add(RestManager.SCHEMA_BASE_PATH + COPY_FIELDS_PATH);
+ reservedEndpoints.add(RestManager.SCHEMA_BASE_PATH + VERSION_PATH);
+ reservedEndpoints.add(RestManager.SCHEMA_BASE_PATH + DEFAULT_SEARCH_FIELD_PATH);
+ reservedEndpoints.add(RestManager.SCHEMA_BASE_PATH + SIMILARITY_PATH);
+ reservedEndpoints.add(RestManager.SCHEMA_BASE_PATH + SOLR_QUERY_PARSER_PATH);
+ reservedEndpoints.add(RestManager.SCHEMA_BASE_PATH + DEFAULT_OPERATOR_PATH);
+ reservedEndpoints.add(RestManager.SCHEMA_BASE_PATH + UNIQUE_KEY_FIELD_PATH);
+ return Collections.unmodifiableSet(reservedEndpoints);
+ }
+
private Router router;
- public SolrRestApi() {
+ public SolrSchemaRestApi() {
router = new Router(getContext());
}
@@ -92,8 +117,8 @@ public class SolrRestApi extends Applica
@Override
public synchronized Restlet createInboundRoot() {
- log.info("createInboundRoot started");
-
+ log.info("createInboundRoot started for /schema");
+
router.attach("", SchemaResource.class);
// Allow a trailing slash on full-schema requests
router.attach("/", SchemaResource.class);
@@ -131,10 +156,14 @@ public class SolrRestApi extends Applica
router.attach(SOLR_QUERY_PARSER_PATH, SolrQueryParserResource.class);
router.attach(DEFAULT_OPERATOR_PATH, SolrQueryParserDefaultOperatorResource.class);
- router.attachDefault(DefaultSchemaResource.class);
+ router.attachDefault(RestManager.ManagedEndpoint.class);
+
+ // attach all the dynamically registered schema resources
+ RestManager.getRestManager(SolrRequestInfo.getRequestInfo())
+ .attachManagedResources(RestManager.SCHEMA_BASE_PATH, router);
- log.info("createInboundRoot complete");
+ log.info("createInboundRoot complete for /schema");
return router;
- }
+ }
}
Modified: lucene/dev/trunk/solr/core/src/java/org/apache/solr/rest/schema/BaseFieldResource.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/core/src/java/org/apache/solr/rest/schema/BaseFieldResource.java?rev=1576939&r1=1576938&r2=1576939&view=diff
==============================================================================
--- lucene/dev/trunk/solr/core/src/java/org/apache/solr/rest/schema/BaseFieldResource.java (original)
+++ lucene/dev/trunk/solr/core/src/java/org/apache/solr/rest/schema/BaseFieldResource.java Wed Mar 12 21:52:49 2014
@@ -18,6 +18,7 @@ package org.apache.solr.rest.schema;
import org.apache.solr.common.params.CommonParams;
import org.apache.solr.common.util.SimpleOrderedMap;
+import org.apache.solr.rest.BaseSolrResource;
import org.apache.solr.schema.IndexSchema;
import org.apache.solr.schema.SchemaField;
import org.restlet.resource.ResourceException;
@@ -28,7 +29,7 @@ import java.util.LinkedHashSet;
/**
* Base class for Schema Field and DynamicField requests.
*/
-abstract class BaseFieldResource extends BaseSchemaResource {
+abstract class BaseFieldResource extends BaseSolrResource {
protected static final String INCLUDE_DYNAMIC_PARAM = "includeDynamic";
private static final String DYNAMIC_BASE = "dynamicBase";
Modified: lucene/dev/trunk/solr/core/src/java/org/apache/solr/rest/schema/BaseFieldTypeResource.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/core/src/java/org/apache/solr/rest/schema/BaseFieldTypeResource.java?rev=1576939&r1=1576938&r2=1576939&view=diff
==============================================================================
--- lucene/dev/trunk/solr/core/src/java/org/apache/solr/rest/schema/BaseFieldTypeResource.java (original)
+++ lucene/dev/trunk/solr/core/src/java/org/apache/solr/rest/schema/BaseFieldTypeResource.java Wed Mar 12 21:52:49 2014
@@ -18,6 +18,7 @@ package org.apache.solr.rest.schema;
*/
import org.apache.solr.common.util.SimpleOrderedMap;
+import org.apache.solr.rest.BaseSolrResource;
import org.apache.solr.schema.FieldType;
import org.apache.solr.schema.IndexSchema;
import org.restlet.resource.ResourceException;
@@ -27,7 +28,7 @@ import java.util.List;
/**
* Base class for the FieldType resource classes.
*/
-abstract class BaseFieldTypeResource extends BaseSchemaResource {
+abstract class BaseFieldTypeResource extends BaseSolrResource {
private boolean showDefaults;
protected BaseFieldTypeResource() {
Modified: lucene/dev/trunk/solr/core/src/java/org/apache/solr/rest/schema/DefaultSearchFieldResource.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/core/src/java/org/apache/solr/rest/schema/DefaultSearchFieldResource.java?rev=1576939&r1=1576938&r2=1576939&view=diff
==============================================================================
--- lucene/dev/trunk/solr/core/src/java/org/apache/solr/rest/schema/DefaultSearchFieldResource.java (original)
+++ lucene/dev/trunk/solr/core/src/java/org/apache/solr/rest/schema/DefaultSearchFieldResource.java Wed Mar 12 21:52:49 2014
@@ -18,6 +18,7 @@ package org.apache.solr.rest.schema;
import org.apache.solr.common.SolrException;
import org.apache.solr.common.SolrException.ErrorCode;
+import org.apache.solr.rest.BaseSolrResource;
import org.apache.solr.rest.GETable;
import org.apache.solr.schema.IndexSchema;
import org.restlet.representation.Representation;
@@ -29,7 +30,7 @@ import org.slf4j.LoggerFactory;
/**
* This class responds to requests at /solr/(corename)/schema/defaultsearchfield
*/
-public class DefaultSearchFieldResource extends BaseSchemaResource implements GETable {
+public class DefaultSearchFieldResource extends BaseSolrResource implements GETable {
private static final Logger log = LoggerFactory.getLogger(DefaultSearchFieldResource.class);
public DefaultSearchFieldResource() {
Modified: lucene/dev/trunk/solr/core/src/java/org/apache/solr/rest/schema/SchemaNameResource.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/core/src/java/org/apache/solr/rest/schema/SchemaNameResource.java?rev=1576939&r1=1576938&r2=1576939&view=diff
==============================================================================
--- lucene/dev/trunk/solr/core/src/java/org/apache/solr/rest/schema/SchemaNameResource.java (original)
+++ lucene/dev/trunk/solr/core/src/java/org/apache/solr/rest/schema/SchemaNameResource.java Wed Mar 12 21:52:49 2014
@@ -17,6 +17,7 @@ package org.apache.solr.rest.schema;
*/
import org.apache.solr.common.SolrException;
+import org.apache.solr.rest.BaseSolrResource;
import org.apache.solr.rest.GETable;
import org.apache.solr.schema.IndexSchema;
import org.restlet.representation.Representation;
@@ -28,7 +29,7 @@ import org.slf4j.LoggerFactory;
/**
* This class responds to requests at /solr/(corename)/schema/name
*/
-public class SchemaNameResource extends BaseSchemaResource implements GETable {
+public class SchemaNameResource extends BaseSolrResource implements GETable {
private static final Logger log = LoggerFactory.getLogger(SchemaNameResource.class);
public SchemaNameResource() {
Modified: lucene/dev/trunk/solr/core/src/java/org/apache/solr/rest/schema/SchemaResource.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/core/src/java/org/apache/solr/rest/schema/SchemaResource.java?rev=1576939&r1=1576938&r2=1576939&view=diff
==============================================================================
--- lucene/dev/trunk/solr/core/src/java/org/apache/solr/rest/schema/SchemaResource.java (original)
+++ lucene/dev/trunk/solr/core/src/java/org/apache/solr/rest/schema/SchemaResource.java Wed Mar 12 21:52:49 2014
@@ -16,6 +16,7 @@ package org.apache.solr.rest.schema;
* limitations under the License.
*/
+import org.apache.solr.rest.BaseSolrResource;
import org.apache.solr.rest.GETable;
import org.apache.solr.schema.IndexSchema;
import org.restlet.representation.Representation;
@@ -26,7 +27,7 @@ import org.slf4j.LoggerFactory;
/**
* This class responds to requests at /solr/(corename)/schema
*/
-public class SchemaResource extends BaseSchemaResource implements GETable {
+public class SchemaResource extends BaseSolrResource implements GETable {
private static final Logger log = LoggerFactory.getLogger(SchemaResource.class);
public SchemaResource() {
Modified: lucene/dev/trunk/solr/core/src/java/org/apache/solr/rest/schema/SchemaSimilarityResource.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/core/src/java/org/apache/solr/rest/schema/SchemaSimilarityResource.java?rev=1576939&r1=1576938&r2=1576939&view=diff
==============================================================================
--- lucene/dev/trunk/solr/core/src/java/org/apache/solr/rest/schema/SchemaSimilarityResource.java (original)
+++ lucene/dev/trunk/solr/core/src/java/org/apache/solr/rest/schema/SchemaSimilarityResource.java Wed Mar 12 21:52:49 2014
@@ -16,8 +16,8 @@ package org.apache.solr.rest.schema;
* limitations under the License.
*/
+import org.apache.solr.rest.BaseSolrResource;
import org.apache.solr.rest.GETable;
-import org.apache.solr.rest.SolrRestApi;
import org.apache.solr.schema.IndexSchema;
import org.restlet.representation.Representation;
import org.restlet.resource.ResourceException;
@@ -28,7 +28,7 @@ import org.slf4j.LoggerFactory;
/**
* This class responds to requests at /solr/(corename)/schema/similarity
*/
-public class SchemaSimilarityResource extends BaseSchemaResource implements GETable {
+public class SchemaSimilarityResource extends BaseSolrResource implements GETable {
private static final Logger log = LoggerFactory.getLogger(SchemaSimilarityResource.class);
public SchemaSimilarityResource() {
Modified: lucene/dev/trunk/solr/core/src/java/org/apache/solr/rest/schema/SchemaVersionResource.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/core/src/java/org/apache/solr/rest/schema/SchemaVersionResource.java?rev=1576939&r1=1576938&r2=1576939&view=diff
==============================================================================
--- lucene/dev/trunk/solr/core/src/java/org/apache/solr/rest/schema/SchemaVersionResource.java (original)
+++ lucene/dev/trunk/solr/core/src/java/org/apache/solr/rest/schema/SchemaVersionResource.java Wed Mar 12 21:52:49 2014
@@ -16,8 +16,8 @@ package org.apache.solr.rest.schema;
* limitations under the License.
*/
+import org.apache.solr.rest.BaseSolrResource;
import org.apache.solr.rest.GETable;
-import org.apache.solr.rest.SolrRestApi;
import org.apache.solr.schema.IndexSchema;
import org.restlet.representation.Representation;
import org.restlet.resource.ResourceException;
@@ -28,7 +28,7 @@ import org.slf4j.LoggerFactory;
/**
* This class responds to requests at /solr/(corename)/schema/version
*/
-public class SchemaVersionResource extends BaseSchemaResource implements GETable {
+public class SchemaVersionResource extends BaseSolrResource implements GETable {
private static final Logger log = LoggerFactory.getLogger(SchemaVersionResource.class);
public SchemaVersionResource() {
Modified: lucene/dev/trunk/solr/core/src/java/org/apache/solr/rest/schema/SolrQueryParserDefaultOperatorResource.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/core/src/java/org/apache/solr/rest/schema/SolrQueryParserDefaultOperatorResource.java?rev=1576939&r1=1576938&r2=1576939&view=diff
==============================================================================
--- lucene/dev/trunk/solr/core/src/java/org/apache/solr/rest/schema/SolrQueryParserDefaultOperatorResource.java (original)
+++ lucene/dev/trunk/solr/core/src/java/org/apache/solr/rest/schema/SolrQueryParserDefaultOperatorResource.java Wed Mar 12 21:52:49 2014
@@ -16,6 +16,7 @@ package org.apache.solr.rest.schema;
* limitations under the License.
*/
+import org.apache.solr.rest.BaseSolrResource;
import org.apache.solr.rest.GETable;
import org.apache.solr.schema.IndexSchema;
import org.restlet.representation.Representation;
@@ -27,7 +28,7 @@ import org.slf4j.LoggerFactory;
/**
* This class responds to requests at /solr/(corename)/schema/solrqueryparser/defaultoperator
*/
-public class SolrQueryParserDefaultOperatorResource extends BaseSchemaResource implements GETable {
+public class SolrQueryParserDefaultOperatorResource extends BaseSolrResource implements GETable {
private static final Logger log = LoggerFactory.getLogger(SolrQueryParserDefaultOperatorResource.class);
public SolrQueryParserDefaultOperatorResource() {
Modified: lucene/dev/trunk/solr/core/src/java/org/apache/solr/rest/schema/SolrQueryParserResource.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/core/src/java/org/apache/solr/rest/schema/SolrQueryParserResource.java?rev=1576939&r1=1576938&r2=1576939&view=diff
==============================================================================
--- lucene/dev/trunk/solr/core/src/java/org/apache/solr/rest/schema/SolrQueryParserResource.java (original)
+++ lucene/dev/trunk/solr/core/src/java/org/apache/solr/rest/schema/SolrQueryParserResource.java Wed Mar 12 21:52:49 2014
@@ -17,6 +17,7 @@ package org.apache.solr.rest.schema;
*/
import org.apache.solr.common.util.SimpleOrderedMap;
+import org.apache.solr.rest.BaseSolrResource;
import org.apache.solr.rest.GETable;
import org.apache.solr.schema.IndexSchema;
import org.restlet.representation.Representation;
@@ -28,7 +29,7 @@ import org.slf4j.LoggerFactory;
/**
* This class responds to requests at /solr/(corename)/schema/solrqueryparser
*/
-public class SolrQueryParserResource extends BaseSchemaResource implements GETable {
+public class SolrQueryParserResource extends BaseSolrResource implements GETable {
private static final Logger log = LoggerFactory.getLogger(SolrQueryParserResource.class);
public SolrQueryParserResource() {
Modified: lucene/dev/trunk/solr/core/src/java/org/apache/solr/rest/schema/UniqueKeyFieldResource.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/core/src/java/org/apache/solr/rest/schema/UniqueKeyFieldResource.java?rev=1576939&r1=1576938&r2=1576939&view=diff
==============================================================================
--- lucene/dev/trunk/solr/core/src/java/org/apache/solr/rest/schema/UniqueKeyFieldResource.java (original)
+++ lucene/dev/trunk/solr/core/src/java/org/apache/solr/rest/schema/UniqueKeyFieldResource.java Wed Mar 12 21:52:49 2014
@@ -16,6 +16,7 @@ package org.apache.solr.rest.schema;
* limitations under the License.
*/
+import org.apache.solr.rest.BaseSolrResource;
import org.apache.solr.rest.GETable;
import org.apache.solr.schema.IndexSchema;
import org.restlet.representation.Representation;
@@ -27,7 +28,7 @@ import org.slf4j.LoggerFactory;
/**
* This class responds to requests at /solr/(corename)/schema/uniquekey
*/
-public class UniqueKeyFieldResource extends BaseSchemaResource implements GETable {
+public class UniqueKeyFieldResource extends BaseSolrResource implements GETable {
private static final Logger log = LoggerFactory.getLogger(UniqueKeyFieldResource.class);
public UniqueKeyFieldResource() {
Added: lucene/dev/trunk/solr/core/src/java/org/apache/solr/rest/schema/analysis/ManagedWordSetResource.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/core/src/java/org/apache/solr/rest/schema/analysis/ManagedWordSetResource.java?rev=1576939&view=auto
==============================================================================
--- lucene/dev/trunk/solr/core/src/java/org/apache/solr/rest/schema/analysis/ManagedWordSetResource.java (added)
+++ lucene/dev/trunk/solr/core/src/java/org/apache/solr/rest/schema/analysis/ManagedWordSetResource.java Wed Mar 12 21:52:49 2014
@@ -0,0 +1,193 @@
+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.Collections;
+import java.util.List;
+import java.util.Locale;
+import java.util.Set;
+import java.util.SortedSet;
+import java.util.TreeSet;
+
+import org.apache.solr.common.SolrException;
+import org.apache.solr.common.SolrException.ErrorCode;
+import org.apache.solr.common.util.NamedList;
+import org.apache.solr.core.SolrResourceLoader;
+import org.apache.solr.response.SolrQueryResponse;
+import org.apache.solr.rest.BaseSolrResource;
+import org.apache.solr.rest.ManagedResource;
+import org.apache.solr.rest.ManagedResourceStorage.StorageIO;
+
+/**
+ * ManagedResource implementation for managing a set of words using the REST API;
+ * useful for managing stop words and/or protected words for analysis components
+ * like the KeywordMarkerFilter.
+ */
+public class ManagedWordSetResource extends ManagedResource
+ implements ManagedResource.ChildResourceSupport {
+
+ public static final String WORD_SET_JSON_FIELD = "wordSet";
+ public static final String IGNORE_CASE_INIT_ARG = "ignoreCase";
+
+ private SortedSet<String> managedWords = null;
+
+ public ManagedWordSetResource(String resourceId, SolrResourceLoader loader, StorageIO storageIO)
+ throws SolrException {
+ super(resourceId, loader, storageIO);
+ }
+
+ /**
+ * Returns the set of words in this managed word set.
+ */
+ public Set<String> getWordSet() {
+ return Collections.unmodifiableSet(managedWords);
+ }
+
+ /**
+ * Returns the boolean value of the {@link #IGNORE_CASE_INIT_ARG} init arg,
+ * or the default value (false) if it has not been specified
+ */
+ public boolean getIgnoreCase() {
+ return getIgnoreCase(managedInitArgs);
+ }
+
+ /**
+ * Returns the boolean value of the {@link #IGNORE_CASE_INIT_ARG} init arg,
+ * or the default value (false) if it has not been specified
+ */
+ public boolean getIgnoreCase(NamedList<?> initArgs) {
+ Boolean ignoreCase = initArgs.getBooleanArg(IGNORE_CASE_INIT_ARG);
+ // ignoreCase = false by default
+ return null == ignoreCase ? false : ignoreCase;
+ }
+
+ /**
+ * Invoked when loading data from storage to initialize the
+ * list of words managed by this instance. A load of the
+ * data can happen many times throughout the life cycle of this
+ * object.
+ */
+ @SuppressWarnings("unchecked")
+ @Override
+ protected void onManagedDataLoadedFromStorage(NamedList<?> initArgs, Object data)
+ throws SolrException {
+
+ // the default behavior is to not ignore case,
+ boolean ignoreCase = getIgnoreCase(initArgs);
+ if (null == initArgs.get(IGNORE_CASE_INIT_ARG)) {
+ // Explicitly include the default value of ignoreCase
+ ((NamedList<Object>)initArgs).add(IGNORE_CASE_INIT_ARG, false);
+ }
+
+ managedWords = new TreeSet<>();
+ if (data != null) {
+ List<String> wordList = (List<String>)data;
+ if (ignoreCase) {
+ // if we're ignoring case, just lowercase all terms as we add them
+ for (String word : wordList) {
+ managedWords.add(word.toLowerCase(Locale.ROOT));
+ }
+ } else {
+ managedWords.addAll(wordList);
+ }
+ }
+
+ log.info("Loaded "+managedWords.size()+" words for "+getResourceId());
+ }
+
+ /**
+ * Implements the GET request to provide the list of words to the client.
+ * Alternatively, if a specific word is requested, then it is returned
+ * or a 404 is raised, indicating that the requested word does not exist.
+ */
+ @Override
+ public void doGet(BaseSolrResource endpoint, String childId) {
+ SolrQueryResponse response = endpoint.getSolrResponse();
+ if (childId != null) {
+ // downcase arg if we're configured to ignoreCase
+ String key = getIgnoreCase() ? childId.toLowerCase(Locale.ROOT) : childId;
+ if (!managedWords.contains(key))
+ throw new SolrException(ErrorCode.NOT_FOUND,
+ String.format(Locale.ROOT, "%s not found in %s", childId, getResourceId()));
+
+ response.add(childId, key);
+ } else {
+ response.add(WORD_SET_JSON_FIELD, buildMapToStore(managedWords));
+ }
+ }
+
+ /**
+ * Deletes words managed by this resource.
+ */
+ @Override
+ public synchronized void doDeleteChild(BaseSolrResource endpoint, String childId) {
+ // downcase arg if we're configured to ignoreCase
+ String key = getIgnoreCase() ? childId.toLowerCase(Locale.ROOT) : childId;
+ if (!managedWords.contains(key))
+ throw new SolrException(ErrorCode.NOT_FOUND,
+ String.format(Locale.ROOT, "%s not found in %s", childId, getResourceId()));
+
+ managedWords.remove(key);
+ storeManagedData(managedWords);
+ log.info("Removed word: {}", key);
+ }
+
+ /**
+ * Applies updates to the word set being managed by this resource.
+ */
+ @SuppressWarnings("unchecked")
+ @Override
+ protected Object applyUpdatesToManagedData(Object updates) {
+ boolean madeChanges = false;
+ List<String> words = (List<String>)updates;
+
+ log.info("Applying updates: "+words);
+ boolean ignoreCase = getIgnoreCase();
+ for (String word : words) {
+ if (ignoreCase)
+ word = word.toLowerCase(Locale.ROOT);
+
+ if (managedWords.add(word)) {
+ madeChanges = true;
+ log.info("Added word: {}", word);
+ }
+ }
+ return madeChanges ? managedWords : null;
+ }
+
+ @Override
+ protected boolean updateInitArgs(NamedList<?> updatedArgs) {
+ if (updatedArgs == null || updatedArgs.size() == 0) {
+ return false;
+ }
+ boolean currentIgnoreCase = getIgnoreCase(managedInitArgs);
+ boolean updatedIgnoreCase = getIgnoreCase(updatedArgs);
+ if (currentIgnoreCase == true && updatedIgnoreCase == false) {
+ throw new SolrException(ErrorCode.BAD_REQUEST,
+ "Changing a managed word set's ignoreCase arg from true to false is not permitted.");
+ } else if (currentIgnoreCase == false && updatedIgnoreCase == true) {
+ // rebuild the word set on policy change from case-sensitive to case-insensitive
+ SortedSet<String> updatedWords = new TreeSet<>();
+ for (String word : managedWords) {
+ updatedWords.add(word.toLowerCase(Locale.ROOT));
+ }
+ managedWords = updatedWords;
+ }
+ // otherwise currentIgnoreCase == updatedIgnoreCase: nothing to do
+ return super.updateInitArgs(updatedArgs);
+ }
+}
Added: lucene/dev/trunk/solr/core/src/java/org/apache/solr/rest/schema/analysis/package.html
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/core/src/java/org/apache/solr/rest/schema/analysis/package.html?rev=1576939&view=auto
==============================================================================
--- lucene/dev/trunk/solr/core/src/java/org/apache/solr/rest/schema/analysis/package.html (added)
+++ lucene/dev/trunk/solr/core/src/java/org/apache/solr/rest/schema/analysis/package.html Wed Mar 12 21:52:49 2014
@@ -0,0 +1,29 @@
+<!doctype html public "-//w3c//dtd html 4.0 transitional//en">
+<!--
+ 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.
+ -->
+
+<!doctype html public "-//w3c//dtd html 4.0 transitional//en">
+<html>
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+</head>
+<body>
+<p>
+ Analysis-related functionality for RESTful API access to the Solr Schema using Restlet.
+</p>
+</body>
+</html>
Modified: lucene/dev/trunk/solr/core/src/java/org/apache/solr/servlet/SolrDispatchFilter.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/core/src/java/org/apache/solr/servlet/SolrDispatchFilter.java?rev=1576939&r1=1576938&r2=1576939&view=diff
==============================================================================
--- lucene/dev/trunk/solr/core/src/java/org/apache/solr/servlet/SolrDispatchFilter.java (original)
+++ lucene/dev/trunk/solr/core/src/java/org/apache/solr/servlet/SolrDispatchFilter.java Wed Mar 12 21:52:49 2014
@@ -20,6 +20,7 @@ package org.apache.solr.servlet;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.http.client.HttpClient;
+import org.apache.http.client.methods.HttpDelete;
import org.apache.http.client.methods.HttpEntityEnclosingRequestBase;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpHead;
@@ -364,8 +365,9 @@ public class SolrDispatchFilter implemen
// get or create/cache the parser for the core
SolrRequestParsers parser = config.getRequestParsers();
- // Handle /schema/* paths via Restlet
- if( path.startsWith("/schema") ) {
+ // Handle /schema/* and /config/* paths via Restlet
+ if( path.equals("/schema") || path.startsWith("/schema/")
+ || path.equals("/config") || path.startsWith("/config/")) {
solrReq = parser.parse(core, path, req);
SolrRequestInfo.setRequestInfo(new SolrRequestInfo(solrReq, new SolrQueryResponse()));
if( path.equals(req.getServletPath()) ) {
@@ -536,6 +538,9 @@ public class SolrDispatchFilter implemen
entityRequest.setEntity(entity);
method = entityRequest;
}
+ else if ("DELETE".equals(req.getMethod())) {
+ method = new HttpDelete(urlstr);
+ }
else {
throw new SolrException(SolrException.ErrorCode.SERVER_ERROR,
"Unexpected method type: " + req.getMethod());
Modified: lucene/dev/trunk/solr/core/src/java/org/apache/solr/servlet/SolrRequestParsers.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/core/src/java/org/apache/solr/servlet/SolrRequestParsers.java?rev=1576939&r1=1576938&r2=1576939&view=diff
==============================================================================
--- lucene/dev/trunk/solr/core/src/java/org/apache/solr/servlet/SolrRequestParsers.java (original)
+++ lucene/dev/trunk/solr/core/src/java/org/apache/solr/servlet/SolrRequestParsers.java Wed Mar 12 21:52:49 2014
@@ -665,7 +665,9 @@ public class SolrRequestParsers
{
String method = req.getMethod().toUpperCase(Locale.ROOT);
if ("GET".equals(method) || "HEAD".equals(method)
- || ("PUT".equals(method) && req.getRequestURI().contains("/schema"))) {
+ || (("PUT".equals(method) || "DELETE".equals(method))
+ && (req.getRequestURI().contains("/schema")
+ || req.getRequestURI().contains("/config")))) {
return parseQueryString(req.getQueryString());
}
if ("POST".equals( method ) ) {
Modified: lucene/dev/trunk/solr/core/src/test-files/solr/collection1/conf/solrconfig.xml
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/core/src/test-files/solr/collection1/conf/solrconfig.xml?rev=1576939&r1=1576938&r2=1576939&view=diff
==============================================================================
--- lucene/dev/trunk/solr/core/src/test-files/solr/collection1/conf/solrconfig.xml (original)
+++ lucene/dev/trunk/solr/core/src/test-files/solr/collection1/conf/solrconfig.xml Wed Mar 12 21:52:49 2014
@@ -575,5 +575,13 @@
<processor class="solr.RunUpdateProcessorFactory" />
</updateRequestProcessorChain>
+ <restManager>
+ <!--
+ IMPORTANT: Due to the Lucene SecurityManager, tests can only write to their runtime directory or below.
+ But its easier to just keep everything in memory for testing so no remnants are left behind.
+ -->
+ <str name="storageIO">org.apache.solr.rest.ManagedResourceStorage$InMemoryStorageIO</str>
+ </restManager>
+
</config>
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=1576939&r1=1576938&r2=1576939&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 Wed Mar 12 21:52:49 2014
@@ -24,13 +24,26 @@ import org.restlet.ext.servlet.ServerSer
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.
+ */
abstract public class SolrRestletTestBase extends RestTestBase {
+
+ /**
+ * Creates test harness, including "extra" servlets for all
+ * Solr Restlet Application subclasses.
+ */
@BeforeClass
public static void init() throws Exception {
final SortedMap<ServletHolder,String> extraServlets = new TreeMap<>();
- final ServletHolder solrRestApi = new ServletHolder("SolrRestApi", ServerServlet.class);
- solrRestApi.setInitParameter("org.restlet.application", "org.apache.solr.rest.SolrRestApi");
- extraServlets.put(solrRestApi, "/schema/*"); // '/schema/*' matches '/schema', '/schema/', and '/schema/whatever...'
+ final ServletHolder solrSchemaRestApi = new ServletHolder("SolrSchemaRestApi", ServerServlet.class);
+ solrSchemaRestApi.setInitParameter("org.restlet.application", "org.apache.solr.rest.SolrSchemaRestApi");
+ extraServlets.put(solrSchemaRestApi, "/schema/*"); // '/schema/*' matches '/schema', '/schema/', and '/schema/whatever...'
+
+ final ServletHolder solrConfigRestApi = new ServletHolder("SolrConfigRestApi", ServerServlet.class);
+ solrConfigRestApi.setInitParameter("org.restlet.application", "org.apache.solr.rest.SolrConfigRestApi");
+ extraServlets.put(solrConfigRestApi, "/config/*");
createJettyAndHarness(TEST_HOME(), "solrconfig.xml", "schema-rest.xml", "/solr", true, extraServlets);
}
Added: lucene/dev/trunk/solr/core/src/test/org/apache/solr/rest/TestManagedResource.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/core/src/test/org/apache/solr/rest/TestManagedResource.java?rev=1576939&view=auto
==============================================================================
--- lucene/dev/trunk/solr/core/src/test/org/apache/solr/rest/TestManagedResource.java (added)
+++ lucene/dev/trunk/solr/core/src/test/org/apache/solr/rest/TestManagedResource.java Wed Mar 12 21:52:49 2014
@@ -0,0 +1,327 @@
+package org.apache.solr.rest;
+/*
+ * 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.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.Serializable;
+import java.io.StringReader;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.lucene.util.BytesRef;
+import org.apache.solr.SolrTestCaseJ4;
+import org.apache.solr.common.SolrException;
+import org.apache.solr.common.util.NamedList;
+import org.apache.solr.core.SolrResourceLoader;
+import org.apache.solr.rest.ManagedResourceStorage.StorageIO;
+import org.junit.Test;
+import org.noggit.JSONParser;
+import org.noggit.ObjectBuilder;
+
+/**
+ * Tests {@link ManagedResource} functionality.
+ */
+public class TestManagedResource extends SolrTestCaseJ4 {
+
+ /**
+ * Mock class that acts like an analysis component that depends on
+ * data managed by a ManagedResource
+ */
+ private class MockAnalysisComponent implements ManagedResourceObserver {
+
+ private boolean wasNotified = false;
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public void onManagedResourceInitialized(NamedList<?> args, ManagedResource res) throws SolrException {
+
+ assertEquals("someVal", args.get("someArg"));
+
+ assertTrue(res instanceof ManagedTestResource);
+ ManagedTestResource testRes = (ManagedTestResource)res;
+ List<String> data = (List<String>)testRes.managedData;
+ assertTrue(data.contains("1"));
+ assertTrue(data.contains("2"));
+ assertTrue(data.contains("3"));
+
+ wasNotified = true;
+ }
+ }
+
+ private class ManagedTestResource extends ManagedResource {
+
+ private Object managedData;
+
+ private ManagedTestResource(String resourceId, SolrResourceLoader loader,
+ StorageIO storageIO) throws SolrException {
+ super(resourceId, loader, storageIO);
+ }
+
+ @Override
+ protected void onManagedDataLoadedFromStorage(NamedList<?> managedInitArgs, Object managedData)
+ throws SolrException {
+
+ assertNotNull(managedData);
+ assertTrue(managedData instanceof List);
+
+ // {'initArgs':{'someArg':'someVal', 'arg2':true, 'arg3':['one','two','three'],
+ // 'arg4':18, 'arg5':0.9, 'arg6':{ 'uno':1, 'dos':2 }},'"
+ assertEquals("someVal", managedInitArgs.get("someArg"));
+ assertEquals(true, managedInitArgs.get("arg2"));
+ List<String> arg3List = Arrays.asList("one", "two", "three");
+ assertEquals(arg3List, managedInitArgs.get("arg3"));
+ assertEquals(18L, managedInitArgs.get("arg4"));
+ assertEquals(0.9, managedInitArgs.get("arg5"));
+ Map<String,Long> arg6map = new LinkedHashMap<>(2);
+ arg6map.put("uno", 1L);
+ arg6map.put("dos", 2L);
+ assertEquals(arg6map, managedInitArgs.get("arg6"));
+
+ this.managedData = managedData;
+ }
+
+
+ // NOTE: These methods are better tested from the REST API
+ // so they are stubbed out here and not used in this test
+
+ @Override
+ protected Object applyUpdatesToManagedData(Object updates) {
+ return null;
+ }
+
+ @Override
+ public void doDeleteChild(BaseSolrResource endpoint, String childId) {}
+
+ @Override
+ public void doGet(BaseSolrResource endpoint, String childId) {}
+ }
+
+ /**
+ * Implements a Java serialization based storage format.
+ */
+ private class SerializableStorage extends ManagedResourceStorage {
+
+ SerializableStorage(StorageIO storageIO, SolrResourceLoader loader) {
+ super(storageIO, loader);
+ }
+
+ @Override
+ public Object load(String resourceId) throws IOException {
+ String storedId = getStoredResourceId(resourceId);
+ InputStream inputStream = storageIO.openInputStream(storedId);
+ if (inputStream == null) {
+ return null;
+ }
+ Object serialized = null;
+ ObjectInputStream ois = null;
+ try {
+ ois = new ObjectInputStream(inputStream);
+ serialized = ois.readObject();
+ } catch (ClassNotFoundException e) {
+ // unlikely
+ throw new IOException(e);
+ } finally {
+ if (ois != null) {
+ try {
+ ois.close();
+ } catch (Exception ignore){}
+ }
+ }
+ return serialized;
+ }
+
+ @Override
+ public void store(String resourceId, Object toStore) throws IOException {
+ if (!(toStore instanceof Serializable))
+ throw new IOException("Instance of "+
+ toStore.getClass().getName()+" is not Serializable!");
+
+ String storedId = getStoredResourceId(resourceId);
+ ObjectOutputStream oos = null;
+ try {
+ oos = new ObjectOutputStream(storageIO.openOutputStream(storedId));
+ oos.writeObject(toStore);
+ oos.flush();
+ } finally {
+ if (oos != null) {
+ try {
+ oos.close();
+ } catch (Exception ignore){}
+ }
+ }
+ }
+
+ @Override
+ public String getStoredResourceId(String resourceId) {
+ return resourceId.replace('/','_')+".bin";
+ }
+ }
+
+ private class CustomStorageFormatResource extends ManagedTestResource {
+ private CustomStorageFormatResource(String resourceId, SolrResourceLoader loader,
+ StorageIO storageIO) throws SolrException {
+ super(resourceId, loader, storageIO);
+ }
+
+ @Override
+ protected ManagedResourceStorage createStorage(StorageIO storageIO, SolrResourceLoader loader)
+ throws SolrException
+ {
+ return new SerializableStorage(storageIO, loader);
+ }
+ }
+
+ /**
+ * Tests managed data storage to and loading from {@link ManagedResourceStorage.InMemoryStorageIO}.
+ */
+ @SuppressWarnings("unchecked")
+ @Test
+ public void testLoadingAndStoringOfManagedData() throws Exception {
+ String resourceId = "/config/test/foo";
+ String storedResourceId = "_config_test_foo.json";
+
+ MockAnalysisComponent observer = new MockAnalysisComponent();
+ List<ManagedResourceObserver> observers =
+ Arrays.asList((ManagedResourceObserver)observer);
+
+ // put some data in the storage impl so that we can test
+ // initialization of managed data from storage
+ String storedJson = "{'initArgs':{'someArg':'someVal', 'arg2':true, 'arg3':['one','two','three'],"
+ + " 'arg4':18, 'arg5':0.9, 'arg6':{ 'uno':1, 'dos':2}},'"
+ + ManagedResource.MANAGED_JSON_LIST_FIELD+"':['1','2','3']}";
+ ManagedResourceStorage.InMemoryStorageIO storageIO =
+ new ManagedResourceStorage.InMemoryStorageIO();
+ storageIO.storage.put(storedResourceId, new BytesRef(json(storedJson)));
+
+ ManagedTestResource res =
+ new ManagedTestResource(resourceId, new SolrResourceLoader("./"), storageIO);
+ res.loadManagedDataAndNotify(observers);
+
+ assertTrue("Observer was not notified by ManagedResource!", observer.wasNotified);
+
+ // now update the managed data (as if it came from the REST API)
+ List<String> updatedData = new ArrayList<>();
+ updatedData.add("1");
+ updatedData.add("2");
+ updatedData.add("3");
+ updatedData.add("4");
+ res.storeManagedData(updatedData);
+
+ StringReader stringReader =
+ new StringReader(storageIO.storage.get(storedResourceId).utf8ToString());
+ Map<String,Object> jsonObject =
+ (Map<String,Object>) ObjectBuilder.getVal(new JSONParser(stringReader));
+ List<String> jsonList =
+ (List<String>)jsonObject.get(ManagedResource.MANAGED_JSON_LIST_FIELD);
+
+ assertTrue("Managed data was not updated correctly!", jsonList.contains("4"));
+ }
+
+ /**
+ * The ManagedResource storage framework allows the end developer to use a different
+ * storage format other than JSON, as demonstrated by this test.
+ */
+ @SuppressWarnings("rawtypes")
+ @Test
+ public void testCustomStorageFormat() throws Exception {
+ String resourceId = "/schema/test/foo";
+ String storedResourceId = "_schema_test_foo.bin";
+
+ MockAnalysisComponent observer = new MockAnalysisComponent();
+ List<ManagedResourceObserver> observers =
+ Arrays.asList((ManagedResourceObserver)observer);
+
+ // put some data in the storage impl so that we can test
+ // initialization of managed data from storage
+ Map<String,Object> storedData = new HashMap<>();
+ Map<String,Object> initArgs = new HashMap<>();
+
+ // {'initArgs':{'someArg':'someVal', 'arg2':true, 'arg3':['one','two','three'],
+ // 'arg4':18, 'arg5':0.9, 'arg6':{ 'uno':1, 'dos':2 }},'"
+ initArgs.put("someArg", "someVal");
+ initArgs.put("arg2", Boolean.TRUE);
+ List<String> arg3list = Arrays.asList("one", "two", "three");
+ initArgs.put("arg3", arg3list);
+ initArgs.put("arg4", 18L);
+ initArgs.put("arg5", 0.9);
+ Map<String,Long> arg6map = new HashMap<>();
+ arg6map.put("uno", 1L);
+ arg6map.put("dos", 2L);
+ initArgs.put("arg6", arg6map);
+
+ storedData.put("initArgs", initArgs);
+ List<String> managedList = new ArrayList<>();
+ managedList.add("1");
+ managedList.add("2");
+ managedList.add("3");
+ storedData.put(ManagedResource.MANAGED_JSON_LIST_FIELD, managedList);
+ ManagedResourceStorage.InMemoryStorageIO storageIO =
+ new ManagedResourceStorage.InMemoryStorageIO();
+ storageIO.storage.put(storedResourceId, ser2bytes((Serializable)storedData));
+
+ CustomStorageFormatResource res =
+ new CustomStorageFormatResource(resourceId, new SolrResourceLoader("./"), storageIO);
+ res.loadManagedDataAndNotify(observers);
+
+ assertTrue("Observer was not notified by ManagedResource!", observer.wasNotified);
+
+ // now store some data (as if it came from the REST API)
+ List<String> updatedData = new ArrayList<>();
+ updatedData.add("1");
+ updatedData.add("2");
+ updatedData.add("3");
+ updatedData.add("4");
+ res.storeManagedData(updatedData);
+
+ Object stored = res.storage.load(resourceId);
+ assertNotNull(stored);
+ assertTrue(stored instanceof Map);
+ Map storedMap = (Map)stored;
+ assertNotNull(storedMap.get("initArgs"));
+ List storedList = (List)storedMap.get(ManagedResource.MANAGED_JSON_LIST_FIELD);
+ assertTrue(storedList.contains("4"));
+ }
+
+
+ /**
+ * Converts the given Serializable object to bytes
+ */
+ private BytesRef ser2bytes(Serializable ser) throws Exception {
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ ObjectOutputStream oos = null;
+ try {
+ oos = new ObjectOutputStream(out);
+ oos.writeObject(ser);
+ oos.flush();
+ } finally {
+ if (oos != null) {
+ try {
+ oos.close();
+ } catch (Exception ignore){}
+ }
+ }
+ return new BytesRef(out.toByteArray());
+ }
+}
Added: lucene/dev/trunk/solr/core/src/test/org/apache/solr/rest/TestManagedResourceStorage.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/core/src/test/org/apache/solr/rest/TestManagedResourceStorage.java?rev=1576939&view=auto
==============================================================================
--- lucene/dev/trunk/solr/core/src/test/org/apache/solr/rest/TestManagedResourceStorage.java (added)
+++ lucene/dev/trunk/solr/core/src/test/org/apache/solr/rest/TestManagedResourceStorage.java Wed Mar 12 21:52:49 2014
@@ -0,0 +1,134 @@
+package org.apache.solr.rest;
+/*
+ * 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.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.lucene.util.LuceneTestCase.Slow;
+import org.apache.solr.cloud.AbstractZkTestCase;
+import org.apache.solr.common.cloud.SolrZkClient;
+import org.apache.solr.common.util.NamedList;
+import org.apache.solr.core.SolrResourceLoader;
+import org.apache.solr.rest.ManagedResourceStorage.StorageIO;
+import org.apache.solr.rest.ManagedResourceStorage.FileStorageIO;
+import org.apache.solr.rest.ManagedResourceStorage.ZooKeeperStorageIO;
+import org.apache.solr.rest.ManagedResourceStorage.JsonStorage;
+import org.junit.Test;
+
+/**
+ * Depends on ZK for testing ZooKeeper backed storage logic.
+ */
+@Slow
+public class TestManagedResourceStorage extends AbstractZkTestCase {
+
+ /**
+ * Runs persisted managed resource creation and update tests on Zookeeper storage.
+ */
+ @Test
+ public void testZkBasedJsonStorage() throws Exception {
+
+ // test using ZooKeeper
+ assertTrue("Not using ZooKeeper", h.getCoreContainer().isZooKeeperAware());
+ SolrZkClient zkClient = h.getCoreContainer().getZkController().getZkClient();
+ SolrResourceLoader loader = new SolrResourceLoader("./");
+ // Solr unit tests can only write to their working directory due to
+ // a custom Java Security Manager installed in the test environment
+ NamedList<String> initArgs = new NamedList<>();
+ try {
+ ZooKeeperStorageIO zkStorageIO = new ZooKeeperStorageIO(zkClient, "/test");
+ zkStorageIO.configure(loader, initArgs);
+ doStorageTests(loader, zkStorageIO);
+ } finally {
+ zkClient.close();
+ }
+ }
+
+
+ /**
+ * Runs persisted managed resource creation and update tests on JSON storage.
+ */
+ @Test
+ public void testFileBasedJsonStorage() throws Exception {
+ SolrResourceLoader loader = new SolrResourceLoader("./");
+ // Solr unit tests can only write to their working directory due to
+ // a custom Java Security Manager installed in the test environment
+ NamedList<String> initArgs = new NamedList<>();
+ initArgs.add(ManagedResourceStorage.STORAGE_DIR_INIT_ARG, "./managed");
+ FileStorageIO fileStorageIO = new FileStorageIO();
+ fileStorageIO.configure(loader, initArgs);
+ doStorageTests(loader, fileStorageIO);
+ }
+
+ /**
+ * Called from tests for each storage type to run creation and update tests
+ * on a persisted managed resource.
+ */
+ @SuppressWarnings("unchecked")
+ private void doStorageTests(SolrResourceLoader loader, StorageIO storageIO) throws Exception {
+ String resourceId = "/test/foo";
+
+ JsonStorage jsonStorage = new JsonStorage(storageIO, loader);
+
+ Map<String,String> managedInitArgs = new HashMap<>();
+ managedInitArgs.put("ignoreCase","true");
+ managedInitArgs.put("dontIgnoreCase", "false");
+
+ List<String> managedList = new ArrayList<>(); // we need a mutable List for this test
+ managedList.addAll(Arrays.asList("a","b","c","d","e"));
+
+ Map<String,Object> toStore = new HashMap<>();
+ toStore.put(ManagedResource.INIT_ARGS_JSON_FIELD, managedInitArgs);
+ toStore.put(ManagedResource.MANAGED_JSON_LIST_FIELD, managedList);
+
+ jsonStorage.store(resourceId, toStore);
+
+ String storedResourceId = jsonStorage.getStoredResourceId(resourceId);
+ assertTrue(storedResourceId+" file not found!", storageIO.exists(storedResourceId));
+
+ Object fromStorage = jsonStorage.load(resourceId);
+ assertNotNull(fromStorage);
+
+ Map<String,Object> storedMap = (Map<String,Object>)fromStorage;
+ Map<String,Object> storedArgs = (Map<String,Object>)storedMap.get(ManagedResource.INIT_ARGS_JSON_FIELD);
+ assertNotNull(storedArgs);
+ assertEquals("true", storedArgs.get("ignoreCase"));
+ List<String> storedList = (List<String>)storedMap.get(ManagedResource.MANAGED_JSON_LIST_FIELD);
+ assertNotNull(storedList);
+ assertTrue(storedList.size() == managedList.size());
+ assertTrue(storedList.contains("a"));
+
+ // now verify you can update existing data
+ managedInitArgs.put("anotherArg", "someValue");
+ managedList.add("f");
+ jsonStorage.store(resourceId, toStore);
+ fromStorage = jsonStorage.load(resourceId);
+ assertNotNull(fromStorage);
+
+ storedMap = (Map<String,Object>)fromStorage;
+ storedArgs = (Map<String,Object>)storedMap.get(ManagedResource.INIT_ARGS_JSON_FIELD);
+ assertNotNull(storedArgs);
+ assertEquals("someValue", storedArgs.get("anotherArg"));
+ storedList = (List<String>)storedMap.get(ManagedResource.MANAGED_JSON_LIST_FIELD);
+ assertNotNull(storedList);
+ assertTrue(storedList.size() == managedList.size());
+ assertTrue(storedList.contains("e"));
+ }
+}
Added: lucene/dev/trunk/solr/core/src/test/org/apache/solr/rest/TestRestManager.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/core/src/test/org/apache/solr/rest/TestRestManager.java?rev=1576939&view=auto
==============================================================================
--- lucene/dev/trunk/solr/core/src/test/org/apache/solr/rest/TestRestManager.java (added)
+++ lucene/dev/trunk/solr/core/src/test/org/apache/solr/rest/TestRestManager.java Wed Mar 12 21:52:49 2014
@@ -0,0 +1,225 @@
+package org.apache.solr.rest;
+/*
+ * 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.Arrays;
+import java.util.Locale;
+import java.util.Set;
+
+import org.apache.solr.common.SolrException;
+import org.apache.solr.common.util.NamedList;
+import org.apache.solr.core.SolrResourceLoader;
+import org.apache.solr.rest.ManagedResourceStorage.StorageIO;
+import org.apache.solr.rest.schema.analysis.ManagedWordSetResource;
+import org.junit.Test;
+import org.noggit.JSONUtil;
+
+/**
+ * Tests {@link RestManager} functionality, including resource registration,
+ * and REST API requests and responses.
+ */
+public class TestRestManager extends SolrRestletTestBase {
+
+ private class BogusManagedResource extends ManagedResource {
+
+ protected BogusManagedResource(String resourceId,
+ SolrResourceLoader loader, StorageIO storageIO) throws SolrException {
+ super(resourceId, loader, storageIO);
+ }
+
+ @Override
+ protected void onManagedDataLoadedFromStorage(NamedList<?> managedInitArgs, Object managedData)
+ throws SolrException {}
+
+ @Override
+ protected Object applyUpdatesToManagedData(Object updates) {
+ return null;
+ }
+
+ @Override
+ public void doDeleteChild(BaseSolrResource endpoint, String childId) {}
+
+ @Override
+ public void doGet(BaseSolrResource endpoint, String childId) {}
+
+ }
+
+ private class MockAnalysisComponent implements ManagedResourceObserver {
+
+ @Override
+ public void onManagedResourceInitialized(NamedList<?> args, ManagedResource res)
+ throws SolrException {
+ assertTrue(res instanceof ManagedWordSetResource);
+ }
+ }
+
+ /**
+ * Test RestManager initialization and handling of registered ManagedResources.
+ */
+ @Test
+ public void testManagedResourceRegistrationAndInitialization() throws Exception {
+ // first, we need to register some ManagedResources, which is done with the registry
+ // provided by the SolrResourceLoader
+ SolrResourceLoader loader = new SolrResourceLoader("./");
+
+ RestManager.Registry registry = loader.getManagedResourceRegistry();
+ assertNotNull("Expected a non-null RestManager.Registry from the SolrResourceLoader!", registry);
+
+ String resourceId = "/config/test/foo";
+ registry.registerManagedResource(resourceId,
+ ManagedWordSetResource.class,
+ new MockAnalysisComponent());
+
+ // verify the two different components can register the same ManagedResource in the registry
+ registry.registerManagedResource(resourceId,
+ ManagedWordSetResource.class,
+ new MockAnalysisComponent());
+
+ // verify we can register another resource under a different resourceId
+ registry.registerManagedResource("/config/test/foo2",
+ ManagedWordSetResource.class,
+ new MockAnalysisComponent());
+
+ ignoreException("REST API path .* already registered to instances of ");
+
+ String failureMessage = "Should not be able to register a different"
+ + " ManagedResource implementation for {}";
+
+ // verify that some other hooligan cannot register another type
+ // of ManagedResource implementation under the same resourceId
+ try {
+ registry.registerManagedResource(resourceId,
+ BogusManagedResource.class,
+ new MockAnalysisComponent());
+ fail(String.format(Locale.ROOT, failureMessage, resourceId));
+ } catch (SolrException solrExc) {
+ // expected output
+ }
+
+ resetExceptionIgnores();
+
+ ignoreException("is a reserved endpoint used by the Solr REST API!");
+
+ failureMessage = "Should not be able to register reserved endpoint {}";
+
+ // verify that already-spoken-for REST API endpoints can't be registered
+ Set<String> reservedEndpoints = registry.getReservedEndpoints();
+ assertTrue(reservedEndpoints.size() > 2);
+ assertTrue(reservedEndpoints.contains(RestManager.SCHEMA_BASE_PATH + RestManager.MANAGED_ENDPOINT));
+ assertTrue(reservedEndpoints.contains(RestManager.CONFIG_BASE_PATH + RestManager.MANAGED_ENDPOINT));
+ for (String endpoint : reservedEndpoints) {
+
+ try {
+ registry.registerManagedResource
+ (endpoint, BogusManagedResource.class, new MockAnalysisComponent());
+ fail(String.format(Locale.ROOT, failureMessage, endpoint));
+ } catch (SolrException solrExc) {
+ // expected output
+ }
+
+ // also try to register already-spoken-for REST API endpoints with a child segment
+ endpoint += "/kid";
+ try {
+ registry.registerManagedResource
+ (endpoint, BogusManagedResource.class, new MockAnalysisComponent());
+ fail(String.format(Locale.ROOT, failureMessage, endpoint));
+ } catch (SolrException solrExc) {
+ // expected output
+ }
+ }
+
+ resetExceptionIgnores();
+
+ NamedList<String> initArgs = new NamedList<>();
+ RestManager restManager = new RestManager();
+ restManager.init(loader, initArgs, new ManagedResourceStorage.InMemoryStorageIO());
+
+ ManagedResource res = restManager.getManagedResource(resourceId);
+ assertTrue(res instanceof ManagedWordSetResource);
+ assertEquals(res.getResourceId(), resourceId);
+
+ restManager.getManagedResource("/config/test/foo2"); // exception if it isn't registered
+ }
+
+ /**
+ * Tests {@link RestManager}'s responses to REST API requests on /config/managed
+ * and /schema/managed. Also tests {@link ManagedWordSetResource} functionality
+ * through the REST API.
+ */
+ @Test
+ public void testRestManagerEndpoints() throws Exception {
+ // relies on these ManagedResources being activated in the schema-rest.xml used by this test
+ assertJQ("/schema/managed",
+ "/responseHeader/status==0");
+ /*
+ * TODO: can't assume these will be here unless schema-rest.xml includes these declarations
+ *
+ "/managedResources/[0]/class=='org.apache.solr.rest.schema.analysis.ManagedWordSetResource'",
+ "/managedResources/[0]/resourceId=='/schema/analysis/stopwords/english'",
+ "/managedResources/[1]/class=='org.apache.solr.rest.schema.analysis.ManagedSynonymFilterFactory$SynonymManager'",
+ "/managedResources/[1]/resourceId=='/schema/analysis/synonyms/english'");
+ */
+
+ // no pre-existing managed config components
+ assertJQ("/config/managed", "/managedResources==[]");
+
+ // add a ManagedWordSetResource for managing protected words (for stemming)
+ String newEndpoint = "/schema/analysis/protwords/english";
+
+ assertJPut(newEndpoint, json("{ 'class':'solr.ManagedWordSetResource' }"), "/responseHeader/status==0");
+
+ assertJQ("/schema/managed"
+ ,"/managedResources/[0]/class=='org.apache.solr.rest.schema.analysis.ManagedWordSetResource'"
+ ,"/managedResources/[0]/resourceId=='/schema/analysis/protwords/english'");
+
+ // query the resource we just created
+ assertJQ(newEndpoint, "/wordSet/managedList==[]");
+
+ // add some words to this new word list manager
+ assertJPut(newEndpoint, JSONUtil.toJSON(Arrays.asList("this", "is", "a", "test")), "/responseHeader/status==0");
+
+ assertJQ(newEndpoint
+ ,"/wordSet/managedList==['a','is','test','this']"
+ ,"/wordSet/initArgs=={'ignoreCase':false}"); // make sure the default is serialized even if not specified
+
+ // Test for case-sensitivity - "Test" lookup should fail
+ assertJQ(newEndpoint + "/Test", "/responseHeader/status==404");
+
+ // Switch to case-insensitive
+ assertJPut(newEndpoint, json("{ 'initArgs':{ 'ignoreCase':'true' } }"), "/responseHeader/status==0");
+
+ // Test for case-insensitivity - "Test" lookup should succeed
+ assertJQ(newEndpoint + "/Test", "/responseHeader/status==0");
+
+ // Switch to case-sensitive - this request should fail: changing ignoreCase from true to false is not permitted
+ assertJPut(newEndpoint, json("{ 'initArgs':{ 'ignoreCase':false } }"), "/responseHeader/status==400");
+
+ // Test XML response format
+ assertQ(newEndpoint + "?wt=xml"
+ ,"/response/lst[@name='responseHeader']/int[@name='status']=0"
+ ,"/response/lst[@name='wordSet']/arr[@name='managedList']/str[1]='a'"
+ ,"/response/lst[@name='wordSet']/arr[@name='managedList']/str[2]='is'"
+ ,"/response/lst[@name='wordSet']/arr[@name='managedList']/str[3]='test'"
+ ,"/response/lst[@name='wordSet']/arr[@name='managedList']/str[4]='this'");
+
+ // delete the one we created above
+ assertJDelete(newEndpoint, "/responseHeader/status==0");
+
+ // make sure it's really gone
+ assertJQ("/config/managed", "/managedResources==[]");
+ }
+}
\ No newline at end of file
Modified: lucene/dev/trunk/solr/core/src/test/org/apache/solr/rest/schema/TestClassNameShortening.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/core/src/test/org/apache/solr/rest/schema/TestClassNameShortening.java?rev=1576939&r1=1576938&r2=1576939&view=diff
==============================================================================
--- lucene/dev/trunk/solr/core/src/test/org/apache/solr/rest/schema/TestClassNameShortening.java (original)
+++ lucene/dev/trunk/solr/core/src/test/org/apache/solr/rest/schema/TestClassNameShortening.java Wed Mar 12 21:52:49 2014
@@ -31,8 +31,8 @@ public class TestClassNameShortening ext
@BeforeClass
public static void init() throws Exception {
final SortedMap<ServletHolder,String> extraServlets = new TreeMap<>();
- final ServletHolder solrRestApi = new ServletHolder("SolrRestApi", ServerServlet.class);
- solrRestApi.setInitParameter("org.restlet.application", "org.apache.solr.rest.SolrRestApi");
+ 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...'
createJettyAndHarness(TEST_HOME(), "solrconfig-minimal.xml", "schema-class-name-shortening-on-serialization.xml",
Modified: lucene/dev/trunk/solr/core/src/test/org/apache/solr/rest/schema/TestManagedSchemaFieldResource.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/core/src/test/org/apache/solr/rest/schema/TestManagedSchemaFieldResource.java?rev=1576939&r1=1576938&r2=1576939&view=diff
==============================================================================
--- lucene/dev/trunk/solr/core/src/test/org/apache/solr/rest/schema/TestManagedSchemaFieldResource.java (original)
+++ lucene/dev/trunk/solr/core/src/test/org/apache/solr/rest/schema/TestManagedSchemaFieldResource.java Wed Mar 12 21:52:49 2014
@@ -47,8 +47,8 @@ public class TestManagedSchemaFieldResou
FileUtils.copyDirectory(new File(TEST_HOME()), tmpSolrHome.getAbsoluteFile());
final SortedMap<ServletHolder,String> extraServlets = new TreeMap<>();
- final ServletHolder solrRestApi = new ServletHolder("SolrRestApi", ServerServlet.class);
- solrRestApi.setInitParameter("org.restlet.application", "org.apache.solr.rest.SolrRestApi");
+ 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");
Modified: lucene/dev/trunk/solr/core/src/test/org/apache/solr/rest/schema/TestSerializedLuceneMatchVersion.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/core/src/test/org/apache/solr/rest/schema/TestSerializedLuceneMatchVersion.java?rev=1576939&r1=1576938&r2=1576939&view=diff
==============================================================================
--- lucene/dev/trunk/solr/core/src/test/org/apache/solr/rest/schema/TestSerializedLuceneMatchVersion.java (original)
+++ lucene/dev/trunk/solr/core/src/test/org/apache/solr/rest/schema/TestSerializedLuceneMatchVersion.java Wed Mar 12 21:52:49 2014
@@ -31,8 +31,8 @@ public class TestSerializedLuceneMatchVe
@BeforeClass
public static void init() throws Exception {
final SortedMap<ServletHolder,String> extraServlets = new TreeMap<>();
- final ServletHolder solrRestApi = new ServletHolder("SolrRestApi", ServerServlet.class);
- solrRestApi.setInitParameter("org.restlet.application", "org.apache.solr.rest.SolrRestApi");
+ 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...'
createJettyAndHarness(TEST_HOME(), "solrconfig-minimal.xml", "schema-rest-lucene-match-version.xml",
Modified: lucene/dev/trunk/solr/core/src/test/org/apache/solr/schema/TestCloudManagedSchemaAddField.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/core/src/test/org/apache/solr/schema/TestCloudManagedSchemaAddField.java?rev=1576939&r1=1576938&r2=1576939&view=diff
==============================================================================
--- lucene/dev/trunk/solr/core/src/test/org/apache/solr/schema/TestCloudManagedSchemaAddField.java (original)
+++ lucene/dev/trunk/solr/core/src/test/org/apache/solr/schema/TestCloudManagedSchemaAddField.java Wed Mar 12 21:52:49 2014
@@ -58,8 +58,8 @@ public class TestCloudManagedSchemaAddFi
@Override
public SortedMap<ServletHolder,String> getExtraServlets() {
final SortedMap<ServletHolder,String> extraServlets = new TreeMap<>();
- final ServletHolder solrRestApi = new ServletHolder("SolrRestApi", ServerServlet.class);
- solrRestApi.setInitParameter("org.restlet.application", "org.apache.solr.rest.SolrRestApi");
+ 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...'
return extraServlets;
}
Modified: lucene/dev/trunk/solr/solrj/src/java/org/apache/solr/common/util/NamedList.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/solrj/src/java/org/apache/solr/common/util/NamedList.java?rev=1576939&r1=1576938&r2=1576939&view=diff
==============================================================================
--- lucene/dev/trunk/solr/solrj/src/java/org/apache/solr/common/util/NamedList.java (original)
+++ lucene/dev/trunk/solr/solrj/src/java/org/apache/solr/common/util/NamedList.java Wed Mar 12 21:52:49 2014
@@ -81,6 +81,31 @@ public class NamedList<T> implements Clo
}
/**
+ * Creates a NamedList instance containing the "name,value" pairs contained in the
+ * Map.
+ *
+ * <p>
+ * Modifying the contents of the Map after calling this constructor may change
+ * the NamedList (in future versions of Solr), but this is not guaranteed and should
+ * not be relied upon. To modify the NamedList, refer to {@link #add(String, Object)}
+ * or {@link #remove(String)}.
+ * </p>
+ *
+ * @param nameValueMap the name value pairs
+ */
+ public NamedList(Map<String,? extends T> nameValueMap) {
+ if (null == nameValueMap) {
+ nvPairs = new ArrayList<>();
+ } else {
+ nvPairs = new ArrayList<>(nameValueMap.size());
+ for (Map.Entry<String,? extends T> ent : nameValueMap.entrySet()) {
+ nvPairs.add(ent.getKey());
+ nvPairs.add(ent.getValue());
+ }
+ }
+ }
+
+ /**
* Creates an instance backed by an explicitly specified list of
* pairwise names/values.
*
@@ -528,6 +553,30 @@ public class NamedList<T> implements Clo
* not a Boolean or a String.
*/
public Boolean removeBooleanArg(final String name) {
+ Boolean bool = getBooleanArg(name);
+ if (null != bool) {
+ remove(name);
+ }
+ return bool;
+ }
+
+ /**
+ * Used for getting a boolean argument from a NamedList object. If the name
+ * is not present, returns null. If there is more than one value with that
+ * name, or if the value found is not a Boolean or a String, throws an
+ * exception. If there is only one value present and it is a Boolean or a
+ * String, the value is returned as a Boolean. The NamedList is not
+ * modified. See {@link #remove(String)}, {@link #removeAll(String)}
+ * and {@link #removeConfigArgs(String)} for additional ways of gathering
+ * configuration information from a NamedList.
+ *
+ * @param name The key to look up in the NamedList.
+ * @return The boolean value found.
+ * @throws SolrException
+ * If multiple values are found for the name or the value found is
+ * not a Boolean or a String.
+ */
+ public Boolean getBooleanArg(final String name) {
Boolean bool;
List<T> values = getAll(name);
if (0 == values.size()) {
@@ -544,12 +593,11 @@ public class NamedList<T> implements Clo
bool = Boolean.parseBoolean(o.toString());
} else {
throw new SolrException(SolrException.ErrorCode.SERVER_ERROR,
- "'" + name + "' must have type 'bool' or 'str'; found " + o.getClass());
+ "'" + name + "' must have type Boolean or CharSequence; found " + o.getClass());
}
- remove(name);
return bool;
}
-
+
/**
* Used for getting one or many arguments from NamedList objects that hold
* configuration parameters. Finds all entries in the NamedList that match
Modified: lucene/dev/trunk/solr/test-framework/src/java/org/apache/solr/util/RestTestBase.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/test-framework/src/java/org/apache/solr/util/RestTestBase.java?rev=1576939&r1=1576938&r2=1576939&view=diff
==============================================================================
--- lucene/dev/trunk/solr/test-framework/src/java/org/apache/solr/util/RestTestBase.java (original)
+++ lucene/dev/trunk/solr/test-framework/src/java/org/apache/solr/util/RestTestBase.java Wed Mar 12 21:52:49 2014
@@ -422,8 +422,73 @@ abstract public class RestTestBase exten
}
}
}
+
+ /**
+ * Deletes a resource and then matches some JSON test expressions against the
+ * response using the default double delta tolerance.
+ * @see org.apache.solr.JSONTestUtil#DEFAULT_DELTA
+ * @see #assertJDelete(String,double,String...)
+ */
+ public static void assertJDelete(String request, String... tests) throws Exception {
+ assertJDelete(request, JSONTestUtil.DEFAULT_DELTA, tests);
+ }
+
+ /**
+ * Deletes a resource and then matches some JSON test expressions against the
+ * response using the specified double delta tolerance.
+ */
+ public static void assertJDelete(String request, double delta, String... tests) throws Exception {
+ int queryStartPos = request.indexOf('?');
+ String query;
+ String path;
+ if (-1 == queryStartPos) {
+ query = "";
+ path = request;
+ } else {
+ query = request.substring(queryStartPos + 1);
+ path = request.substring(0, queryStartPos);
+ }
+ query = setParam(query, "wt", "json");
+ request = path + '?' + setParam(query, "indent", "on");
+
+ String response;
+ boolean failed = true;
+ try {
+ response = restTestHarness.delete(request);
+ failed = false;
+ } finally {
+ if (failed) {
+ log.error("REQUEST FAILED: " + request);
+ }
+ }
+ for (String test : tests) {
+ if (null == test || 0 == test.length()) continue;
+ String testJSON = json(test);
+ try {
+ failed = true;
+ String err = JSONTestUtil.match(response, testJSON, delta);
+ failed = false;
+ if (err != null) {
+ log.error("query failed JSON validation. error=" + err +
+ "\n expected =" + testJSON +
+ "\n response = " + response +
+ "\n request = " + request + "\n"
+ );
+ throw new RuntimeException(err);
+ }
+ } finally {
+ if (failed) {
+ log.error("JSON query validation threw an exception." +
+ "\n expected =" + testJSON +
+ "\n response = " + response +
+ "\n request = " + request + "\n"
+ );
+ }
+ }
+ }
+ }
/**
* Insures that the given param is included in the query with the given value.
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=1576939&r1=1576938&r2=1576939&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 Wed Mar 12 21:52:49 2014
@@ -23,6 +23,7 @@ import javax.xml.xpath.XPathExpressionEx
import org.apache.http.HttpEntity;
import org.apache.http.client.HttpClient;
+import org.apache.http.client.methods.HttpDelete;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpPut;
@@ -110,6 +111,18 @@ public class RestTestHarness extends Bas
}
/**
+ * Processes a DELETE request using a URL path (with no context path) + optional query params,
+ * e.g. "/schema/analysis/protwords/english", and returns the response content.
+ *
+ * @param request the URL path and optional query params
+ * @return The response to the DELETE request
+ */
+ public String delete(String request) throws IOException {
+ HttpDelete httpDelete = new HttpDelete(getBaseURL() + request);
+ return getResponse(httpDelete);
+ }
+
+ /**
* Processes a POST request using a URL path (with no context path) + optional query params,
* e.g. "/schema/fields/newfield", PUTs the given content, and returns the response content.
*
@@ -160,7 +173,10 @@ public class RestTestHarness extends Bas
throw new RuntimeException(e);
}
}
-
+
+ /**
+ * Executes the given request and returns the response.
+ */
private String getResponse(HttpUriRequest request) throws IOException {
HttpEntity entity = null;
try {
Modified: lucene/dev/trunk/solr/webapp/web/WEB-INF/web.xml
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/webapp/web/WEB-INF/web.xml?rev=1576939&r1=1576938&r2=1576939&view=diff
==============================================================================
--- lucene/dev/trunk/solr/webapp/web/WEB-INF/web.xml (original)
+++ lucene/dev/trunk/solr/webapp/web/WEB-INF/web.xml Wed Mar 12 21:52:49 2014
@@ -131,7 +131,16 @@
<servlet-class>org.restlet.ext.servlet.ServerServlet</servlet-class>
<init-param>
<param-name>org.restlet.application</param-name>
- <param-value>org.apache.solr.rest.SolrRestApi</param-value>
+ <param-value>org.apache.solr.rest.SolrSchemaRestApi</param-value>
+ </init-param>
+ </servlet>
+
+ <servlet>
+ <servlet-name>SolrConfigRestApi</servlet-name>
+ <servlet-class>org.restlet.ext.servlet.ServerServlet</servlet-class>
+ <init-param>
+ <param-name>org.restlet.application</param-name>
+ <param-value>org.apache.solr.rest.SolrConfigRestApi</param-value>
</init-param>
</servlet>
@@ -168,6 +177,11 @@
<url-pattern>/schema/*</url-pattern>
</servlet-mapping>
+ <servlet-mapping>
+ <servlet-name>SolrConfigRestApi</servlet-name>
+ <url-pattern>/config/*</url-pattern>
+ </servlet-mapping>
+
<mime-mapping>
<extension>.xsl</extension>
<!-- per http://www.w3.org/TR/2006/PR-xslt20-20061121/ -->