You are viewing a plain text version of this content. The canonical link for it is here.
Posted to oak-commits@jackrabbit.apache.org by to...@apache.org on 2013/07/16 14:17:31 UTC

svn commit: r1503679 - in /jackrabbit/oak/trunk/oak-solr-remote: ./ src/main/java/org/apache/jackrabbit/oak/plugins/index/solr/http/ src/main/resources/ src/main/resources/solr-oak-conf/ src/test/ src/test/java/ src/test/java/org/ src/test/java/org/apa...

Author: tommaso
Date: Tue Jul 16 12:17:31 2013
New Revision: 1503679

URL: http://svn.apache.org/r1503679
Log:
OAK-849 - added first implementation to create Oak collection for SolrCloud remote deployments

Added:
    jackrabbit/oak/trunk/oak-solr-remote/src/main/resources/
    jackrabbit/oak/trunk/oak-solr-remote/src/main/resources/solr-oak-conf/
    jackrabbit/oak/trunk/oak-solr-remote/src/main/resources/solr-oak-conf/currency.xml   (with props)
    jackrabbit/oak/trunk/oak-solr-remote/src/main/resources/solr-oak-conf/schema.xml   (with props)
    jackrabbit/oak/trunk/oak-solr-remote/src/main/resources/solr-oak-conf/solrconfig.xml   (with props)
    jackrabbit/oak/trunk/oak-solr-remote/src/test/
    jackrabbit/oak/trunk/oak-solr-remote/src/test/java/
    jackrabbit/oak/trunk/oak-solr-remote/src/test/java/org/
    jackrabbit/oak/trunk/oak-solr-remote/src/test/java/org/apache/
    jackrabbit/oak/trunk/oak-solr-remote/src/test/java/org/apache/jackrabbit/
    jackrabbit/oak/trunk/oak-solr-remote/src/test/java/org/apache/jackrabbit/oak/
    jackrabbit/oak/trunk/oak-solr-remote/src/test/java/org/apache/jackrabbit/oak/plugins/
    jackrabbit/oak/trunk/oak-solr-remote/src/test/java/org/apache/jackrabbit/oak/plugins/index/
    jackrabbit/oak/trunk/oak-solr-remote/src/test/java/org/apache/jackrabbit/oak/plugins/index/solr/
    jackrabbit/oak/trunk/oak-solr-remote/src/test/java/org/apache/jackrabbit/oak/plugins/index/solr/http/
    jackrabbit/oak/trunk/oak-solr-remote/src/test/java/org/apache/jackrabbit/oak/plugins/index/solr/http/RemoteSolrServerProviderIT.java   (with props)
Modified:
    jackrabbit/oak/trunk/oak-solr-remote/pom.xml
    jackrabbit/oak/trunk/oak-solr-remote/src/main/java/org/apache/jackrabbit/oak/plugins/index/solr/http/RemoteSolrServerProvider.java

Modified: jackrabbit/oak/trunk/oak-solr-remote/pom.xml
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-solr-remote/pom.xml?rev=1503679&r1=1503678&r2=1503679&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-solr-remote/pom.xml (original)
+++ jackrabbit/oak/trunk/oak-solr-remote/pom.xml Tue Jul 16 12:17:31 2013
@@ -95,6 +95,22 @@
       <version>${solr.version}</version>
       <scope>provided</scope>
     </dependency>
+    <dependency>
+      <groupId>org.apache.zookeeper</groupId>
+      <artifactId>zookeeper</artifactId>
+      <version>3.3.6</version>
+      <scope>provided</scope>
+      <exclusions>
+        <exclusion>
+          <groupId>com.sun.jdmk</groupId>
+          <artifactId>jmxtools</artifactId>
+        </exclusion>
+        <exclusion>
+          <groupId>com.sun.jmx</groupId>
+          <artifactId>jmxri</artifactId>
+        </exclusion>
+      </exclusions>
+    </dependency>
 
     <dependency>
       <groupId>org.apache.felix</groupId>
@@ -106,6 +122,26 @@
     <dependency>
       <groupId>junit</groupId>
       <artifactId>junit</artifactId>
+      <version>4.7</version>
+      <scope>test</scope>
+    </dependency>
+
+    <dependency>
+      <groupId>javax.servlet</groupId>
+      <artifactId>servlet-api</artifactId>
+      <version>2.5</version>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.slf4j</groupId>
+      <artifactId>log4j-over-slf4j</artifactId>
+      <optional>true</optional>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.slf4j</groupId>
+      <artifactId>jcl-over-slf4j</artifactId>
+      <optional>true</optional>
       <scope>test</scope>
     </dependency>
   </dependencies>

Modified: jackrabbit/oak/trunk/oak-solr-remote/src/main/java/org/apache/jackrabbit/oak/plugins/index/solr/http/RemoteSolrServerProvider.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-solr-remote/src/main/java/org/apache/jackrabbit/oak/plugins/index/solr/http/RemoteSolrServerProvider.java?rev=1503679&r1=1503678&r2=1503679&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-solr-remote/src/main/java/org/apache/jackrabbit/oak/plugins/index/solr/http/RemoteSolrServerProvider.java (original)
+++ jackrabbit/oak/trunk/oak-solr-remote/src/main/java/org/apache/jackrabbit/oak/plugins/index/solr/http/RemoteSolrServerProvider.java Tue Jul 16 12:17:31 2013
@@ -16,6 +16,7 @@
  */
 package org.apache.jackrabbit.oak.plugins.index.solr.http;
 
+import java.io.File;
 import java.io.IOException;
 
 import org.apache.felix.scr.annotations.Activate;
@@ -29,6 +30,10 @@ import org.apache.solr.client.solrj.Solr
 import org.apache.solr.client.solrj.SolrServerException;
 import org.apache.solr.client.solrj.impl.CloudSolrServer;
 import org.apache.solr.client.solrj.impl.HttpSolrServer;
+import org.apache.solr.client.solrj.request.UpdateRequest;
+import org.apache.solr.cloud.ZkController;
+import org.apache.solr.common.cloud.SolrZkClient;
+import org.apache.solr.common.cloud.ZkStateReader;
 import org.osgi.service.component.ComponentContext;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -43,33 +48,54 @@ public class RemoteSolrServerProvider im
     private final Logger log = LoggerFactory.getLogger(RemoteSolrServerProvider.class);
 
     private static final String DEFAULT_COLLECTION = "oak";
-    private static final String DEFAULT_HTTP_URL = "http://127.0.0.1:8983/solr";
+    private static final String DEFAULT_HTTP_URL = "http://127.0.0.1:8983/solr/oak";
     private static final String DEFAULT_ZK_HOST = "localhost:9983";
+    private static final int DEFAULT_SHARDS_NO = 2;
+    private static final int DEFAULT_REPLICATION_FACTOR = 2;
 
-    @Property(value = DEFAULT_HTTP_URL, name = "Default Solr HTTP URL")
+    @Property(value = DEFAULT_HTTP_URL, name = "Solr HTTP URL")
     private static final String SOLR_HTTP_URL = "solr.http.url";
 
-    @Property(value = DEFAULT_ZK_HOST, name = "Zookeeper host")
+    @Property(value = DEFAULT_ZK_HOST, name = "ZooKeeper host")
     private static final String SOLR_ZK_HOST = "solr.zk.host";
 
-    @Property(value = DEFAULT_COLLECTION, name = "Default collection")
+    @Property(value = DEFAULT_COLLECTION, name = "Solr collection")
     private static final String SOLR_COLLECTION = "solr.collection";
 
+    @Property(intValue = DEFAULT_SHARDS_NO, name = "No. of collection shards")
+    private static final String SOLR_SHARDS_NO = "solr.shards.no";
+
+    @Property(intValue = DEFAULT_REPLICATION_FACTOR, name = "Replication factor")
+    private static final String SOLR_REPLICATION_FACTOR = "solr.replication.factor";
+
+    @Property(value = "", name = "Solr configuration directory")
+    private static final String SOLR_CONF_DIR = "solr.conf.dir";
+
     private SolrServer solrServer;
     private String solrHttpUrl;
     private String solrZkHost;
     private String solrCollection;
+    private int solrShardsNo;
+    private int solrReplicationFactor;
+    private String solrConfDir;
 
     public RemoteSolrServerProvider() {
         this.solrHttpUrl = DEFAULT_HTTP_URL;
         this.solrZkHost = DEFAULT_ZK_HOST;
         this.solrCollection = DEFAULT_COLLECTION;
+        this.solrShardsNo = DEFAULT_SHARDS_NO;
+        this.solrReplicationFactor = DEFAULT_REPLICATION_FACTOR;
     }
 
-    public RemoteSolrServerProvider(String solrHttpUrl, String solrZkHost, String solrCollection) {
+    public RemoteSolrServerProvider(String solrHttpUrl, String solrZkHost,
+                                    String solrCollection, int solrShardsNo,
+                                    int solrReplicationFactor, String solrConfDir) {
         this.solrHttpUrl = solrHttpUrl;
         this.solrZkHost = solrZkHost;
         this.solrCollection = solrCollection;
+        this.solrShardsNo = solrShardsNo;
+        this.solrReplicationFactor = solrReplicationFactor;
+        this.solrConfDir = solrConfDir;
     }
 
     @Activate
@@ -77,6 +103,9 @@ public class RemoteSolrServerProvider im
         solrHttpUrl = String.valueOf(componentContext.getProperties().get(SOLR_HTTP_URL));
         solrZkHost = String.valueOf(componentContext.getProperties().get(SOLR_ZK_HOST));
         solrCollection = String.valueOf(componentContext.getProperties().get(SOLR_COLLECTION));
+        solrShardsNo = Integer.valueOf(componentContext.getProperties().get(SOLR_SHARDS_NO).toString());
+        solrReplicationFactor = Integer.valueOf(componentContext.getProperties().get(SOLR_REPLICATION_FACTOR).toString());
+        solrConfDir = String.valueOf(componentContext.getProperties().get(SOLR_CONF_DIR));
     }
 
     @Deactivate
@@ -84,6 +113,9 @@ public class RemoteSolrServerProvider im
         solrHttpUrl = null;
         solrZkHost = null;
         solrCollection = null;
+        solrShardsNo = 0;
+        solrReplicationFactor = 0;
+        solrConfDir = null;
         if (solrServer != null) {
             solrServer.shutdown();
             solrServer = null;
@@ -97,11 +129,11 @@ public class RemoteSolrServerProvider im
             try {
                 solrServer = initializeWithCloudSolrServer();
             } catch (Exception e) {
-                log.warn("unable to initialize default SolrCloud client");
+                log.warn("unable to initialize SolrCloud client", e);
                 try {
                     solrServer = initializeWithExistingHttpServer();
                 } catch (Exception e1) {
-                    log.warn("unable to initialize default Solr HTTP client");
+                    log.warn("unable to initialize Solr HTTP client", e1);
                 }
             }
             if (solrServer == null) {
@@ -115,7 +147,7 @@ public class RemoteSolrServerProvider im
         // try basic Solr HTTP client
         HttpSolrServer httpSolrServer = new HttpSolrServer(solrHttpUrl);
         if (OakSolrUtils.checkServerAlive(httpSolrServer)) {
-            // TODO : check if oak collection exists, otherwise create it
+            // TODO : check if the oak core exists, otherwise create it
             return httpSolrServer;
         } else {
             throw new IOException("the found HTTP Solr server is not alive");
@@ -126,12 +158,53 @@ public class RemoteSolrServerProvider im
     private SolrServer initializeWithCloudSolrServer() throws IOException, SolrServerException {
         // try SolrCloud client
         CloudSolrServer cloudSolrServer = new CloudSolrServer(solrZkHost);
-        cloudSolrServer.setDefaultCollection(DEFAULT_COLLECTION);
-        if (OakSolrUtils.checkServerAlive(cloudSolrServer)) {
-            // TODO : check if oak collection exists, otherwise create it
-            return cloudSolrServer;
-        } else {
-            throw new IOException("the found SolrCloud server is not alive");
+        cloudSolrServer.connect();
+        cloudSolrServer.setDefaultCollection("collection1"); // workaround for first request when the needed collection may not exist
+
+        // create specified collection if it doesn't exists
+        createCollectionIfNeeded(cloudSolrServer);
+
+        cloudSolrServer.setDefaultCollection(solrCollection);
+
+        // SolrCloud may need some time to sync on collection creation (to spread it over the shards / replicas)
+        int i = 0;
+        while (i < 3) {
+            try {
+                OakSolrUtils.checkServerAlive(cloudSolrServer);
+                return cloudSolrServer;
+            } catch (Exception e) {
+                // wait a bit
+                try {
+                    log.warn("wait a bit", e);
+                    Thread.sleep(3000);
+                } catch (InterruptedException e1) {
+                    // do nothing
+                }
+            }
+            i++;
+        }
+        throw new IOException("the found SolrCloud server is not alive");
+
+    }
+
+    private void createCollectionIfNeeded(CloudSolrServer cloudSolrServer) throws SolrServerException, IOException {
+        try {
+            ZkStateReader zkStateReader = cloudSolrServer.getZkStateReader();
+            SolrZkClient zkClient = zkStateReader.getZkClient();
+            if (zkClient.isConnected() && !zkClient.exists("/configs/" + solrCollection, false)) {
+                File dir = new File(solrConfDir != null ? solrConfDir : getClass().getResource("/solr-oak-conf").getFile());
+                ZkController.uploadConfigDir(zkClient, dir, solrCollection);
+                UpdateRequest req = new UpdateRequest("/admin/collections");
+                req.setParam("action", "CREATE");
+                req.setParam("numShards", String.valueOf(solrShardsNo));
+                req.setParam("replicationFactor", String.valueOf(solrReplicationFactor));
+                req.setParam("collection.configName", solrCollection);
+                req.setParam("name", solrCollection);
+                cloudSolrServer.request(req);
+            }
+        } catch (Exception e) {
+            log.warn("could not create collection {}", solrCollection);
+            throw new SolrServerException(e);
         }
     }
 }

Added: jackrabbit/oak/trunk/oak-solr-remote/src/main/resources/solr-oak-conf/currency.xml
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-solr-remote/src/main/resources/solr-oak-conf/currency.xml?rev=1503679&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-solr-remote/src/main/resources/solr-oak-conf/currency.xml (added)
+++ jackrabbit/oak/trunk/oak-solr-remote/src/main/resources/solr-oak-conf/currency.xml Tue Jul 16 12:17:31 2013
@@ -0,0 +1,67 @@
+<?xml version="1.0" ?>
+<!--
+ 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.
+-->
+
+<!-- Example exchange rates file for CurrencyField type named "currency" in example schema -->
+
+<currencyConfig version="1.0">
+  <rates>
+    <!-- Updated from http://www.exchangerate.com/ at 2011-09-27 -->
+    <rate from="USD" to="ARS" rate="4.333871" comment="ARGENTINA Peso" />
+    <rate from="USD" to="AUD" rate="1.025768" comment="AUSTRALIA Dollar" />
+    <rate from="USD" to="EUR" rate="0.743676" comment="European Euro" />
+    <rate from="USD" to="BRL" rate="1.881093" comment="BRAZIL Real" />
+    <rate from="USD" to="CAD" rate="1.030815" comment="CANADA Dollar" />
+    <rate from="USD" to="CLP" rate="519.0996" comment="CHILE Peso" />
+    <rate from="USD" to="CNY" rate="6.387310" comment="CHINA Yuan" />
+    <rate from="USD" to="CZK" rate="18.47134" comment="CZECH REP. Koruna" />
+    <rate from="USD" to="DKK" rate="5.515436" comment="DENMARK Krone" />
+    <rate from="USD" to="HKD" rate="7.801922" comment="HONG KONG Dollar" />
+    <rate from="USD" to="HUF" rate="215.6169" comment="HUNGARY Forint" />
+    <rate from="USD" to="ISK" rate="118.1280" comment="ICELAND Krona" />
+    <rate from="USD" to="INR" rate="49.49088" comment="INDIA Rupee" />
+    <rate from="USD" to="XDR" rate="0.641358" comment="INTNL MON. FUND SDR" />
+    <rate from="USD" to="ILS" rate="3.709739" comment="ISRAEL Sheqel" />
+    <rate from="USD" to="JPY" rate="76.32419" comment="JAPAN Yen" />
+    <rate from="USD" to="KRW" rate="1169.173" comment="KOREA (SOUTH) Won" />
+    <rate from="USD" to="KWD" rate="0.275142" comment="KUWAIT Dinar" />
+    <rate from="USD" to="MXN" rate="13.85895" comment="MEXICO Peso" />
+    <rate from="USD" to="NZD" rate="1.285159" comment="NEW ZEALAND Dollar" />
+    <rate from="USD" to="NOK" rate="5.859035" comment="NORWAY Krone" />
+    <rate from="USD" to="PKR" rate="87.57007" comment="PAKISTAN Rupee" />
+    <rate from="USD" to="PEN" rate="2.730683" comment="PERU Sol" />
+    <rate from="USD" to="PHP" rate="43.62039" comment="PHILIPPINES Peso" />
+    <rate from="USD" to="PLN" rate="3.310139" comment="POLAND Zloty" />
+    <rate from="USD" to="RON" rate="3.100932" comment="ROMANIA Leu" />
+    <rate from="USD" to="RUB" rate="32.14663" comment="RUSSIA Ruble" />
+    <rate from="USD" to="SAR" rate="3.750465" comment="SAUDI ARABIA Riyal" />
+    <rate from="USD" to="SGD" rate="1.299352" comment="SINGAPORE Dollar" />
+    <rate from="USD" to="ZAR" rate="8.329761" comment="SOUTH AFRICA Rand" />
+    <rate from="USD" to="SEK" rate="6.883442" comment="SWEDEN Krona" />
+    <rate from="USD" to="CHF" rate="0.906035" comment="SWITZERLAND Franc" />
+    <rate from="USD" to="TWD" rate="30.40283" comment="TAIWAN Dollar" />
+    <rate from="USD" to="THB" rate="30.89487" comment="THAILAND Baht" />
+    <rate from="USD" to="AED" rate="3.672955" comment="U.A.E. Dirham" />
+    <rate from="USD" to="UAH" rate="7.988582" comment="UKRAINE Hryvnia" />
+    <rate from="USD" to="GBP" rate="0.647910" comment="UNITED KINGDOM Pound" />
+    
+    <!-- Cross-rates for some common currencies -->
+    <rate from="EUR" to="GBP" rate="0.869914" />  
+    <rate from="EUR" to="NOK" rate="7.800095" />  
+    <rate from="GBP" to="NOK" rate="8.966508" />  
+  </rates>
+</currencyConfig>

Propchange: jackrabbit/oak/trunk/oak-solr-remote/src/main/resources/solr-oak-conf/currency.xml
------------------------------------------------------------------------------
    svn:eol-style = native

Added: jackrabbit/oak/trunk/oak-solr-remote/src/main/resources/solr-oak-conf/schema.xml
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-solr-remote/src/main/resources/solr-oak-conf/schema.xml?rev=1503679&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-solr-remote/src/main/resources/solr-oak-conf/schema.xml (added)
+++ jackrabbit/oak/trunk/oak-solr-remote/src/main/resources/solr-oak-conf/schema.xml Tue Jul 16 12:17:31 2013
@@ -0,0 +1,146 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!--
+ 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.
+-->
+<schema name="minimal" version="1.5">
+  <types>
+    <fieldType name="string" class="solr.StrField"/>
+    <fieldType name="descendent_path" class="solr.TextField">
+      <analyzer type="index">
+        <tokenizer class="solr.PathHierarchyTokenizerFactory" delimiter="/" />
+      </analyzer>
+      <analyzer type="query">
+        <tokenizer class="solr.KeywordTokenizerFactory" />
+      </analyzer>
+    </fieldType>
+    <fieldType name="children_path" class="solr.TextField">
+      <analyzer type="index">
+        <tokenizer class="solr.PathHierarchyTokenizerFactory" delimiter="/" skip="1" reverse="true" />
+        <filter class="solr.PatternReplaceFilterFactory" pattern="/" replacement="" replace="all"/>
+      </analyzer>
+      <analyzer type="query">
+        <tokenizer class="solr.KeywordTokenizerFactory" />
+        <filter class="solr.PatternReplaceFilterFactory" pattern="/" replacement="" replace="all"/>
+      </analyzer>
+    </fieldType>
+    <fieldType name="parent_path" class="solr.TextField">
+      <analyzer type="index">
+        <tokenizer class="solr.KeywordTokenizerFactory" />
+        <filter class="solr.PatternReplaceFilterFactory" pattern="/" replacement="" replace="all"/>
+      </analyzer>
+      <analyzer type="query">
+        <tokenizer class="solr.PathHierarchyTokenizerFactory" delimiter="/" skip="1" reverse="true"/>
+        <filter class="solr.PatternReplaceFilterFactory" pattern="/" replacement="" replace="all"/>
+      </analyzer>
+    </fieldType>
+    <fieldType name="text_keepcase" class="solr.TextField" positionIncrementGap="100">
+      <analyzer type="index">
+        <tokenizer class="solr.StandardTokenizerFactory"/>
+      </analyzer>
+      <analyzer type="query">
+        <tokenizer class="solr.StandardTokenizerFactory"/>
+      </analyzer>
+    </fieldType>
+    <fieldType name="text_general" class="solr.TextField" positionIncrementGap="100">
+      <analyzer type="index">
+        <tokenizer class="solr.StandardTokenizerFactory"/>
+        <filter class="solr.LowerCaseFilterFactory"/>
+      </analyzer>
+      <analyzer type="query">
+        <tokenizer class="solr.StandardTokenizerFactory"/>
+        <filter class="solr.LowerCaseFilterFactory"/>
+      </analyzer>
+    </fieldType>
+
+    <fieldType name="boolean" class="solr.BoolField" sortMissingLast="true"/>
+
+    <fieldType name="int" class="solr.TrieIntField" precisionStep="0" positionIncrementGap="0"/>
+    <fieldType name="float" class="solr.TrieFloatField" precisionStep="0" positionIncrementGap="0"/>
+    <fieldType name="long" class="solr.TrieLongField" precisionStep="0" positionIncrementGap="0"/>
+    <fieldType name="double" class="solr.TrieDoubleField" precisionStep="0" positionIncrementGap="0"/>
+
+    <fieldType name="tint" class="solr.TrieIntField" precisionStep="8" positionIncrementGap="0"/>
+    <fieldType name="tfloat" class="solr.TrieFloatField" precisionStep="8" positionIncrementGap="0"/>
+    <fieldType name="tlong" class="solr.TrieLongField" precisionStep="8" positionIncrementGap="0"/>
+    <fieldType name="tdouble" class="solr.TrieDoubleField" precisionStep="8" positionIncrementGap="0"/>
+    <fieldType name="date" class="solr.TrieDateField" precisionStep="0" positionIncrementGap="0"/>
+
+    <fieldType name="tdate" class="solr.TrieDateField" precisionStep="6" positionIncrementGap="0"/>
+
+    <fieldtype name="binary" class="solr.BinaryField"/>
+
+    <fieldType name="pint" class="solr.IntField"/>
+    <fieldType name="plong" class="solr.LongField"/>
+    <fieldType name="pfloat" class="solr.FloatField"/>
+    <fieldType name="pdouble" class="solr.DoubleField"/>
+    <fieldType name="pdate" class="solr.DateField" sortMissingLast="true"/>
+
+    <fieldType name="point" class="solr.PointType" dimension="2" subFieldSuffix="_d"/>
+
+    <fieldType name="location" class="solr.LatLonType" subFieldSuffix="_coordinate"/>
+
+    <fieldType name="location_rpt" class="solr.SpatialRecursivePrefixTreeFieldType"
+               geo="true" distErrPct="0.025" maxDistErr="0.000009" units="degrees" />
+
+    <fieldType name="currency" class="solr.CurrencyField" precisionStep="8" defaultCurrency="USD" currencyConfig="currency.xml" />
+    <fieldtype name="ignored" stored="false" indexed="false" multiValued="true" class="solr.StrField"/>
+  </types>
+  <fields>
+    <field name="path_exact" type="string" indexed="true" stored="true"/>
+    <field name="path_child" type="children_path" indexed="true" stored="false"/>
+    <field name="path_anc" type="parent_path" indexed="true" stored="false"/>
+    <field name="path_des" type="descendent_path" indexed="true" stored="false"/>
+    <field name="ignored" type="ignored" multiValued="true"/>
+    <field name="catch_all" type="text_general" indexed="true" stored="false" multiValued="true"/>
+    <field name="_version_" type="long" indexed="true" stored="true"/>
+
+    <dynamicField name="*_i"  type="int"    indexed="true"  stored="true"/>
+    <dynamicField name="*_is" type="int"    indexed="true"  stored="true"  multiValued="true"/>
+    <dynamicField name="*_s"  type="string"  indexed="true"  stored="true" />
+    <dynamicField name="*_ss" type="string"  indexed="true"  stored="true" multiValued="true"/>
+    <dynamicField name="*_l"  type="long"   indexed="true"  stored="true"/>
+    <dynamicField name="*_ls" type="long"   indexed="true"  stored="true"  multiValued="true"/>
+    <dynamicField name="*_t"  type="text_general"    indexed="true"  stored="true"/>
+    <dynamicField name="*_txt" type="text_general"   indexed="true"  stored="true" multiValued="true"/>
+    <dynamicField name="*_b"  type="boolean" indexed="true" stored="true"/>
+    <dynamicField name="*_bs" type="boolean" indexed="true" stored="true"  multiValued="true"/>
+    <dynamicField name="*_f"  type="float"  indexed="true"  stored="true"/>
+    <dynamicField name="*_fs" type="float"  indexed="true"  stored="true"  multiValued="true"/>
+    <dynamicField name="*_d"  type="double" indexed="true"  stored="true"/>
+    <dynamicField name="*_ds" type="double" indexed="true"  stored="true"  multiValued="true"/>
+
+    <dynamicField name="*_coordinate"  type="tdouble" indexed="true"  stored="false" />
+
+    <dynamicField name="*_dt"  type="date"    indexed="true"  stored="true"/>
+    <dynamicField name="*_dts" type="date"    indexed="true"  stored="true" multiValued="true"/>
+    <dynamicField name="*_p"  type="location" indexed="true" stored="true"/>
+
+    <dynamicField name="*_ti" type="tint"    indexed="true"  stored="true"/>
+    <dynamicField name="*_tl" type="tlong"   indexed="true"  stored="true"/>
+    <dynamicField name="*_tf" type="tfloat"  indexed="true"  stored="true"/>
+    <dynamicField name="*_td" type="tdouble" indexed="true"  stored="true"/>
+    <dynamicField name="*_tdt" type="tdate"  indexed="true"  stored="true"/>
+
+    <dynamicField name="*_pi"  type="pint"    indexed="true"  stored="true"/>
+    <dynamicField name="*_c"   type="currency" indexed="true"  stored="true"/>
+    <dynamicField name="*" type="text_keepcase" indexed="true" stored="true" multiValued="true"/>
+  </fields>
+  <uniqueKey>path_exact</uniqueKey>
+  <copyField source="path_exact" dest="path_anc"/>
+  <copyField source="path_exact" dest="path_des"/>
+  <copyField source="path_exact" dest="path_child"/>
+  <copyField source="*" dest="catch_all"/>
+</schema>

Propchange: jackrabbit/oak/trunk/oak-solr-remote/src/main/resources/solr-oak-conf/schema.xml
------------------------------------------------------------------------------
    svn:eol-style = native

Added: jackrabbit/oak/trunk/oak-solr-remote/src/main/resources/solr-oak-conf/solrconfig.xml
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-solr-remote/src/main/resources/solr-oak-conf/solrconfig.xml?rev=1503679&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-solr-remote/src/main/resources/solr-oak-conf/solrconfig.xml (added)
+++ jackrabbit/oak/trunk/oak-solr-remote/src/main/resources/solr-oak-conf/solrconfig.xml Tue Jul 16 12:17:31 2013
@@ -0,0 +1,373 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!--
+ 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.
+-->
+
+<!-- 
+     For more details about configurations options that may appear in
+     this file, see http://wiki.apache.org/solr/SolrConfigXml. 
+-->
+<config>
+
+  <luceneMatchVersion>LUCENE_40</luceneMatchVersion>
+
+  <dataDir>${solr.data.dir:}</dataDir>
+
+  <directoryFactory name="DirectoryFactory"
+                    class="${solr.directoryFactory:solr.MMapDirectoryFactory}"/>
+
+
+  <indexConfig>
+
+    <lockType>native</lockType>
+
+  </indexConfig>
+
+
+  <jmx/>
+
+  <updateHandler class="solr.DirectUpdateHandler2">
+
+    <updateLog>
+      <str name="dir">${solr.data.dir:}</str>
+    </updateLog>
+
+
+  </updateHandler>
+
+
+  <query>
+
+    <maxBooleanClauses>10240</maxBooleanClauses>
+
+
+    <filterCache class="solr.FastLRUCache"
+                 size="512"
+                 initialSize="512"
+                 autowarmCount="0"/>
+
+    <queryResultCache class="solr.LRUCache"
+                      size="512"
+                      initialSize="512"
+                      autowarmCount="0"/>
+
+    <documentCache class="solr.LRUCache"
+                   size="512"
+                   initialSize="512"
+                   autowarmCount="0"/>
+
+
+    <enableLazyFieldLoading>true</enableLazyFieldLoading>
+
+    <queryResultWindowSize>20</queryResultWindowSize>
+
+    <queryResultMaxDocsCached>200</queryResultMaxDocsCached>
+
+    <useColdSearcher>true</useColdSearcher>
+
+    <maxWarmingSearchers>2</maxWarmingSearchers>
+
+  </query>
+
+
+  <requestDispatcher handleSelect="false">
+
+    <requestParsers enableRemoteStreaming="true"
+                    multipartUploadLimitInKB="2048000"/>
+
+    <httpCaching never304="true"/>
+
+  </requestDispatcher>
+
+  <requestHandler name="/select" class="solr.SearchHandler">
+    <lst name="defaults">
+      <str name="echoParams">explicit</str>
+      <int name="rows">10</int>
+      <str name="df">text</str>
+    </lst>
+
+  </requestHandler>
+
+  <requestHandler name="/query" class="solr.SearchHandler">
+    <lst name="defaults">
+      <str name="echoParams">explicit</str>
+      <str name="wt">json</str>
+      <str name="indent">true</str>
+      <str name="df">text</str>
+    </lst>
+  </requestHandler>
+
+
+  <requestHandler name="/get" class="solr.RealTimeGetHandler">
+    <lst name="defaults">
+      <str name="omitHeader">true</str>
+      <str name="wt">json</str>
+      <str name="indent">true</str>
+    </lst>
+  </requestHandler>
+
+
+  <requestHandler name="/update" class="solr.UpdateRequestHandler">
+
+  </requestHandler>
+
+  <requestHandler name="/update/json" class="solr.JsonUpdateRequestHandler">
+    <lst name="defaults">
+      <str name="stream.contentType">application/json</str>
+    </lst>
+  </requestHandler>
+  <requestHandler name="/update/csv" class="solr.CSVRequestHandler">
+    <lst name="defaults">
+      <str name="stream.contentType">application/csv</str>
+    </lst>
+  </requestHandler>
+
+  <requestHandler name="/update/extract"
+                  startup="lazy"
+                  class="solr.extraction.ExtractingRequestHandler">
+    <lst name="defaults">
+      <str name="lowernames">true</str>
+      <str name="uprefix">ignored_</str>
+
+      <str name="captureAttr">true</str>
+      <str name="fmap.a">links</str>
+      <str name="fmap.div">ignored_</str>
+    </lst>
+  </requestHandler>
+
+
+  <requestHandler name="/analysis/field"
+                  startup="lazy"
+                  class="solr.FieldAnalysisRequestHandler"/>
+
+
+  <requestHandler name="/analysis/document"
+                  class="solr.DocumentAnalysisRequestHandler"
+                  startup="lazy"/>
+
+  <requestHandler name="/admin/"
+                  class="solr.admin.AdminHandlers"/>
+
+  <requestHandler name="/admin/ping" class="solr.PingRequestHandler">
+    <lst name="invariants">
+      <str name="q">solrpingquery</str>
+    </lst>
+    <lst name="defaults">
+      <str name="echoParams">all</str>
+    </lst>
+  </requestHandler>
+
+  <requestHandler name="/debug/dump" class="solr.DumpRequestHandler">
+    <lst name="defaults">
+      <str name="echoParams">explicit</str>
+      <str name="echoHandler">true</str>
+    </lst>
+  </requestHandler>
+
+  <requestHandler name="/replication" class="solr.ReplicationHandler">
+  </requestHandler>
+
+
+  <searchComponent name="spellcheck" class="solr.SpellCheckComponent">
+
+    <str name="queryAnalyzerFieldType">textSpell</str>
+
+    <!-- a spellchecker built from a field of the main index -->
+    <lst name="spellchecker">
+      <str name="name">default</str>
+      <str name="field">name</str>
+      <str name="classname">solr.DirectSolrSpellChecker</str>
+      <!-- the spellcheck distance measure used, the default is the internal levenshtein -->
+      <str name="distanceMeasure">internal</str>
+      <!-- minimum accuracy needed to be considered a valid spellcheck suggestion -->
+      <float name="accuracy">0.5</float>
+      <!-- the maximum #edits we consider when enumerating terms: can be 1 or 2 -->
+      <int name="maxEdits">2</int>
+      <!-- the minimum shared prefix when enumerating terms -->
+      <int name="minPrefix">1</int>
+      <!-- maximum number of inspections per result. -->
+      <int name="maxInspections">5</int>
+      <!-- minimum length of a query term to be considered for correction -->
+      <int name="minQueryLength">4</int>
+      <!-- maximum threshold of documents a query term can appear to be considered for correction -->
+      <float name="maxQueryFrequency">0.01</float>
+      <!-- uncomment this to require suggestions to occur in 1% of the documents
+          <float name="thresholdTokenFrequency">.01</float>
+      -->
+    </lst>
+
+    <!-- a spellchecker that can break or combine words.  See "/spell" handler below for usage -->
+    <lst name="spellchecker">
+      <str name="name">wordbreak</str>
+      <str name="classname">solr.WordBreakSolrSpellChecker</str>
+      <str name="field">name</str>
+      <str name="combineWords">true</str>
+      <str name="breakWords">true</str>
+      <int name="maxChanges">10</int>
+    </lst>
+
+
+  </searchComponent>
+
+
+  <searchComponent name="tvComponent" class="solr.TermVectorComponent"/>
+
+  <requestHandler name="/tvrh" class="solr.SearchHandler" startup="lazy">
+    <lst name="defaults">
+      <str name="df">text</str>
+      <bool name="tv">true</bool>
+    </lst>
+    <arr name="last-components">
+      <str>tvComponent</str>
+    </arr>
+  </requestHandler>
+
+
+  <searchComponent name="terms" class="solr.TermsComponent"/>
+
+  <requestHandler name="/terms" class="solr.SearchHandler" startup="lazy">
+    <lst name="defaults">
+      <bool name="terms">true</bool>
+    </lst>
+    <arr name="components">
+      <str>terms</str>
+    </arr>
+  </requestHandler>
+
+
+  <searchComponent class="solr.HighlightComponent" name="highlight">
+    <highlighting>
+      <!-- Configure the standard fragmenter -->
+      <!-- This could most likely be commented out in the "default" case -->
+      <fragmenter name="gap"
+                  default="true"
+                  class="solr.highlight.GapFragmenter">
+        <lst name="defaults">
+          <int name="hl.fragsize">100</int>
+        </lst>
+      </fragmenter>
+
+      <!-- A regular-expression-based fragmenter
+         (for sentence extraction)
+      -->
+      <fragmenter name="regex"
+                  class="solr.highlight.RegexFragmenter">
+        <lst name="defaults">
+          <!-- slightly smaller fragsizes work better because of slop -->
+          <int name="hl.fragsize">70</int>
+          <!-- allow 50% slop on fragment sizes -->
+          <float name="hl.regex.slop">0.5</float>
+          <!-- a basic sentence pattern -->
+          <str name="hl.regex.pattern">[-\w
+            ,/\n\&quot;&apos;]{20,200}
+          </str>
+        </lst>
+      </fragmenter>
+
+      <!-- Configure the standard formatter -->
+      <formatter name="html"
+                 default="true"
+                 class="solr.highlight.HtmlFormatter">
+        <lst name="defaults">
+          <str name="hl.simple.pre"><![CDATA[<em>]]></str>
+          <str name="hl.simple.post"><![CDATA[</em>]]></str>
+        </lst>
+      </formatter>
+
+      <!-- Configure the standard encoder -->
+      <encoder name="html"
+               class="solr.highlight.HtmlEncoder"/>
+
+      <!-- Configure the standard fragListBuilder -->
+      <fragListBuilder name="simple"
+                       class="solr.highlight.SimpleFragListBuilder"/>
+
+      <!-- Configure the single fragListBuilder -->
+      <fragListBuilder name="single"
+                       class="solr.highlight.SingleFragListBuilder"/>
+
+      <!-- Configure the weighted fragListBuilder -->
+      <fragListBuilder name="weighted"
+                       default="true"
+                       class="solr.highlight.WeightedFragListBuilder"/>
+
+      <!-- default tag FragmentsBuilder -->
+      <fragmentsBuilder name="default"
+                        default="true"
+                        class="solr.highlight.ScoreOrderFragmentsBuilder">
+        <!--
+        <lst name="defaults">
+          <str name="hl.multiValuedSeparatorChar">/</str>
+        </lst>
+        -->
+      </fragmentsBuilder>
+
+      <!-- multi-colored tag FragmentsBuilder -->
+      <fragmentsBuilder name="colored"
+                        class="solr.highlight.ScoreOrderFragmentsBuilder">
+        <lst name="defaults">
+          <str name="hl.tag.pre"><![CDATA[
+               <b style="background:yellow">,<b style="background:lawgreen">,
+               <b style="background:aquamarine">,<b style="background:magenta">,
+               <b style="background:palegreen">,<b style="background:coral">,
+               <b style="background:wheat">,<b style="background:khaki">,
+               <b style="background:lime">,<b style="background:deepskyblue">]]></str>
+          <str name="hl.tag.post"><![CDATA[</b>]]></str>
+        </lst>
+      </fragmentsBuilder>
+
+      <boundaryScanner name="default"
+                       default="true"
+                       class="solr.highlight.SimpleBoundaryScanner">
+        <lst name="defaults">
+          <str name="hl.bs.maxScan">10</str>
+          <str name="hl.bs.chars">.,!? &#9;&#10;&#13;</str>
+        </lst>
+      </boundaryScanner>
+
+      <boundaryScanner name="breakIterator"
+                       class="solr.highlight.BreakIteratorBoundaryScanner">
+        <lst name="defaults">
+          <!-- type should be one of CHARACTER, WORD(default), LINE and SENTENCE -->
+          <str name="hl.bs.type">WORD</str>
+          <!-- language and country are used when constructing Locale object.  -->
+          <!-- And the Locale object will be used when getting instance of BreakIterator -->
+          <str name="hl.bs.language">en</str>
+          <str name="hl.bs.country">US</str>
+        </lst>
+      </boundaryScanner>
+    </highlighting>
+  </searchComponent>
+
+
+  <queryResponseWriter name="json" class="solr.JSONResponseWriter">
+    <str name="content-type">text/plain; charset=UTF-8</str>
+  </queryResponseWriter>
+
+  <queryResponseWriter name="velocity" class="solr.VelocityResponseWriter"
+                       startup="lazy"/>
+
+
+  <queryResponseWriter name="xslt" class="solr.XSLTResponseWriter">
+    <int name="xsltCacheLifetimeSeconds">5</int>
+  </queryResponseWriter>
+
+
+  <admin>
+    <defaultQuery>*:*</defaultQuery>
+  </admin>
+
+</config>

Propchange: jackrabbit/oak/trunk/oak-solr-remote/src/main/resources/solr-oak-conf/solrconfig.xml
------------------------------------------------------------------------------
    svn:eol-style = native

Added: jackrabbit/oak/trunk/oak-solr-remote/src/test/java/org/apache/jackrabbit/oak/plugins/index/solr/http/RemoteSolrServerProviderIT.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-solr-remote/src/test/java/org/apache/jackrabbit/oak/plugins/index/solr/http/RemoteSolrServerProviderIT.java?rev=1503679&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-solr-remote/src/test/java/org/apache/jackrabbit/oak/plugins/index/solr/http/RemoteSolrServerProviderIT.java (added)
+++ jackrabbit/oak/trunk/oak-solr-remote/src/test/java/org/apache/jackrabbit/oak/plugins/index/solr/http/RemoteSolrServerProviderIT.java Tue Jul 16 12:17:31 2013
@@ -0,0 +1,70 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.jackrabbit.oak.plugins.index.solr.http;
+
+import org.apache.solr.client.solrj.SolrServer;
+import org.apache.solr.client.solrj.impl.CloudSolrServer;
+import org.apache.solr.client.solrj.request.UpdateRequest;
+import org.apache.solr.common.util.NamedList;
+import org.junit.Test;
+
+import static org.junit.Assert.assertNotNull;
+
+/**
+ * Testcase for {@link RemoteSolrServerProvider}
+ */
+public class RemoteSolrServerProviderIT {
+
+    // common local zk hosts
+    private final String[] zkHosts = new String[]{"localhost:9983"};
+
+    private boolean canCreateCollections(String host) throws Exception {
+        UpdateRequest req = new UpdateRequest("/admin/collections");
+        req.setParam("action", "CREATE");
+        String solrCollection = "solr_" + System.nanoTime();
+        req.setParam("name", solrCollection);
+        req.setParam("numShards", "2");
+        req.setParam("replicationFactor", "2");
+        req.setParam("collection.configName", "myconf");
+        CloudSolrServer cloudSolrServer = new CloudSolrServer(host);
+        NamedList<Object> request = cloudSolrServer.request(req);
+//        cloudSolrServer.shutdown();
+        return request != null && request.get("success") != null;
+    }
+
+    @Test
+    public void testCloudRemoteServerCreation() throws Exception {
+        // do this test only if a Solr Cloud server is available
+        for (String host : zkHosts) {
+            boolean cloudServerAvailable = false;
+            try {
+                cloudServerAvailable = canCreateCollections(host);
+            } catch (Exception e) {
+                // do nothing
+            }
+            if (cloudServerAvailable) {
+                String collection = "sample_" + System.nanoTime();
+                RemoteSolrServerProvider remoteSolrServerProvider = new RemoteSolrServerProvider(null, host, collection, 2, 2, null);
+                SolrServer solrServer = remoteSolrServerProvider.getSolrServer();
+                assertNotNull(solrServer);
+                solrServer.shutdown();
+                break;
+            }
+        }
+    }
+}

Propchange: jackrabbit/oak/trunk/oak-solr-remote/src/test/java/org/apache/jackrabbit/oak/plugins/index/solr/http/RemoteSolrServerProviderIT.java
------------------------------------------------------------------------------
    svn:eol-style = native