You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucene.apache.org by gs...@apache.org on 2013/08/05 12:51:50 UTC
svn commit: r1510425 [1/4] - in
/lucene/dev/branches/solr_guice_restlet/solr: core/
core/src/java/org/apache/solr/ core/src/java/org/apache/solr/core/
core/src/java/org/apache/solr/request/ core/src/java/org/apache/solr/rest/
core/src/java/org/apache/s...
Author: gsingers
Date: Mon Aug 5 10:51:48 2013
New Revision: 1510425
URL: http://svn.apache.org/r1510425
Log:
SOLR-4818, SOLR-5091: very basics starting to come together
Added:
lucene/dev/branches/solr_guice_restlet/solr/core/src/java/org/apache/solr/core/CoreContainerAPI.java
lucene/dev/branches/solr_guice_restlet/solr/core/src/java/org/apache/solr/core/CoreContainerAPIModule.java
lucene/dev/branches/solr_guice_restlet/solr/core/src/java/org/apache/solr/core/CoreContainerProxySR.java
lucene/dev/branches/solr_guice_restlet/solr/core/src/java/org/apache/solr/core/CoreContainerResource.java
lucene/dev/branches/solr_guice_restlet/solr/core/src/java/org/apache/solr/request/SolrQueryRequestDecoder.java
lucene/dev/branches/solr_guice_restlet/solr/core/src/java/org/apache/solr/rest/API.java
lucene/dev/branches/solr_guice_restlet/solr/core/src/java/org/apache/solr/rest/APIMBean.java
lucene/dev/branches/solr_guice_restlet/solr/core/src/java/org/apache/solr/rest/APIModule.java
lucene/dev/branches/solr_guice_restlet/solr/core/src/java/org/apache/solr/rest/BaseCoreResource.java
lucene/dev/branches/solr_guice_restlet/solr/core/src/java/org/apache/solr/rest/BaseResource.java
lucene/dev/branches/solr_guice_restlet/solr/core/src/java/org/apache/solr/rest/ResourceFinder.java
lucene/dev/branches/solr_guice_restlet/solr/core/src/java/org/apache/solr/rest/admin/
lucene/dev/branches/solr_guice_restlet/solr/core/src/java/org/apache/solr/rest/admin/EndpointsResource.java
lucene/dev/branches/solr_guice_restlet/solr/core/src/java/org/apache/solr/rest/admin/EndpointsSR.java
lucene/dev/branches/solr_guice_restlet/solr/core/src/java/org/apache/solr/rest/admin/InfoResource.java
lucene/dev/branches/solr_guice_restlet/solr/core/src/java/org/apache/solr/rest/admin/InfoSR.java
lucene/dev/branches/solr_guice_restlet/solr/core/src/java/org/apache/solr/rest/admin/MonitoringAPI.java
lucene/dev/branches/solr_guice_restlet/solr/core/src/java/org/apache/solr/rest/admin/MonitoringAPIModule.java
lucene/dev/branches/solr_guice_restlet/solr/core/src/java/org/apache/solr/rest/admin/StatsResource.java
lucene/dev/branches/solr_guice_restlet/solr/core/src/java/org/apache/solr/rest/admin/StatsSR.java
lucene/dev/branches/solr_guice_restlet/solr/core/src/java/org/apache/solr/rest/ping/
lucene/dev/branches/solr_guice_restlet/solr/core/src/java/org/apache/solr/rest/ping/PingAPI.java
lucene/dev/branches/solr_guice_restlet/solr/core/src/java/org/apache/solr/rest/ping/PingAPIModule.java
lucene/dev/branches/solr_guice_restlet/solr/core/src/java/org/apache/solr/rest/ping/PingResource.java
lucene/dev/branches/solr_guice_restlet/solr/core/src/java/org/apache/solr/rest/ping/PingSR.java
lucene/dev/branches/solr_guice_restlet/solr/core/src/java/org/apache/solr/rest/schema/CopyFieldCollectionSR.java
lucene/dev/branches/solr_guice_restlet/solr/core/src/java/org/apache/solr/rest/schema/DefaultSchemaSR.java
lucene/dev/branches/solr_guice_restlet/solr/core/src/java/org/apache/solr/rest/schema/DefaultSearchFieldSR.java
lucene/dev/branches/solr_guice_restlet/solr/core/src/java/org/apache/solr/rest/schema/DynamicFieldCollectionSR.java
lucene/dev/branches/solr_guice_restlet/solr/core/src/java/org/apache/solr/rest/schema/DynamicFieldSR.java
lucene/dev/branches/solr_guice_restlet/solr/core/src/java/org/apache/solr/rest/schema/FieldCollectionSR.java
lucene/dev/branches/solr_guice_restlet/solr/core/src/java/org/apache/solr/rest/schema/FieldSR.java
lucene/dev/branches/solr_guice_restlet/solr/core/src/java/org/apache/solr/rest/schema/FieldTypeCollectionSR.java
lucene/dev/branches/solr_guice_restlet/solr/core/src/java/org/apache/solr/rest/schema/FieldTypeSR.java
lucene/dev/branches/solr_guice_restlet/solr/core/src/java/org/apache/solr/rest/schema/SchemaAPI.java
lucene/dev/branches/solr_guice_restlet/solr/core/src/java/org/apache/solr/rest/schema/SchemaAPIModule.java
lucene/dev/branches/solr_guice_restlet/solr/core/src/java/org/apache/solr/rest/schema/SchemaNameSR.java
lucene/dev/branches/solr_guice_restlet/solr/core/src/java/org/apache/solr/rest/schema/SchemaSR.java
lucene/dev/branches/solr_guice_restlet/solr/core/src/java/org/apache/solr/rest/schema/SchemaSimilaritySR.java
lucene/dev/branches/solr_guice_restlet/solr/core/src/java/org/apache/solr/rest/schema/SchemaVersionSR.java
lucene/dev/branches/solr_guice_restlet/solr/core/src/java/org/apache/solr/rest/schema/SolrQueryParserDefaultOperatorSR.java
lucene/dev/branches/solr_guice_restlet/solr/core/src/java/org/apache/solr/rest/schema/SolrQueryParserSR.java
lucene/dev/branches/solr_guice_restlet/solr/core/src/java/org/apache/solr/rest/schema/UniqueKeyFieldSR.java
lucene/dev/branches/solr_guice_restlet/solr/core/src/java/org/apache/solr/servlet/HttpServletModule.java
lucene/dev/branches/solr_guice_restlet/solr/core/src/java/org/apache/solr/servlet/HttpServletSQRDecoder.java
lucene/dev/branches/solr_guice_restlet/solr/core/src/java/org/apache/solr/servlet/InjectableServlet.java
lucene/dev/branches/solr_guice_restlet/solr/core/src/java/org/apache/solr/servlet/SolrGuiceServletConfig.java
lucene/dev/branches/solr_guice_restlet/solr/core/src/test/org/apache/solr/servlet/SolrGuiceServletConfigTest.java
Removed:
lucene/dev/branches/solr_guice_restlet/solr/core/src/java/org/apache/solr/rest/SolrRestApi.java
Modified:
lucene/dev/branches/solr_guice_restlet/solr/core/ivy.xml
lucene/dev/branches/solr_guice_restlet/solr/core/src/java/org/apache/solr/core/CoreContainer.java
lucene/dev/branches/solr_guice_restlet/solr/core/src/java/org/apache/solr/core/SolrCore.java
lucene/dev/branches/solr_guice_restlet/solr/core/src/java/org/apache/solr/package.html
lucene/dev/branches/solr_guice_restlet/solr/core/src/java/org/apache/solr/rest/schema/BaseFieldResource.java
lucene/dev/branches/solr_guice_restlet/solr/core/src/java/org/apache/solr/rest/schema/BaseFieldTypeResource.java
lucene/dev/branches/solr_guice_restlet/solr/core/src/java/org/apache/solr/rest/schema/BaseSchemaResource.java
lucene/dev/branches/solr_guice_restlet/solr/core/src/java/org/apache/solr/rest/schema/CopyFieldCollectionResource.java
lucene/dev/branches/solr_guice_restlet/solr/core/src/java/org/apache/solr/rest/schema/DefaultSchemaResource.java
lucene/dev/branches/solr_guice_restlet/solr/core/src/java/org/apache/solr/rest/schema/DefaultSearchFieldResource.java
lucene/dev/branches/solr_guice_restlet/solr/core/src/java/org/apache/solr/rest/schema/DynamicFieldCollectionResource.java
lucene/dev/branches/solr_guice_restlet/solr/core/src/java/org/apache/solr/rest/schema/DynamicFieldResource.java
lucene/dev/branches/solr_guice_restlet/solr/core/src/java/org/apache/solr/rest/schema/FieldCollectionResource.java
lucene/dev/branches/solr_guice_restlet/solr/core/src/java/org/apache/solr/rest/schema/FieldResource.java
lucene/dev/branches/solr_guice_restlet/solr/core/src/java/org/apache/solr/rest/schema/FieldTypeCollectionResource.java
lucene/dev/branches/solr_guice_restlet/solr/core/src/java/org/apache/solr/rest/schema/FieldTypeResource.java
lucene/dev/branches/solr_guice_restlet/solr/core/src/java/org/apache/solr/rest/schema/SchemaNameResource.java
lucene/dev/branches/solr_guice_restlet/solr/core/src/java/org/apache/solr/rest/schema/SchemaResource.java
lucene/dev/branches/solr_guice_restlet/solr/core/src/java/org/apache/solr/rest/schema/SchemaSimilarityResource.java
lucene/dev/branches/solr_guice_restlet/solr/core/src/java/org/apache/solr/rest/schema/SchemaVersionResource.java
lucene/dev/branches/solr_guice_restlet/solr/core/src/java/org/apache/solr/rest/schema/SolrQueryParserDefaultOperatorResource.java
lucene/dev/branches/solr_guice_restlet/solr/core/src/java/org/apache/solr/rest/schema/SolrQueryParserResource.java
lucene/dev/branches/solr_guice_restlet/solr/core/src/java/org/apache/solr/rest/schema/UniqueKeyFieldResource.java
lucene/dev/branches/solr_guice_restlet/solr/core/src/java/org/apache/solr/servlet/LoadAdminUiServlet.java
lucene/dev/branches/solr_guice_restlet/solr/core/src/java/org/apache/solr/servlet/SolrDispatchFilter.java
lucene/dev/branches/solr_guice_restlet/solr/core/src/java/org/apache/solr/servlet/SolrRequestParsers.java
lucene/dev/branches/solr_guice_restlet/solr/core/src/java/org/apache/solr/servlet/ZookeeperInfoServlet.java
lucene/dev/branches/solr_guice_restlet/solr/webapp/web/WEB-INF/web.xml
Modified: lucene/dev/branches/solr_guice_restlet/solr/core/ivy.xml
URL: http://svn.apache.org/viewvc/lucene/dev/branches/solr_guice_restlet/solr/core/ivy.xml?rev=1510425&r1=1510424&r2=1510425&view=diff
==============================================================================
--- lucene/dev/branches/solr_guice_restlet/solr/core/ivy.xml (original)
+++ lucene/dev/branches/solr_guice_restlet/solr/core/ivy.xml Mon Aug 5 10:51:48 2013
@@ -55,6 +55,18 @@
<dependency org="com.google.protobuf" name="protobuf-java" rev="2.4.0a" conf="compile.hadoop->*"/>
<dependency org="com.googlecode.concurrentlinkedhashmap" name="concurrentlinkedhashmap-lru" rev="1.2" conf="compile.hadoop->*"/>
+ <dependency org="com.google.inject" name="guice" rev="3.0" conf="compile->*"/>
+ <dependency org="com.google.inject.extensions" name="guice-multibindings" rev="3.0" conf="compile->*"/>
+ <dependency org="com.google.inject.extensions" name="guice-servlet" rev="3.0" conf="compile->*"/>
+ <dependency org="javax.inject" name="javax.inject" rev="1" conf="compile->*"/>
+ <dependency org="aopalliance" name="aopalliance" rev="1.0" conf="compile->*"/>
+ <!--<dependency org="javax.inject" name="javax.inject" rev="1" conf="compile->*"/>-->
+ <!--<dependency org="javax.inject" name="javax.inject-tck" rev="" conf="compile->*"/>-->
+ <!--<dependency org="org.sonatype.sisu.inject" name="cglib" rev="2.2.1-v20090111" conf="compile->*"/>
+ <dependency org="org.sonatype.sisu.inject" name="cglib" rev="" conf="compile->*"/>-->
+
+
+
<!-- Hadoop DfsMiniCluster Dependencies-->
<dependency org="org.apache.hadoop" name="hadoop-common" rev="&hadoop.version;" conf="test.DfsMiniCluster->*">
<artifact name="hadoop-common" type="test" ext="jar" maven:classifier="tests" />
Modified: lucene/dev/branches/solr_guice_restlet/solr/core/src/java/org/apache/solr/core/CoreContainer.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/solr_guice_restlet/solr/core/src/java/org/apache/solr/core/CoreContainer.java?rev=1510425&r1=1510424&r2=1510425&view=diff
==============================================================================
--- lucene/dev/branches/solr_guice_restlet/solr/core/src/java/org/apache/solr/core/CoreContainer.java (original)
+++ lucene/dev/branches/solr_guice_restlet/solr/core/src/java/org/apache/solr/core/CoreContainer.java Mon Aug 5 10:51:48 2013
@@ -18,6 +18,7 @@
package org.apache.solr.core;
import com.google.common.collect.Maps;
+import com.google.inject.Singleton;
import org.apache.solr.cloud.ZkController;
import org.apache.solr.cloud.ZkSolrResourceLoader;
import org.apache.solr.common.SolrException;
@@ -66,6 +67,7 @@ import static com.google.common.base.Pre
*
* @since solr 1.3
*/
+@Singleton
public class CoreContainer {
protected static final Logger log = LoggerFactory.getLogger(CoreContainer.class);
@@ -100,7 +102,7 @@ public class CoreContainer {
{
log.info("New CoreContainer " + System.identityHashCode(this));
}
-
+ //TODO: simplify this stuff.
/**
* Create a new CoreContainer using system properties to detect the solr home
* directory. The container's cores are not loaded.
Added: lucene/dev/branches/solr_guice_restlet/solr/core/src/java/org/apache/solr/core/CoreContainerAPI.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/solr_guice_restlet/solr/core/src/java/org/apache/solr/core/CoreContainerAPI.java?rev=1510425&view=auto
==============================================================================
--- lucene/dev/branches/solr_guice_restlet/solr/core/src/java/org/apache/solr/core/CoreContainerAPI.java (added)
+++ lucene/dev/branches/solr_guice_restlet/solr/core/src/java/org/apache/solr/core/CoreContainerAPI.java Mon Aug 5 10:51:48 2013
@@ -0,0 +1,60 @@
+package org.apache.solr.core;
+
+
+import com.google.inject.Inject;
+import com.google.inject.Singleton;
+import org.apache.solr.request.SolrRequestHandler;
+import org.apache.solr.rest.API;
+import org.apache.solr.rest.ResourceFinder;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ *
+ *
+ **/
+@Singleton
+public class CoreContainerAPI extends API {
+ //TODO: move this someplace common
+ public static final String CORE_NAME = "/{coreName}";
+ private transient static Logger log = LoggerFactory.getLogger(CoreContainerAPI.class);
+ private final CoreContainer coreContainer;
+
+ @Inject
+ public CoreContainerAPI(ResourceFinder finder, CoreContainer coreContainer) {
+ super(finder);
+ this.coreContainer = coreContainer;
+ }
+
+ @Override
+ protected void initAttachments() {
+ //TODO: how to handle new cores?
+ Set<String> seen = new HashSet<>();
+ for (SolrCore solrCore : coreContainer.getCores()) {
+ SolrConfig config = solrCore.getSolrConfig();
+ String coreName = solrCore.getName();
+
+ for (Map.Entry<String, SolrRequestHandler> entry : solrCore.getRequestHandlers().entrySet()) {
+ if (seen.contains(entry.getKey()) == false) {
+ log.info("Attach: " + entry.getKey());
+ attach(CORE_NAME + "/" + entry.getKey(), CoreContainerProxySR.class);
+ seen.add(entry.getKey());
+ }
+ }
+ }
+ }
+
+ @Override
+ public String getAPIRoot() {
+ return "/collections"; //TODO: change?
+ }
+
+ @Override
+ public String getAPIName() {
+ return "CORE";
+ }
+}
Added: lucene/dev/branches/solr_guice_restlet/solr/core/src/java/org/apache/solr/core/CoreContainerAPIModule.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/solr_guice_restlet/solr/core/src/java/org/apache/solr/core/CoreContainerAPIModule.java?rev=1510425&view=auto
==============================================================================
--- lucene/dev/branches/solr_guice_restlet/solr/core/src/java/org/apache/solr/core/CoreContainerAPIModule.java (added)
+++ lucene/dev/branches/solr_guice_restlet/solr/core/src/java/org/apache/solr/core/CoreContainerAPIModule.java Mon Aug 5 10:51:48 2013
@@ -0,0 +1,19 @@
+package org.apache.solr.core;
+
+
+import org.apache.solr.rest.APIModule;
+
+/**
+ *
+ *
+ **/
+public class CoreContainerAPIModule extends APIModule {
+
+ @Override
+ protected void defineBindings() {
+ CoreContainer cores = new CoreContainer();
+ cores.load();
+ bind(CoreContainer.class).toInstance(cores);
+ bind(CoreContainerResource.class).to(CoreContainerProxySR.class);
+ }
+}
Added: lucene/dev/branches/solr_guice_restlet/solr/core/src/java/org/apache/solr/core/CoreContainerProxySR.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/solr_guice_restlet/solr/core/src/java/org/apache/solr/core/CoreContainerProxySR.java?rev=1510425&view=auto
==============================================================================
--- lucene/dev/branches/solr_guice_restlet/solr/core/src/java/org/apache/solr/core/CoreContainerProxySR.java (added)
+++ lucene/dev/branches/solr_guice_restlet/solr/core/src/java/org/apache/solr/core/CoreContainerProxySR.java Mon Aug 5 10:51:48 2013
@@ -0,0 +1,59 @@
+package org.apache.solr.core;
+
+
+import com.google.inject.Inject;
+import com.google.inject.Singleton;
+import org.apache.solr.request.SolrQueryRequestDecoder;
+import org.apache.solr.request.SolrRequestHandler;
+import org.apache.solr.rest.BaseCoreResource;
+import org.restlet.representation.Representation;
+import org.restlet.resource.ResourceException;
+
+/**
+ *
+ *
+ **/
+@Singleton
+public class CoreContainerProxySR extends BaseCoreResource implements CoreContainerResource {
+ protected CoreContainer coreContainer;
+ protected SolrRequestHandler requestHandler;
+
+ @Inject
+ public CoreContainerProxySR(SolrQueryRequestDecoder requestDecoder, CoreContainer coreContainer) {
+ super(requestDecoder);
+ this.coreContainer = coreContainer;
+ }
+
+ @Override
+ protected SolrCore findCore() {
+ String coreName = (String) getRequest().getAttributes().get("coreName");
+ if (coreName != null) {
+ return coreContainer.getCore(coreName);
+ }
+ return null;
+ }
+
+ @Override
+ protected void setupResource() {
+
+ super.setupResource();
+ String handlerName = getReference().getLastSegment();
+ requestHandler = solrCore.getRequestHandler("/" + handlerName);
+ if (handlerName == null) {
+ requestHandler = solrCore.getRequestHandler(handlerName);
+ }
+ }
+
+ @Override
+ public Representation get() throws ResourceException {
+ requestHandler.handleRequest(request, getSolrResponse());
+ return new SolrOutputRepresentation();
+ }
+
+ @Override
+ public Representation post(Representation entity) throws ResourceException {
+ requestHandler.handleRequest(request, getSolrResponse());
+ return new SolrOutputRepresentation();
+ }
+
+}
Added: lucene/dev/branches/solr_guice_restlet/solr/core/src/java/org/apache/solr/core/CoreContainerResource.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/solr_guice_restlet/solr/core/src/java/org/apache/solr/core/CoreContainerResource.java?rev=1510425&view=auto
==============================================================================
--- lucene/dev/branches/solr_guice_restlet/solr/core/src/java/org/apache/solr/core/CoreContainerResource.java (added)
+++ lucene/dev/branches/solr_guice_restlet/solr/core/src/java/org/apache/solr/core/CoreContainerResource.java Mon Aug 5 10:51:48 2013
@@ -0,0 +1,19 @@
+package org.apache.solr.core;
+
+
+import org.apache.solr.rest.GETable;
+import org.apache.solr.rest.POSTable;
+import org.restlet.representation.Representation;
+import org.restlet.resource.ResourceException;
+
+/**
+ *
+ *
+ **/
+public interface CoreContainerResource extends GETable, POSTable {
+ @Override
+ public Representation get();
+
+ @Override
+ public Representation post(Representation entity) throws ResourceException;
+}
Modified: lucene/dev/branches/solr_guice_restlet/solr/core/src/java/org/apache/solr/core/SolrCore.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/solr_guice_restlet/solr/core/src/java/org/apache/solr/core/SolrCore.java?rev=1510425&r1=1510424&r2=1510425&view=diff
==============================================================================
--- lucene/dev/branches/solr_guice_restlet/solr/core/src/java/org/apache/solr/core/SolrCore.java (original)
+++ lucene/dev/branches/solr_guice_restlet/solr/core/src/java/org/apache/solr/core/SolrCore.java Mon Aug 5 10:51:48 2013
@@ -1914,9 +1914,10 @@ public final class SolrCore implements S
}
-
+ //TODO: make this stuff injectable
private QueryResponseWriter defaultResponseWriter;
private final Map<String, QueryResponseWriter> responseWriters = new HashMap<String, QueryResponseWriter>();
+
public static final Map<String ,QueryResponseWriter> DEFAULT_RESPONSE_WRITERS ;
static{
HashMap<String, QueryResponseWriter> m= new HashMap<String, QueryResponseWriter>();
Modified: lucene/dev/branches/solr_guice_restlet/solr/core/src/java/org/apache/solr/package.html
URL: http://svn.apache.org/viewvc/lucene/dev/branches/solr_guice_restlet/solr/core/src/java/org/apache/solr/package.html?rev=1510425&r1=1510424&r2=1510425&view=diff
==============================================================================
--- lucene/dev/branches/solr_guice_restlet/solr/core/src/java/org/apache/solr/package.html (original)
+++ lucene/dev/branches/solr_guice_restlet/solr/core/src/java/org/apache/solr/package.html Mon Aug 5 10:51:48 2013
@@ -25,5 +25,51 @@ Commonly reused classes and interfaces (
</p>
+<!-- Change this to official, once have it all in place, for now use as
+ a scratch pad-->
+<h2>API Planning Scratch Pad</h2>
+
+<h3>Admin</h3>
+<p>
+/admin
+ <ul>
+ <li>/collections</li>
+ <li>/info
+ <!-- New -->
+ <ul><li>/stats</li></ul>
+ </li>
+ <li>/zookeeper</li>
+ <li>/plugins</li>
+ </ul>
+</p>
+<h4>UI</h4>
+<p>
+
+</p>
+<h3>Per Collection</h3>
+<p>
+/collections/{collection}
+ <ul>
+ <li>/schema
+ <ul>/...</ul>
+ </li>
+ <!-- New -->
+ <li>/config
+ <ul>
+ <li></li></ul></li>
+ <li>/documents -- Access to documents, not everything is a "search", so just capture it here in that we are operating over documents. Similar to Select.
+ Post handles adding multiple documents
+ <ul>
+ <li>/{id} -- Realtime get, Update at a per document level</li>
+ </ul></li>
+ </ul>
+</p>
+<h4>Request Handlers</h4>
+
+<h3>Legacy</h3>
+<p></p>
+<h2>Security</h2>
+<p>Restlet makes it incredibly easy to offer HTTPS and Authorization schemes. We should
+take advantage of this to secure the APIs</p>
</body>
</html>
Added: lucene/dev/branches/solr_guice_restlet/solr/core/src/java/org/apache/solr/request/SolrQueryRequestDecoder.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/solr_guice_restlet/solr/core/src/java/org/apache/solr/request/SolrQueryRequestDecoder.java?rev=1510425&view=auto
==============================================================================
--- lucene/dev/branches/solr_guice_restlet/solr/core/src/java/org/apache/solr/request/SolrQueryRequestDecoder.java (added)
+++ lucene/dev/branches/solr_guice_restlet/solr/core/src/java/org/apache/solr/request/SolrQueryRequestDecoder.java Mon Aug 5 10:51:48 2013
@@ -0,0 +1,26 @@
+package org.apache.solr.request;
+
+
+import org.apache.solr.core.SolrCore;
+
+/**
+ * Given some raw input (such as an HttpRequest), create a SolrQueryRequest
+ *
+ **/
+public interface SolrQueryRequestDecoder {
+
+ /**
+ *
+ * @return The Decoded SolrQueryRequest
+ * @throws Exception
+ */
+ SolrQueryRequest decode() throws Exception;
+
+ /**
+ * Decode in the context of a {@link org.apache.solr.core.SolrCore}.
+ * @param core The core
+ * @return the {@link org.apache.solr.request.SolrQueryRequest}
+ * @throws Exception
+ */
+ SolrQueryRequest decode(SolrCore core) throws Exception;
+}
Added: lucene/dev/branches/solr_guice_restlet/solr/core/src/java/org/apache/solr/rest/API.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/solr_guice_restlet/solr/core/src/java/org/apache/solr/rest/API.java?rev=1510425&view=auto
==============================================================================
--- lucene/dev/branches/solr_guice_restlet/solr/core/src/java/org/apache/solr/rest/API.java (added)
+++ lucene/dev/branches/solr_guice_restlet/solr/core/src/java/org/apache/solr/rest/API.java Mon Aug 5 10:51:48 2013
@@ -0,0 +1,265 @@
+package org.apache.solr.rest;
+
+
+import org.apache.solr.common.util.NamedList;
+import org.apache.solr.core.SolrInfoMBean;
+import org.restlet.Application;
+import org.restlet.Request;
+import org.restlet.Response;
+import org.restlet.Restlet;
+import org.restlet.resource.ServerResource;
+import org.restlet.routing.Redirector;
+import org.restlet.routing.Route;
+import org.restlet.routing.Router;
+import org.restlet.security.Authenticator;
+import org.restlet.security.Role;
+import org.restlet.security.RoleAuthorizer;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.net.URI;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ *
+ *
+ **/
+public abstract class API extends Application implements APIMBean {
+ private transient static Logger log = LoggerFactory.getLogger(API.class);
+ protected Router router;
+ protected ResourceFinder finder;
+ protected Collection<String> paths;
+
+ //stats
+ volatile long numRequests;
+ volatile long numErrors;
+ volatile long totalTime = 0;
+ long handlerStart = System.currentTimeMillis();
+
+ protected API(ResourceFinder finder) {
+ this.finder = finder;
+ paths = new ArrayList<String>();
+ }
+
+ @Override
+ public Restlet createInboundRoot() {
+ router = new Router(getContext());
+ Restlet guard = guardPossibly();
+ initAttachments();
+ return guard;
+ }
+
+ /**
+ * API's that wish to put guards on the Router should override this method with
+ * the appropriate wrapping of the Router. The default is to not
+ * guard.
+ *
+ * @return The Restlet, either the Router or the Guarded Router.
+ */
+ protected Restlet guardPossibly() {
+ return router;
+ }
+
+ //Override so we can instrument it
+
+ /**
+ * Derived classes can override this with per API statistics
+ */
+ @Override
+ public void handle(Request request, Response response) {
+ logStart(request, response);
+ long start = System.currentTimeMillis();
+ super.handle(request, response);
+ long finish = System.currentTimeMillis();
+ if (response.getStatus().isError()) {
+ numErrors++;
+ }
+ long diff = finish - start;
+ if (log.isInfoEnabled() && request.isLoggable()) {
+ log.info(getAPIName() + "/" + getAPIRoot() + " took " + diff + " ms");
+ }
+ totalTime += diff;
+ logFinish(request, response);
+ numRequests++;
+ }
+
+ /**
+ * Provides an easy way for overriding classes to log details about the request/response that are pertinent to that API instead
+ * of logging everything in the request. Is called after all things have finished in the {@link #handle(org.restlet.Request, org.restlet.Response)} method.
+ * <p/>
+ * By default, logs number of requests, request.toString and response.toString.
+ *
+ * @param request The {@link org.restlet.Request}
+ * @param response The {@link org.restlet.Response}
+ */
+ protected void logFinish(Request request, Response response) {
+ if (log.isInfoEnabled() && request.isLoggable()) {
+ log.info("Finish Req #: " + numRequests + " Req: " + request.toString() + " Rsp: " + response.toString());
+ }
+ }
+
+ /**
+ * Provides an easy way for overriding classes to log details about the request/response that are pertinent to that API instead
+ * of logging everything in the request. Is called after all things have finished in the {@link #handle(org.restlet.Request, org.restlet.Response)} method.
+ * <p/>
+ * By default, the number of requests and request.toString() are logged at the info level.
+ *
+ * @param request The {@link org.restlet.Request}
+ * @param response The {@link org.restlet.Response}
+ */
+ protected void logStart(Request request, Response response) {
+ if (log.isInfoEnabled() && request.isLoggable()) {
+ log.info("Start Req #: " + numRequests + " Req: " + request.toString());
+ }
+ }
+
+ protected Route attach(String path, Class<? extends ServerResource> resource) {
+ return attach(path, router, resource, (Role[]) null);
+ }
+
+ protected Route attach(String path, Router base, Class<? extends ServerResource> resource) {
+ return attach(path, base, resource, (Role[]) null);
+ }
+
+ protected Route attach(String path, Router base, Class<? extends ServerResource> resource, Role... roles) {
+ return attach(path, base, resource, roles != null && roles.length > 0 ? Arrays.asList(roles) : null);
+ }
+
+ protected Route attach(String path, Router base, Class<? extends ServerResource> resource, List<Role> roles) {
+ Restlet attachment = null;
+ if (roles != null && roles.isEmpty() == false) {
+ RoleAuthorizer ra = new RoleAuthorizer();
+ ra.getAuthorizedRoles().addAll(roles);
+ ra.setNext(finder.finderOf(resource));
+ attachment = ra;
+ } else {
+ attachment = finder.finderOf(resource);
+ }
+ return attach(path, base, attachment, (Authenticator) null);
+ }
+
+ protected Route attach(String path, Router base, Class<? extends ServerResource> resource, Authenticator authenticator) {
+ return attach(path, base, finder.finderOf(resource), authenticator);
+ }
+
+ protected Route attach(String path, Router base, Restlet restlet) {
+ return attach(path, base, restlet, (Authenticator) null);
+ }
+
+ protected Route attach(String path, Router base, Restlet restlet, Authenticator authenticator) {
+ return attach(path, base, restlet, authenticator, Router.MODE_BEST_MATCH);
+ }
+
+ protected Route attach(String path, Router base, Restlet restlet, Authenticator authenticator, int mode) {
+ Route result;
+ if (authenticator != null) {
+ authenticator.setNext(restlet);
+ result = base.attach(path, authenticator, mode);
+ } else {
+ result = base.attach(path, restlet, mode);
+ }
+ if (path.equals("")) {
+ path = "/";
+ }
+ paths.add(path);
+ return result;
+ }
+
+ protected void redir(URI uri,
+ Router base,
+ String attach,
+ String path, Role... roles) {
+ Restlet attachment;
+ Redirector redir = new Redirector(router.getContext(),
+ uri.toString() + path,
+ Redirector.MODE_SERVER_OUTBOUND);
+ if (roles != null && roles.length > 0) {
+ attachment = getRoleAuthorizer(redir, roles);
+ } else {
+ attachment = redir;
+ }
+ attach(attach, base, attachment);
+ }
+
+
+ protected RoleAuthorizer getRoleAuthorizer(Restlet next, Role... roles) {
+ RoleAuthorizer ra = new RoleAuthorizer();
+ ra.getAuthorizedRoles().addAll(Arrays.asList(roles));
+ ra.setNext(next);
+ return ra;
+ }
+
+ /**
+ * Overriding classes implement this method in order to attach resources (ServerResource) to specific endpoints.
+ */
+ protected abstract void initAttachments();
+
+ /**
+ * The root to attach this API to. Must not be the empty string.
+ *
+ * @return
+ */
+ public abstract String getAPIRoot();
+
+ public abstract String getAPIName();
+
+ @Override
+ public void stop() throws Exception {
+ if (router != null) {
+ router.stop();
+ }
+ }
+
+ @Override
+ public Collection<String> getEndpoints() {
+ return paths;
+ }
+
+ @Override
+ public NamedList getStatistics() {
+
+ NamedList namedList = new NamedList();
+ namedList.add("numRequests", numRequests);
+ namedList.add("numErrors", numErrors);
+ namedList.add("totalTime", totalTime);
+ namedList.add("startTime", handlerStart);
+ return namedList;
+ }
+
+
+ //TODO: Can we automate all of these so people don't need to to it themselves?
+ @Override
+ public String getVersion() {
+ String result = null;
+ return result;
+ }
+
+ @Override
+ public Category getCategory() {
+ Category result = null;
+ return result;
+ }
+
+ @Override
+ public String getSource() {
+ String result = null;
+ return result;
+ }
+
+ @Override
+ public URL[] getDocs() {
+ URL[] result = new URL[0];
+ return result;
+ }
+
+ @Override
+ public String getName() {
+ return getAPIName();
+ }
+}
\ No newline at end of file
Added: lucene/dev/branches/solr_guice_restlet/solr/core/src/java/org/apache/solr/rest/APIMBean.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/solr_guice_restlet/solr/core/src/java/org/apache/solr/rest/APIMBean.java?rev=1510425&view=auto
==============================================================================
--- lucene/dev/branches/solr_guice_restlet/solr/core/src/java/org/apache/solr/rest/APIMBean.java (added)
+++ lucene/dev/branches/solr_guice_restlet/solr/core/src/java/org/apache/solr/rest/APIMBean.java Mon Aug 5 10:51:48 2013
@@ -0,0 +1,14 @@
+package org.apache.solr.rest;
+
+
+import org.apache.solr.core.SolrInfoMBean;
+
+import java.util.Collection;
+
+/**
+ *
+ *
+ **/
+public interface APIMBean extends SolrInfoMBean {
+ public Collection<String> getEndpoints();
+}
\ No newline at end of file
Added: lucene/dev/branches/solr_guice_restlet/solr/core/src/java/org/apache/solr/rest/APIModule.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/solr_guice_restlet/solr/core/src/java/org/apache/solr/rest/APIModule.java?rev=1510425&view=auto
==============================================================================
--- lucene/dev/branches/solr_guice_restlet/solr/core/src/java/org/apache/solr/rest/APIModule.java (added)
+++ lucene/dev/branches/solr_guice_restlet/solr/core/src/java/org/apache/solr/rest/APIModule.java Mon Aug 5 10:51:48 2013
@@ -0,0 +1,63 @@
+package org.apache.solr.rest;
+
+
+import com.google.inject.AbstractModule;
+import com.google.inject.Inject;
+import com.google.inject.Injector;
+import com.google.inject.Provider;
+import com.google.inject.multibindings.Multibinder;
+import org.apache.solr.request.SolrQueryRequest;
+import org.apache.solr.request.SolrQueryRequestDecoder;
+
+/**
+ *
+ *
+ **/
+public abstract class APIModule extends AbstractModule {
+
+ @Inject
+ protected Injector injector;
+
+
+
+ /**
+ * Classes who extend and who's API implementation does not conform to the convention
+ * of being of the same name as the APIModule implementing class or is not in the same
+ * package as the APIModule implementing should override this class. For instance
+ * if your module is FooAPIModule, then by convention this method will look for FooAPI as the API class.
+ *
+ * @return The {@link org.apache.solr.rest.API} class tied to this Module
+ */
+ public Class<? extends API> getAPIClass() {
+ String className = this.getClass().getName();
+ className = className.replace("Module", "");
+ try {
+ return Class.forName(className).asSubclass(API.class);
+ } catch (ClassNotFoundException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ protected abstract void defineBindings();
+
+
+
+ @Override
+ protected void configure() {
+ //TODO
+
+ Multibinder< API > apiBinder = Multibinder.newSetBinder(binder(), API.class);
+ apiBinder.addBinding().to(getAPIClass());
+
+ defineBindings();
+ }
+
+ /**
+ * This method is called when all modules are already configured, Injector has
+ * been created and injected locally, but before the APIServer starts.
+ */
+ public void initInjectorDependent() {
+
+ }
+}
+
Added: lucene/dev/branches/solr_guice_restlet/solr/core/src/java/org/apache/solr/rest/BaseCoreResource.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/solr_guice_restlet/solr/core/src/java/org/apache/solr/rest/BaseCoreResource.java?rev=1510425&view=auto
==============================================================================
--- lucene/dev/branches/solr_guice_restlet/solr/core/src/java/org/apache/solr/rest/BaseCoreResource.java (added)
+++ lucene/dev/branches/solr_guice_restlet/solr/core/src/java/org/apache/solr/rest/BaseCoreResource.java Mon Aug 5 10:51:48 2013
@@ -0,0 +1,134 @@
+package org.apache.solr.rest;
+
+
+import org.apache.solr.common.params.CommonParams;
+import org.apache.solr.common.params.ModifiableSolrParams;
+import org.apache.solr.core.SolrCore;
+import org.apache.solr.request.SolrQueryRequestDecoder;
+import org.apache.solr.response.QueryResponseWriter;
+import org.apache.solr.schema.IndexSchema;
+import org.restlet.data.Status;
+import org.restlet.resource.ResourceException;
+import org.slf4j.Logger;
+
+import java.io.UnsupportedEncodingException;
+import java.net.URLDecoder;
+
+/**
+ *
+ *
+ **/
+public abstract class BaseCoreResource extends BaseResource {
+
+ protected boolean doIndent;
+ protected SolrCore solrCore;
+ protected IndexSchema schema;
+ protected QueryResponseWriter responseWriter;
+
+
+ public BaseCoreResource(SolrQueryRequestDecoder requestDecoder) {
+ super(requestDecoder);
+ doIndent = true; // default to indenting
+ }
+
+
+ /**
+ * Decode URL-encoded strings as UTF-8, and avoid converting "+" to space
+ */
+ protected static String urlDecode(String str) throws UnsupportedEncodingException {
+ return URLDecoder.decode(str.replace("+", "%2B"), "UTF-8");
+ }
+
+ protected SolrCore getSolrCore() {
+ return solrCore;
+ }
+
+ protected IndexSchema getSchema() {
+ return schema;
+ }
+
+
+ /**
+ * @return the response writer from this core
+ */
+ @Override
+ protected QueryResponseWriter getResponseWriter() {
+ return responseWriter;
+ }
+
+ @Override
+ protected void setupResource() {
+ solrCore = request.getCore();
+ schema = request.getSchema();
+ String responseWriterName = request.getParams().get(CommonParams.WT);
+ if (null == responseWriterName) {
+ responseWriterName = "json"; // Default to json writer
+ }
+ String indent = request.getParams().get("indent");
+ if (null != indent && ("".equals(indent) || "off".equals(indent))) {
+ doIndent = false;
+ } else { // indent by default
+ ModifiableSolrParams newParams = new ModifiableSolrParams(request.getParams());
+ newParams.remove(indent);
+ newParams.add("indent", "on");
+ request.setParams(newParams);
+ }
+ responseWriter = solrCore.getQueryResponseWriter(responseWriterName);
+ contentType = responseWriter.getContentType(request, solrResponse);
+ final String path = getRequest().getRootRef().getPath();
+ //TODO: fix this?
+ if (!"/schema".equals(path)) {
+ // don't set webapp property on the request when context and core/collection are excluded
+ final int cutoffPoint = path.indexOf("/", 1);
+ final String firstPathElement = -1 == cutoffPoint ? path : path.substring(0, cutoffPoint);
+ request.getContext().put("webapp", firstPathElement); // Context path
+ }
+ SolrCore.preDecorateResponse(request, solrResponse);
+ }
+
+ /**
+ * Override so that we can use the core
+ */
+ @Override
+ protected void decodeRequest() {
+ solrCore = findCore();
+ if (solrCore != null) {
+ try {
+ request = requestProvider.decode(solrCore);
+ } catch (Exception e) {
+ throw new ResourceException(e);
+ }
+ } else {
+ throw new ResourceException(Status.CLIENT_ERROR_BAD_REQUEST, "Couldn't find a Solr Core in the request");
+ }
+ }
+
+ /**
+ * Derived classes must speficy a way to find the core from the Request
+ * @return The {@link org.apache.solr.core.SolrCore} for this request.
+ */
+ protected abstract SolrCore findCore();
+
+ /**
+ * Pulls the SolrQueryRequest constructed in SolrDispatchFilter
+ * from the SolrRequestInfo thread local, then gets the SolrCore
+ * and IndexSchema and sets up the response.
+ * writer.
+ * <p/>
+ * If an error occurs during initialization, setExisting(false) is
+ * called and an error status code and message is set; in this case,
+ * Restlet will not continue servicing the request (by calling the
+ * method annotated to associate it with GET, etc., but rather will
+ * send an error response.
+ */
+
+
+ @Override
+ protected void handlePostExecution(Logger log) {
+ super.handlePostExecution(log);
+ if (log.isInfoEnabled() && solrResponse.getToLog().size() > 0) {
+ log.info(solrResponse.getToLogAsString(solrCore.getLogId()));
+ }
+ }
+
+}
Added: lucene/dev/branches/solr_guice_restlet/solr/core/src/java/org/apache/solr/rest/BaseResource.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/solr_guice_restlet/solr/core/src/java/org/apache/solr/rest/BaseResource.java?rev=1510425&view=auto
==============================================================================
--- lucene/dev/branches/solr_guice_restlet/solr/core/src/java/org/apache/solr/rest/BaseResource.java (added)
+++ lucene/dev/branches/solr_guice_restlet/solr/core/src/java/org/apache/solr/rest/BaseResource.java Mon Aug 5 10:51:48 2013
@@ -0,0 +1,180 @@
+package org.apache.solr.rest;
+
+
+import com.google.inject.Inject;
+import com.google.inject.Injector;
+import org.apache.solr.common.params.CommonParams;
+import org.apache.solr.common.util.ContentStreamBase;
+import org.apache.solr.common.util.NamedList;
+import org.apache.solr.common.util.SimpleOrderedMap;
+import org.apache.solr.core.SolrCore;
+import org.apache.solr.request.SolrQueryRequest;
+import org.apache.solr.request.SolrQueryRequestDecoder;
+import org.apache.solr.response.BinaryQueryResponseWriter;
+import org.apache.solr.response.QueryResponseWriter;
+import org.apache.solr.response.SolrQueryResponse;
+import org.apache.solr.servlet.ResponseUtils;
+import org.apache.solr.util.FastWriter;
+import org.restlet.data.MediaType;
+import org.restlet.data.Method;
+import org.restlet.data.Status;
+import org.restlet.representation.OutputRepresentation;
+import org.restlet.resource.ResourceException;
+import org.restlet.resource.ServerResource;
+import org.slf4j.Logger;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.io.Writer;
+import java.nio.charset.Charset;
+
+/**
+ *
+ *
+ **/
+public abstract class BaseResource extends ServerResource {
+
+ private static final Charset UTF8 = Charset.forName("UTF-8");
+ protected final SolrQueryRequestDecoder requestProvider;
+ protected SolrQueryRequest request;
+ protected SolrQueryResponse solrResponse = new SolrQueryResponse();
+
+ protected String contentType;
+ @Inject
+ Injector injector;
+
+
+ public BaseResource(SolrQueryRequestDecoder requestDecoder) {
+ this.requestProvider = requestDecoder;
+ }
+
+ @Override
+ protected void doInit() throws ResourceException {
+ setNegotiated(false); // Turn off content negotiation for now
+ //Decode the solrRequest -- do this first
+ decodeRequest();
+ //Setup the resource once we have the request
+ setupResource();
+
+ }
+
+ /**
+ * Overridding classes should implement to do custom parsing of the request, for
+ * instance to get the core, etc.
+ *
+ * This is called before {@link #decodeRequest()}
+ */
+ protected void setupResource(){}
+
+ /**
+ * Decodes the request, assuming no core
+ */
+ protected void decodeRequest() {
+ try {
+ request = requestProvider.decode();
+ } catch (Exception e) {
+ throw new ResourceException(e);
+ }
+ }
+
+ protected SolrQueryRequest getSolrRequest() {
+
+ return request;
+ }
+
+ protected SolrQueryResponse getSolrResponse() {
+ return solrResponse;
+ }
+
+ protected String getContentType() {
+ return contentType;
+ }
+
+ /**
+ * If there is an exception on the SolrResponse:
+ * <ul>
+ * <li>error info is added to the SolrResponse;</li>
+ * <li>the response status code is set to the error code from the exception; and</li>
+ * <li>the exception message is added to the list of things to be logged.</li>
+ * </ul>
+ */
+ protected void handleException(Logger log) {
+ Exception exception = getSolrResponse().getException();
+ if (null != exception) {
+ NamedList info = new SimpleOrderedMap();
+ int code = ResponseUtils.getErrorInfo(exception, info, log);
+ setStatus(Status.valueOf(code));
+ getSolrResponse().add("error", info);
+ String message = (String) info.get("msg");
+ if (null != message && !message.trim().isEmpty()) {
+ getSolrResponse().getToLog().add("msg", "{" + message.trim() + "}");
+ }
+ }
+ }
+
+ /**
+ * Deal with an exception on the SolrResponse, fill in response header info,
+ * and log the accumulated messages on the SolrResponse.
+ */
+ protected void handlePostExecution(Logger log) {
+
+ handleException(log);
+
+ // TODO: should status=0 (success?) be left as-is in the response header?
+ SolrCore.postDecorateResponse(null, getSolrRequest(), getSolrResponse());
+
+
+ }
+
+ /**
+ * @return a default ResponseWriter
+ */
+ protected QueryResponseWriter getResponseWriter() {
+ String responseWriterName = getSolrRequest().getParams().get(CommonParams.WT);
+ if (null == responseWriterName) {
+ responseWriterName = "json"; // Default to json writer
+ }
+ return SolrCore.DEFAULT_RESPONSE_WRITERS.get(responseWriterName);
+ }
+
+
+ //TODO: is there a way to inject this
+
+ /**
+ * This class serves as an adapter between Restlet and Solr's response writers.
+ */
+ public class SolrOutputRepresentation extends OutputRepresentation {
+
+
+ public SolrOutputRepresentation() {
+ // No normalization, in case of a custom media type
+ super(MediaType.valueOf(contentType));
+ // TODO: For now, don't send the Vary: header, but revisit if/when content negotiation is added
+ getDimensions().clear();
+ }
+
+
+ /**
+ * Called by Restlet to get the response body
+ */
+ @Override
+ public void write(OutputStream outputStream) throws IOException {
+ if (getRequest().getMethod() != Method.HEAD) {
+ QueryResponseWriter responseWriter = getResponseWriter();
+ if (responseWriter instanceof BinaryQueryResponseWriter) {
+ BinaryQueryResponseWriter binWriter = (BinaryQueryResponseWriter) responseWriter;
+ binWriter.write(outputStream, getSolrRequest(), getSolrResponse());
+ } else {
+ String charset = ContentStreamBase.getCharsetFromContentType(contentType);
+ Writer out = (charset == null || charset.equalsIgnoreCase("UTF-8"))
+ ? new OutputStreamWriter(outputStream, UTF8)
+ : new OutputStreamWriter(outputStream, charset);
+ out = new FastWriter(out);
+ responseWriter.write(out, getSolrRequest(), getSolrResponse());
+ out.flush();
+ }
+ }
+ }
+ }
+}
Added: lucene/dev/branches/solr_guice_restlet/solr/core/src/java/org/apache/solr/rest/ResourceFinder.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/solr_guice_restlet/solr/core/src/java/org/apache/solr/rest/ResourceFinder.java?rev=1510425&view=auto
==============================================================================
--- lucene/dev/branches/solr_guice_restlet/solr/core/src/java/org/apache/solr/rest/ResourceFinder.java (added)
+++ lucene/dev/branches/solr_guice_restlet/solr/core/src/java/org/apache/solr/rest/ResourceFinder.java Mon Aug 5 10:51:48 2013
@@ -0,0 +1,62 @@
+package org.apache.solr.rest;
+
+
+import com.google.inject.Inject;
+import com.google.inject.Injector;
+import com.google.inject.Key;
+import org.restlet.Request;
+import org.restlet.Response;
+import org.restlet.resource.Finder;
+import org.restlet.resource.ServerResource;
+
+import java.lang.reflect.Type;
+
+/**
+ *
+ *
+ **/
+public class ResourceFinder {
+
+ private volatile Injector injector;
+
+ @Inject
+ public ResourceFinder(Injector injector) {
+ this.injector = injector;
+ }
+
+ public Finder finderOf(Key<? extends ServerResource> key) {
+ return new ServerResourceKeyFinder(key);
+ }
+
+ public Finder finderOf(Class<? extends ServerResource> cls) {
+ return new ServerResourceKeyFinder(Key.get(cls));
+ }
+
+
+ public class KeyFinder extends Finder {
+ private final Class<? extends ServerResource> targetClass;
+
+ KeyFinder(Type type) {
+ this.targetClass = (Class<? extends ServerResource>) type;
+ }
+
+ @Override
+ public final Class<? extends ServerResource> getTargetClass() {
+ return this.targetClass;
+ }
+ }
+
+ public class ServerResourceKeyFinder extends KeyFinder {
+ private final Key<? extends ServerResource> serverResourceKey;
+
+ ServerResourceKeyFinder(Key<? extends ServerResource> serverResourceKey) {
+ super(serverResourceKey.getTypeLiteral().getType());
+ this.serverResourceKey = serverResourceKey;
+ }
+
+ @Override
+ public ServerResource create(Request request, Response response) {
+ return injector.getInstance(serverResourceKey);
+ }
+ }
+}
\ No newline at end of file
Added: lucene/dev/branches/solr_guice_restlet/solr/core/src/java/org/apache/solr/rest/admin/EndpointsResource.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/solr_guice_restlet/solr/core/src/java/org/apache/solr/rest/admin/EndpointsResource.java?rev=1510425&view=auto
==============================================================================
--- lucene/dev/branches/solr_guice_restlet/solr/core/src/java/org/apache/solr/rest/admin/EndpointsResource.java (added)
+++ lucene/dev/branches/solr_guice_restlet/solr/core/src/java/org/apache/solr/rest/admin/EndpointsResource.java Mon Aug 5 10:51:48 2013
@@ -0,0 +1,16 @@
+package org.apache.solr.rest.admin;
+
+
+import org.restlet.resource.Get;
+
+import java.util.Collection;
+import java.util.Map;
+
+/**
+ *
+ *
+ **/
+public interface EndpointsResource {
+ @Get
+ public Map<String, Collection<String>> endpoints();
+}
Added: lucene/dev/branches/solr_guice_restlet/solr/core/src/java/org/apache/solr/rest/admin/EndpointsSR.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/solr_guice_restlet/solr/core/src/java/org/apache/solr/rest/admin/EndpointsSR.java?rev=1510425&view=auto
==============================================================================
--- lucene/dev/branches/solr_guice_restlet/solr/core/src/java/org/apache/solr/rest/admin/EndpointsSR.java (added)
+++ lucene/dev/branches/solr_guice_restlet/solr/core/src/java/org/apache/solr/rest/admin/EndpointsSR.java Mon Aug 5 10:51:48 2013
@@ -0,0 +1,43 @@
+package org.apache.solr.rest.admin;
+
+
+import com.google.inject.Inject;
+import org.apache.solr.request.SolrQueryRequestDecoder;
+import org.apache.solr.rest.API;
+import org.apache.solr.rest.BaseResource;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ *
+ *
+ **/
+public class EndpointsSR extends BaseResource implements EndpointsResource {
+ protected Set<API> apis;
+
+ @Inject
+ public EndpointsSR(SolrQueryRequestDecoder requestDecoder, Set<API> apis) {
+ super(requestDecoder);
+ this.apis = apis;
+ }
+
+
+
+ @Override
+ public Map<String, Collection<String>> endpoints() {
+ Map<String, Collection<String>> result = new HashMap<String, Collection<String>>();
+ for (API api : apis) {
+ Collection<String> uris = result.get(api.getAPIName());
+ if (uris == null) {
+ uris = new HashSet<String>();
+ result.put(api.getAPIName(), uris);
+ }
+ uris.addAll(api.getEndpoints());
+ }
+ return result;
+ }
+}
Added: lucene/dev/branches/solr_guice_restlet/solr/core/src/java/org/apache/solr/rest/admin/InfoResource.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/solr_guice_restlet/solr/core/src/java/org/apache/solr/rest/admin/InfoResource.java?rev=1510425&view=auto
==============================================================================
--- lucene/dev/branches/solr_guice_restlet/solr/core/src/java/org/apache/solr/rest/admin/InfoResource.java (added)
+++ lucene/dev/branches/solr_guice_restlet/solr/core/src/java/org/apache/solr/rest/admin/InfoResource.java Mon Aug 5 10:51:48 2013
@@ -0,0 +1,15 @@
+package org.apache.solr.rest.admin;
+
+
+import org.restlet.resource.Get;
+
+import java.util.Map;
+
+/**
+ *
+ *
+ **/
+public interface InfoResource {
+ @Get
+ public Map<String, Object> info();
+}
Added: lucene/dev/branches/solr_guice_restlet/solr/core/src/java/org/apache/solr/rest/admin/InfoSR.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/solr_guice_restlet/solr/core/src/java/org/apache/solr/rest/admin/InfoSR.java?rev=1510425&view=auto
==============================================================================
--- lucene/dev/branches/solr_guice_restlet/solr/core/src/java/org/apache/solr/rest/admin/InfoSR.java (added)
+++ lucene/dev/branches/solr_guice_restlet/solr/core/src/java/org/apache/solr/rest/admin/InfoSR.java Mon Aug 5 10:51:48 2013
@@ -0,0 +1,72 @@
+package org.apache.solr.rest.admin;
+
+
+import com.google.inject.Inject;
+import org.apache.solr.core.JmxMonitoredMap;
+import org.apache.solr.core.SolrInfoMBean;
+import org.apache.solr.request.SolrQueryRequestDecoder;
+import org.apache.solr.rest.APIMBean;
+import org.apache.solr.rest.BaseResource;
+import org.restlet.resource.Get;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.File;
+import java.io.FileReader;
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Properties;
+
+/**
+ * Provides information about the LWMBeans, with the exception of statistics, as that may be more expensive.
+ */
+public class InfoSR extends BaseResource implements InfoResource {
+ private transient static Logger log = LoggerFactory.getLogger(InfoSR.class);
+
+ public Map<String, Object> infoMap;
+
+ @Inject
+ public InfoSR(SolrQueryRequestDecoder requestDecoder, JmxMonitoredMap<String, APIMBean> jmx) throws IOException {
+ super(requestDecoder);
+
+ File versionFile = new File(System.getProperty("user.dir"), "VERSION.txt");
+ log.info("Looking for Information properties in " + versionFile);
+ Properties props = null;
+ if (versionFile.exists()) {
+ props = new Properties();
+ props.load(new FileReader(versionFile));
+ infoMap = new HashMap<String, Object>(props.size());
+ for (Map.Entry<Object, Object> entry : props.entrySet()) {
+ infoMap.put(entry.getKey().toString(), entry.getValue());
+
+ }
+ } else {
+ //a small development easter egg
+ infoMap = new HashMap<String, Object>();
+ infoMap.put("status", "development");
+ for (Map.Entry<Object, Object> entry : System.getProperties().entrySet()) {
+ infoMap.put(entry.getKey().toString(), entry.getValue());
+ }
+ for (Map.Entry<String, String> entry : System.getenv().entrySet()) {
+ infoMap.put(entry.getKey(), entry.getValue());
+ }
+ }
+ for (Map.Entry<String, SolrInfoMBean> entry : jmx.entrySet()) {
+ Map<String, Object> beanInfoMap = new HashMap<String, Object>();
+ infoMap.put(entry.getValue().getName(), beanInfoMap);
+ beanInfoMap.put("description", entry.getValue().getDescription());
+ if (entry.getValue() instanceof APIMBean) {
+ beanInfoMap.put("endpoints", ((APIMBean) entry.getValue()).getEndpoints());
+ }
+ }
+ }
+
+
+
+ @Override
+ @Get
+ public Map<String, Object> info() {
+ return infoMap;
+ }
+}
Added: lucene/dev/branches/solr_guice_restlet/solr/core/src/java/org/apache/solr/rest/admin/MonitoringAPI.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/solr_guice_restlet/solr/core/src/java/org/apache/solr/rest/admin/MonitoringAPI.java?rev=1510425&view=auto
==============================================================================
--- lucene/dev/branches/solr_guice_restlet/solr/core/src/java/org/apache/solr/rest/admin/MonitoringAPI.java (added)
+++ lucene/dev/branches/solr_guice_restlet/solr/core/src/java/org/apache/solr/rest/admin/MonitoringAPI.java Mon Aug 5 10:51:48 2013
@@ -0,0 +1,52 @@
+package org.apache.solr.rest.admin;
+
+
+import com.google.inject.Inject;
+import com.google.inject.Singleton;
+import org.apache.solr.common.util.NamedList;
+import org.apache.solr.rest.API;
+import org.apache.solr.rest.ResourceFinder;
+
+import java.util.Map;
+
+/**
+ *
+ *
+ **/
+@Singleton
+public class MonitoringAPI extends API {
+ @Inject
+ public MonitoringAPI(ResourceFinder finder) {
+ super(finder);
+ setDescription("Provides info and stats about this server");
+ }
+
+
+ @Override
+ protected void initAttachments() {
+ attach("/info", InfoSR.class);
+ attach("/statistics", StatsSR.class);
+ attach("/endpoints", EndpointsSR.class);
+ }
+
+ @Override
+ public String getAPIRoot() {
+ return "/monitor";
+ }
+
+ @Override
+ public String getAPIName() {
+ return "MONITOR";
+ }
+
+ @Override
+ public NamedList getStatistics() {
+ NamedList result = super.getStatistics();
+ Runtime runtime = Runtime.getRuntime();
+ result.add("freeMemory", runtime.freeMemory());
+ result.add("totalMemory", runtime.totalMemory());
+ result.add("maxMemory", runtime.maxMemory());
+ result.add("availableProcessors", runtime.availableProcessors());
+ return result;
+ }
+}
Added: lucene/dev/branches/solr_guice_restlet/solr/core/src/java/org/apache/solr/rest/admin/MonitoringAPIModule.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/solr_guice_restlet/solr/core/src/java/org/apache/solr/rest/admin/MonitoringAPIModule.java?rev=1510425&view=auto
==============================================================================
--- lucene/dev/branches/solr_guice_restlet/solr/core/src/java/org/apache/solr/rest/admin/MonitoringAPIModule.java (added)
+++ lucene/dev/branches/solr_guice_restlet/solr/core/src/java/org/apache/solr/rest/admin/MonitoringAPIModule.java Mon Aug 5 10:51:48 2013
@@ -0,0 +1,23 @@
+package org.apache.solr.rest.admin;
+
+
+import org.apache.solr.core.JmxMonitoredMap;
+import org.apache.solr.rest.APIModule;
+
+/**
+ * This is an internal API that can be run on each SDAServer. See the Admin service for the main access to this.
+ */
+public class MonitoringAPIModule extends APIModule {
+ private JmxMonitoredMap jmx;
+
+ public MonitoringAPIModule(JmxMonitoredMap jmx) {
+ this.jmx = jmx;
+ }
+
+
+ @Override
+ protected void defineBindings() {
+ bind(InfoResource.class).to(InfoSR.class);
+ bind(JmxMonitoredMap.class).toInstance(jmx);
+ }
+}
Added: lucene/dev/branches/solr_guice_restlet/solr/core/src/java/org/apache/solr/rest/admin/StatsResource.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/solr_guice_restlet/solr/core/src/java/org/apache/solr/rest/admin/StatsResource.java?rev=1510425&view=auto
==============================================================================
--- lucene/dev/branches/solr_guice_restlet/solr/core/src/java/org/apache/solr/rest/admin/StatsResource.java (added)
+++ lucene/dev/branches/solr_guice_restlet/solr/core/src/java/org/apache/solr/rest/admin/StatsResource.java Mon Aug 5 10:51:48 2013
@@ -0,0 +1,15 @@
+package org.apache.solr.rest.admin;
+
+
+import org.restlet.resource.Get;
+
+import java.util.Map;
+
+/**
+ *
+ *
+ **/
+public interface StatsResource {
+ @Get
+ public Map<String, Object> getStatistics();
+}
Added: lucene/dev/branches/solr_guice_restlet/solr/core/src/java/org/apache/solr/rest/admin/StatsSR.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/solr_guice_restlet/solr/core/src/java/org/apache/solr/rest/admin/StatsSR.java?rev=1510425&view=auto
==============================================================================
--- lucene/dev/branches/solr_guice_restlet/solr/core/src/java/org/apache/solr/rest/admin/StatsSR.java (added)
+++ lucene/dev/branches/solr_guice_restlet/solr/core/src/java/org/apache/solr/rest/admin/StatsSR.java Mon Aug 5 10:51:48 2013
@@ -0,0 +1,34 @@
+package org.apache.solr.rest.admin;
+
+
+import com.google.inject.Inject;
+import org.apache.solr.core.JmxMonitoredMap;
+import org.apache.solr.core.SolrInfoMBean;
+import org.apache.solr.request.SolrQueryRequestDecoder;
+import org.apache.solr.rest.BaseResource;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ *
+ *
+ **/
+public class StatsSR extends BaseResource implements StatsResource {
+ private JmxMonitoredMap<String, SolrInfoMBean> jmx;
+
+ @Inject
+ public StatsSR(SolrQueryRequestDecoder requestDecoder, JmxMonitoredMap<String, SolrInfoMBean> jmx) {
+ super(requestDecoder);
+ this.jmx = jmx;
+ }
+
+ @Override
+ public Map<String, Object> getStatistics() {
+ Map<String, Object> result = new HashMap<String, Object>(jmx.size());
+ for (Map.Entry<String, SolrInfoMBean> entry : jmx.entrySet()) {
+ result.put(entry.getKey(), entry.getValue().getStatistics());
+ }
+ return result;
+ }
+}
Added: lucene/dev/branches/solr_guice_restlet/solr/core/src/java/org/apache/solr/rest/ping/PingAPI.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/solr_guice_restlet/solr/core/src/java/org/apache/solr/rest/ping/PingAPI.java?rev=1510425&view=auto
==============================================================================
--- lucene/dev/branches/solr_guice_restlet/solr/core/src/java/org/apache/solr/rest/ping/PingAPI.java (added)
+++ lucene/dev/branches/solr_guice_restlet/solr/core/src/java/org/apache/solr/rest/ping/PingAPI.java Mon Aug 5 10:51:48 2013
@@ -0,0 +1,37 @@
+package org.apache.solr.rest.ping;
+
+
+import com.google.inject.Inject;
+import com.google.inject.Singleton;
+import org.apache.solr.rest.API;
+import org.apache.solr.rest.ResourceFinder;
+
+
+/**
+ * A Trivial API for pinging
+ */
+@Singleton
+public class PingAPI extends API {
+ @Inject
+ public PingAPI(ResourceFinder finder) {
+ super(finder);
+ }
+
+ @Override
+ protected void initAttachments() {
+ attach("", PingSR.class);
+ }
+
+
+ @Override
+ public String getAPIRoot() {
+ return "/ping";
+ }
+
+ @Override
+ public String getAPIName() {
+ return "PING";
+ }
+
+}
+
Added: lucene/dev/branches/solr_guice_restlet/solr/core/src/java/org/apache/solr/rest/ping/PingAPIModule.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/solr_guice_restlet/solr/core/src/java/org/apache/solr/rest/ping/PingAPIModule.java?rev=1510425&view=auto
==============================================================================
--- lucene/dev/branches/solr_guice_restlet/solr/core/src/java/org/apache/solr/rest/ping/PingAPIModule.java (added)
+++ lucene/dev/branches/solr_guice_restlet/solr/core/src/java/org/apache/solr/rest/ping/PingAPIModule.java Mon Aug 5 10:51:48 2013
@@ -0,0 +1,13 @@
+package org.apache.solr.rest.ping;
+
+
+import org.apache.solr.rest.APIModule;
+
+public class PingAPIModule extends APIModule {
+
+ @Override
+ protected void defineBindings() {
+ bind(PingResource.class).to(PingSR.class);
+ }
+
+}
Added: lucene/dev/branches/solr_guice_restlet/solr/core/src/java/org/apache/solr/rest/ping/PingResource.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/solr_guice_restlet/solr/core/src/java/org/apache/solr/rest/ping/PingResource.java?rev=1510425&view=auto
==============================================================================
--- lucene/dev/branches/solr_guice_restlet/solr/core/src/java/org/apache/solr/rest/ping/PingResource.java (added)
+++ lucene/dev/branches/solr_guice_restlet/solr/core/src/java/org/apache/solr/rest/ping/PingResource.java Mon Aug 5 10:51:48 2013
@@ -0,0 +1,15 @@
+package org.apache.solr.rest.ping;
+
+
+import org.apache.solr.rest.GETable;
+import org.restlet.resource.Get;
+
+import java.util.Map;
+
+/**
+ *
+ *
+ **/
+public interface PingResource extends GETable{
+
+}
Added: lucene/dev/branches/solr_guice_restlet/solr/core/src/java/org/apache/solr/rest/ping/PingSR.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/solr_guice_restlet/solr/core/src/java/org/apache/solr/rest/ping/PingSR.java?rev=1510425&view=auto
==============================================================================
--- lucene/dev/branches/solr_guice_restlet/solr/core/src/java/org/apache/solr/rest/ping/PingSR.java (added)
+++ lucene/dev/branches/solr_guice_restlet/solr/core/src/java/org/apache/solr/rest/ping/PingSR.java Mon Aug 5 10:51:48 2013
@@ -0,0 +1,28 @@
+package org.apache.solr.rest.ping;
+
+import com.google.inject.Inject;
+import org.apache.solr.request.SolrQueryRequestDecoder;
+import org.apache.solr.rest.BaseResource;
+import org.restlet.representation.Representation;
+
+/**
+ * Is the server alive? Doesn't mean other API's are alive.
+ */
+//Singleton?
+public class PingSR extends BaseResource implements PingResource {
+
+ @Inject
+ public PingSR(SolrQueryRequestDecoder requestDecoder) {
+ super(requestDecoder);
+ }
+
+
+
+ @Override
+ public Representation get() {
+ getSolrResponse().add("ping", "alive");
+ Representation result = new BaseResource.SolrOutputRepresentation();
+ return result;
+ }
+
+}
Modified: lucene/dev/branches/solr_guice_restlet/solr/core/src/java/org/apache/solr/rest/schema/BaseFieldResource.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/solr_guice_restlet/solr/core/src/java/org/apache/solr/rest/schema/BaseFieldResource.java?rev=1510425&r1=1510424&r2=1510425&view=diff
==============================================================================
--- lucene/dev/branches/solr_guice_restlet/solr/core/src/java/org/apache/solr/rest/schema/BaseFieldResource.java (original)
+++ lucene/dev/branches/solr_guice_restlet/solr/core/src/java/org/apache/solr/rest/schema/BaseFieldResource.java Mon Aug 5 10:51:48 2013
@@ -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.request.SolrQueryRequestDecoder;
import org.apache.solr.schema.IndexSchema;
import org.apache.solr.schema.SchemaField;
import org.restlet.resource.ResourceException;
@@ -36,19 +37,19 @@ abstract class BaseFieldResource extends
private boolean showDefaults;
protected LinkedHashSet<String> getRequestedFields() {
- return requestedFields;
+ return requestedFields;
}
-
- protected BaseFieldResource() {
- super();
+
+ protected BaseFieldResource(SolrQueryRequestDecoder requestDecoder) {
+ super(requestDecoder);
}
/**
* Pulls the "fl" param from the request and splits it to get the
* requested list of fields. The (Dynamic)FieldCollectionResource classes
* will then restrict the fields sent back in the response to those
- * on this list. The (Dynamic)FieldResource classes ignore this list,
+ * on this list. The (Dynamic)FieldResource classes ignore this list,
* since the (dynamic) field is specified in the URL path, rather than
* in a query parameter.
* <p/>
@@ -66,7 +67,7 @@ abstract class BaseFieldResource extends
if (fields.length > 0) {
requestedFields = new LinkedHashSet<String>();
for (String field : fields) {
- if ( ! field.trim().isEmpty()) {
+ if (!field.trim().isEmpty()) {
requestedFields.add(field.trim());
}
}
@@ -76,7 +77,8 @@ abstract class BaseFieldResource extends
}
}
- /** Get the properties for a given field.
+ /**
+ * Get the properties for a given field.
*
* @param field not required to exist in the schema
*/
@@ -85,10 +87,10 @@ abstract class BaseFieldResource extends
return null;
}
SimpleOrderedMap<Object> properties = field.getNamedPropertyValues(showDefaults);
- if ( ! getSchema().getFields().containsKey(field.getName())) {
+ if (!getSchema().getFields().containsKey(field.getName())) {
String dynamicBase = getSchema().getDynamicPattern(field.getName());
// Add dynamicBase property if it's different from the field name.
- if ( ! field.getName().equals(dynamicBase)) {
+ if (!field.getName().equals(dynamicBase)) {
properties.add(DYNAMIC_BASE, dynamicBase);
}
}
Modified: lucene/dev/branches/solr_guice_restlet/solr/core/src/java/org/apache/solr/rest/schema/BaseFieldTypeResource.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/solr_guice_restlet/solr/core/src/java/org/apache/solr/rest/schema/BaseFieldTypeResource.java?rev=1510425&r1=1510424&r2=1510425&view=diff
==============================================================================
--- lucene/dev/branches/solr_guice_restlet/solr/core/src/java/org/apache/solr/rest/schema/BaseFieldTypeResource.java (original)
+++ lucene/dev/branches/solr_guice_restlet/solr/core/src/java/org/apache/solr/rest/schema/BaseFieldTypeResource.java Mon Aug 5 10:51:48 2013
@@ -18,6 +18,7 @@ package org.apache.solr.rest.schema;
*/
import org.apache.solr.common.util.SimpleOrderedMap;
+import org.apache.solr.request.SolrQueryRequestDecoder;
import org.apache.solr.schema.FieldType;
import org.apache.solr.schema.IndexSchema;
import org.restlet.resource.ResourceException;
@@ -30,8 +31,8 @@ import java.util.List;
abstract class BaseFieldTypeResource extends BaseSchemaResource {
private boolean showDefaults;
- protected BaseFieldTypeResource() {
- super();
+ protected BaseFieldTypeResource(SolrQueryRequestDecoder requestDecoder) {
+ super(requestDecoder);
}
@Override
@@ -41,8 +42,10 @@ abstract class BaseFieldTypeResource ext
showDefaults = getSolrRequest().getParams().getBool(SHOW_DEFAULTS, false);
}
}
-
- /** Used by subclasses to collect field type properties */
+
+ /**
+ * Used by subclasses to collect field type properties
+ */
protected SimpleOrderedMap<Object> getFieldTypeProperties(FieldType fieldType) {
SimpleOrderedMap<Object> properties = fieldType.getNamedPropertyValues(showDefaults);
properties.add(IndexSchema.FIELDS, getFieldsWithFieldType(fieldType));
@@ -50,10 +53,14 @@ abstract class BaseFieldTypeResource ext
return properties;
}
-
- /** Return a list of names of Fields that have the given FieldType */
+
+ /**
+ * Return a list of names of Fields that have the given FieldType
+ */
protected abstract List<String> getFieldsWithFieldType(FieldType fieldType);
- /** Return a list of names of DynamicFields that have the given FieldType */
+ /**
+ * Return a list of names of DynamicFields that have the given FieldType
+ */
protected abstract List<String> getDynamicFieldsWithFieldType(FieldType fieldType);
}
Modified: lucene/dev/branches/solr_guice_restlet/solr/core/src/java/org/apache/solr/rest/schema/BaseSchemaResource.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/solr_guice_restlet/solr/core/src/java/org/apache/solr/rest/schema/BaseSchemaResource.java?rev=1510425&r1=1510424&r2=1510425&view=diff
==============================================================================
--- lucene/dev/branches/solr_guice_restlet/solr/core/src/java/org/apache/solr/rest/schema/BaseSchemaResource.java (original)
+++ lucene/dev/branches/solr_guice_restlet/solr/core/src/java/org/apache/solr/rest/schema/BaseSchemaResource.java Mon Aug 5 10:51:48 2013
@@ -16,203 +16,17 @@ package org.apache.solr.rest.schema;
* limitations under the License.
*/
-import org.apache.solr.common.params.CommonParams;
-import org.apache.solr.common.params.ModifiableSolrParams;
-import org.apache.solr.common.util.ContentStreamBase;
-import org.apache.solr.common.util.NamedList;
-import org.apache.solr.common.util.SimpleOrderedMap;
-import org.apache.solr.core.SolrCore;
-import org.apache.solr.request.SolrQueryRequest;
-import org.apache.solr.request.SolrRequestInfo;
-import org.apache.solr.response.BinaryQueryResponseWriter;
-import org.apache.solr.response.QueryResponseWriter;
-import org.apache.solr.response.SolrQueryResponse;
-import org.apache.solr.schema.IndexSchema;
-import org.apache.solr.servlet.ResponseUtils;
-import org.apache.solr.util.FastWriter;
-import org.restlet.data.MediaType;
-import org.restlet.data.Method;
-import org.restlet.data.Status;
-import org.restlet.representation.OutputRepresentation;
-import org.restlet.resource.ResourceException;
-import org.restlet.resource.ServerResource;
-import org.slf4j.Logger;
-
-import java.io.IOException;
-import java.io.OutputStream;
-import java.io.OutputStreamWriter;
-import java.io.UnsupportedEncodingException;
-import java.io.Writer;
-import java.net.URLDecoder;
-import java.nio.charset.Charset;
+import org.apache.solr.request.SolrQueryRequestDecoder;
+import org.apache.solr.rest.BaseCoreResource;
/**
* Base class of all Solr Schema Restlet resource classes.
*/
-abstract class BaseSchemaResource extends ServerResource {
- private static final Charset UTF8 = Charset.forName("UTF-8");
+abstract class BaseSchemaResource extends BaseCoreResource {
protected static final String SHOW_DEFAULTS = "showDefaults";
-
- private SolrCore solrCore;
- private IndexSchema schema;
- private SolrQueryRequest solrRequest;
- private SolrQueryResponse solrResponse;
- private QueryResponseWriter responseWriter;
- private String contentType;
- private boolean doIndent;
-
- protected SolrCore getSolrCore() { return solrCore; }
- protected IndexSchema getSchema() { return schema; }
- protected SolrQueryRequest getSolrRequest() { return solrRequest; }
- protected SolrQueryResponse getSolrResponse() { return solrResponse; }
- protected String getContentType() { return contentType; }
-
-
- protected BaseSchemaResource() {
- super();
- doIndent = true; // default to indenting
- }
-
- /**
- * Pulls the SolrQueryRequest constructed in SolrDispatchFilter
- * from the SolrRequestInfo thread local, then gets the SolrCore
- * and IndexSchema and sets up the response.
- * writer.
- * <p/>
- * If an error occurs during initialization, setExisting(false) is
- * called and an error status code and message is set; in this case,
- * Restlet will not continue servicing the request (by calling the
- * method annotated to associate it with GET, etc., but rather will
- * send an error response.
- */
- @Override
- public void doInit() throws ResourceException {
- super.doInit();
- setNegotiated(false); // Turn off content negotiation for now
- if (isExisting()) {
- try {
- SolrRequestInfo solrRequestInfo = SolrRequestInfo.getRequestInfo();
- if (null == solrRequestInfo) {
- final String message = "No handler or core found in " + getRequest().getOriginalRef().getPath();
- doError(Status.CLIENT_ERROR_BAD_REQUEST, message);
- setExisting(false);
- } else {
- solrRequest = solrRequestInfo.getReq();
- if (null == solrRequest) {
- final String message = "No handler or core found in " + getRequest().getOriginalRef().getPath();
- doError(Status.CLIENT_ERROR_BAD_REQUEST, message);
- setExisting(false);
- } else {
- solrResponse = solrRequestInfo.getRsp();
- solrCore = solrRequest.getCore();
- schema = solrRequest.getSchema();
- String responseWriterName = solrRequest.getParams().get(CommonParams.WT);
- if (null == responseWriterName) {
- responseWriterName = "json"; // Default to json writer
- }
- String indent = solrRequest.getParams().get("indent");
- if (null != indent && ("".equals(indent) || "off".equals(indent))) {
- doIndent = false;
- } else { // indent by default
- ModifiableSolrParams newParams = new ModifiableSolrParams(solrRequest.getParams());
- newParams.remove(indent);
- newParams.add("indent", "on");
- solrRequest.setParams(newParams);
- }
- responseWriter = solrCore.getQueryResponseWriter(responseWriterName);
- contentType = responseWriter.getContentType(solrRequest, solrResponse);
- final String path = getRequest().getRootRef().getPath();
- if ( ! "/schema".equals(path)) {
- // don't set webapp property on the request when context and core/collection are excluded
- final int cutoffPoint = path.indexOf("/", 1);
- final String firstPathElement = -1 == cutoffPoint ? path : path.substring(0, cutoffPoint);
- solrRequest.getContext().put("webapp", firstPathElement); // Context path
- }
- SolrCore.preDecorateResponse(solrRequest, solrResponse);
- }
- }
- } catch (Throwable t) {
- setExisting(false);
- throw new ResourceException(t);
- }
- }
- }
-
- /**
- * This class serves as an adapter between Restlet and Solr's response writers.
- */
- public class SolrOutputRepresentation extends OutputRepresentation {
-
- SolrOutputRepresentation() {
- // No normalization, in case of a custom media type
- super(MediaType.valueOf(contentType));
- // TODO: For now, don't send the Vary: header, but revisit if/when content negotiation is added
- getDimensions().clear();
- }
-
-
- /** Called by Restlet to get the response body */
- @Override
- public void write(OutputStream outputStream) throws IOException {
- if (getRequest().getMethod() != Method.HEAD) {
- if (responseWriter instanceof BinaryQueryResponseWriter) {
- BinaryQueryResponseWriter binWriter = (BinaryQueryResponseWriter)responseWriter;
- binWriter.write(outputStream, solrRequest, solrResponse);
- } else {
- String charset = ContentStreamBase.getCharsetFromContentType(contentType);
- Writer out = (charset == null || charset.equalsIgnoreCase("UTF-8"))
- ? new OutputStreamWriter(outputStream, UTF8)
- : new OutputStreamWriter(outputStream, charset);
- out = new FastWriter(out);
- responseWriter.write(out, solrRequest, solrResponse);
- out.flush();
- }
- }
- }
- }
-
- /**
- * Deal with an exception on the SolrResponse, fill in response header info,
- * and log the accumulated messages on the SolrResponse.
- */
- protected void handlePostExecution(Logger log) {
-
- handleException(log);
-
- // TODO: should status=0 (success?) be left as-is in the response header?
- SolrCore.postDecorateResponse(null, solrRequest, solrResponse);
-
- if (log.isInfoEnabled() && solrResponse.getToLog().size() > 0) {
- log.info(solrResponse.getToLogAsString(solrCore.getLogId()));
- }
- }
-
- /**
- * If there is an exception on the SolrResponse:
- * <ul>
- * <li>error info is added to the SolrResponse;</li>
- * <li>the response status code is set to the error code from the exception; and</li>
- * <li>the exception message is added to the list of things to be logged.</li>
- * </ul>
- */
- protected void handleException(Logger log) {
- Exception exception = getSolrResponse().getException();
- if (null != exception) {
- NamedList info = new SimpleOrderedMap();
- int code = ResponseUtils.getErrorInfo(exception, info, log);
- setStatus(Status.valueOf(code));
- getSolrResponse().add("error", info);
- String message = (String)info.get("msg");
- if (null != message && ! message.trim().isEmpty()) {
- getSolrResponse().getToLog().add("msg", "{" + message.trim() + "}");
- }
- }
- }
-
- /** Decode URL-encoded strings as UTF-8, and avoid converting "+" to space */
- protected static String urlDecode(String str) throws UnsupportedEncodingException {
- return URLDecoder.decode(str.replace("+", "%2B"), "UTF-8");
+ protected BaseSchemaResource(SolrQueryRequestDecoder requestDecoder) {
+ super(requestDecoder);
}
}
Modified: lucene/dev/branches/solr_guice_restlet/solr/core/src/java/org/apache/solr/rest/schema/CopyFieldCollectionResource.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/solr_guice_restlet/solr/core/src/java/org/apache/solr/rest/schema/CopyFieldCollectionResource.java?rev=1510425&r1=1510424&r2=1510425&view=diff
==============================================================================
--- lucene/dev/branches/solr_guice_restlet/solr/core/src/java/org/apache/solr/rest/schema/CopyFieldCollectionResource.java (original)
+++ lucene/dev/branches/solr_guice_restlet/solr/core/src/java/org/apache/solr/rest/schema/CopyFieldCollectionResource.java Mon Aug 5 10:51:48 2013
@@ -1,183 +1,19 @@
package org.apache.solr.rest.schema;
-/*
- * 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.common.SolrException;
-import org.apache.solr.common.params.CommonParams;
import org.apache.solr.rest.GETable;
import org.apache.solr.rest.POSTable;
-import org.apache.solr.schema.IndexSchema;
-import org.apache.solr.schema.ManagedIndexSchema;
-import org.noggit.ObjectBuilder;
-import org.restlet.data.MediaType;
import org.restlet.representation.Representation;
import org.restlet.resource.ResourceException;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.io.IOException;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
/**
- * This class responds to requests at /solr/(corename)/schema/copyfields
- * <p/>
*
- * To restrict the set of copyFields in the response, specify one or both
- * of the following as query parameters, with values as space and/or comma
- * separated dynamic or explicit field names:
*
- * <ul>
- * <li>dest.fl: include copyFields that have one of these as a destination</li>
- * <li>source.fl: include copyFields that have one of these as a source</li>
- * </ul>
- *
- * If both dest.fl and source.fl are given as query parameters, the copyfields
- * in the response will be restricted to those that match any of the destinations
- * in dest.fl and also match any of the sources in source.fl.
- */
-public class CopyFieldCollectionResource extends BaseFieldResource implements GETable, POSTable {
- private static final Logger log = LoggerFactory.getLogger(CopyFieldCollectionResource.class);
- private static final String SOURCE_FIELD_LIST = IndexSchema.SOURCE + "." + CommonParams.FL;
- private static final String DESTINATION_FIELD_LIST = IndexSchema.DESTINATION + "." + CommonParams.FL;
-
- private Set<String> requestedSourceFields;
- private Set<String> requestedDestinationFields;
-
- public CopyFieldCollectionResource() {
- super();
- }
-
+ **/
+public interface CopyFieldCollectionResource extends GETable, POSTable {
@Override
- public void doInit() throws ResourceException {
- super.doInit();
- if (isExisting()) {
- String sourceFieldListParam = getSolrRequest().getParams().get(SOURCE_FIELD_LIST);
- if (null != sourceFieldListParam) {
- String[] fields = sourceFieldListParam.trim().split("[,\\s]+");
- if (fields.length > 0) {
- requestedSourceFields = new HashSet<String>(Arrays.asList(fields));
- requestedSourceFields.remove(""); // Remove empty values, if any
- }
- }
- String destinationFieldListParam = getSolrRequest().getParams().get(DESTINATION_FIELD_LIST);
- if (null != destinationFieldListParam) {
- String[] fields = destinationFieldListParam.trim().split("[,\\s]+");
- if (fields.length > 0) {
- requestedDestinationFields = new HashSet<String>(Arrays.asList(fields));
- requestedDestinationFields.remove(""); // Remove empty values, if any
- }
- }
- }
- }
+ Representation get();
@Override
- public Representation get() {
- try {
- getSolrResponse().add(IndexSchema.COPY_FIELDS,
- getSchema().getCopyFieldProperties(true, requestedSourceFields, requestedDestinationFields));
- } catch (Exception e) {
- getSolrResponse().setException(e);
- }
- handlePostExecution(log);
-
- return new SolrOutputRepresentation();
- }
-
- @Override
- public Representation post(Representation entity) throws ResourceException {
- try {
- if (!getSchema().isMutable()) {
- final String message = "This IndexSchema is not mutable.";
- throw new SolrException(SolrException.ErrorCode.BAD_REQUEST, message);
- } else {
- if (!entity.getMediaType().equals(MediaType.APPLICATION_JSON, true)) {
- String message = "Only media type " + MediaType.APPLICATION_JSON.toString() + " is accepted."
- + " Request has media type " + entity.getMediaType().toString() + ".";
- log.error(message);
- throw new SolrException(SolrException.ErrorCode.BAD_REQUEST, message);
- } else {
- Object object = ObjectBuilder.fromJSON(entity.getText());
-
- if (!(object instanceof List)) {
- String message = "Invalid JSON type " + object.getClass().getName() + ", expected List of the form"
- + " (ignore the backslashes): [{\"source\":\"foo\",\"dest\":\"comma-separated list of targets\"}, {...}, ...]";
- log.error(message);
- throw new SolrException(SolrException.ErrorCode.BAD_REQUEST, message);
- } else {
- List<Map<String, Object>> list = (List<Map<String, Object>>) object;
- Map<String, Collection<String>> fieldsToCopy = new HashMap<>();
- ManagedIndexSchema oldSchema = (ManagedIndexSchema) getSchema();
- Set<String> malformed = new HashSet<>();
- for (Map<String,Object> map : list) {
- String fieldName = (String)map.get(IndexSchema.SOURCE);
- if (null == fieldName) {
- String message = "Missing '" + IndexSchema.SOURCE + "' mapping.";
- log.error(message);
- throw new SolrException(SolrException.ErrorCode.BAD_REQUEST, message);
- }
- Object dest = map.get(IndexSchema.DESTINATION);
- List<String> destinations = null;
- if (dest != null) {
- if (dest instanceof List){
- destinations = (List<String>)dest;
- } else if (dest instanceof String){
- destinations = Collections.singletonList(dest.toString());
- } else {
- String message = "Invalid '" + IndexSchema.DESTINATION + "' type.";
- log.error(message);
- throw new SolrException(SolrException.ErrorCode.BAD_REQUEST, message);
- }
- }
- if (destinations == null) {
- malformed.add(fieldName);
- } else {
- fieldsToCopy.put(fieldName, destinations);
- }
- }
- if (malformed.size() > 0){
- StringBuilder message = new StringBuilder("Malformed destination(s) for: ");
- for (String s : malformed) {
- message.append(s).append(", ");
- }
- if (message.length() > 2) {
- message.setLength(message.length() - 2);//drop the last ,
- }
- log.error(message.toString().trim());
- throw new SolrException(SolrException.ErrorCode.BAD_REQUEST, message.toString().trim());
- }
- IndexSchema newSchema = oldSchema.addCopyFields(fieldsToCopy);
- if (newSchema != null) {
- getSolrCore().setLatestSchema(newSchema);
- }
- }
- }
- }
- } catch (Exception e) {
- getSolrResponse().setException(e);
- }
- handlePostExecution(log);
- return new SolrOutputRepresentation();
- }
+ Representation post(Representation entity) throws ResourceException;
}