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;
 }