You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@gora.apache.org by le...@apache.org on 2013/06/30 21:10:54 UTC

svn commit: r1498171 - in /gora/trunk: ./ gora-solr/ gora-solr/src/ gora-solr/src/main/ gora-solr/src/main/java/ gora-solr/src/main/java/org/ gora-solr/src/main/java/org/apache/ gora-solr/src/main/java/org/apache/gora/ gora-solr/src/main/java/org/apach...

Author: lewismc
Date: Sun Jun 30 19:10:53 2013
New Revision: 1498171

URL: http://svn.apache.org/r1498171
Log:
GORA-9 Implement a Solr-based store

Added:
    gora/trunk/gora-solr/
    gora/trunk/gora-solr/pom.xml
    gora/trunk/gora-solr/src/
    gora/trunk/gora-solr/src/main/
    gora/trunk/gora-solr/src/main/java/
    gora/trunk/gora-solr/src/main/java/org/
    gora/trunk/gora-solr/src/main/java/org/apache/
    gora/trunk/gora-solr/src/main/java/org/apache/gora/
    gora/trunk/gora-solr/src/main/java/org/apache/gora/solr/
    gora/trunk/gora-solr/src/main/java/org/apache/gora/solr/query/
    gora/trunk/gora-solr/src/main/java/org/apache/gora/solr/query/SolrQuery.java
    gora/trunk/gora-solr/src/main/java/org/apache/gora/solr/query/SolrResult.java
    gora/trunk/gora-solr/src/main/java/org/apache/gora/solr/store/
    gora/trunk/gora-solr/src/main/java/org/apache/gora/solr/store/SolrMapping.java
    gora/trunk/gora-solr/src/main/java/org/apache/gora/solr/store/SolrStore.java
    gora/trunk/gora-solr/src/test/
    gora/trunk/gora-solr/src/test/conf/
    gora/trunk/gora-solr/src/test/conf/gora-solr-mapping.xml
    gora/trunk/gora-solr/src/test/conf/gora.properties
    gora/trunk/gora-solr/src/test/conf/solr/
    gora/trunk/gora-solr/src/test/conf/solr/Employee/
    gora/trunk/gora-solr/src/test/conf/solr/Employee/conf/
    gora/trunk/gora-solr/src/test/conf/solr/Employee/conf/schema.xml
    gora/trunk/gora-solr/src/test/conf/solr/Employee/conf/solrconfig.xml
    gora/trunk/gora-solr/src/test/conf/solr/WebPage/
    gora/trunk/gora-solr/src/test/conf/solr/WebPage/conf/
    gora/trunk/gora-solr/src/test/conf/solr/WebPage/conf/schema.xml
    gora/trunk/gora-solr/src/test/conf/solr/WebPage/conf/solrconfig.xml
    gora/trunk/gora-solr/src/test/conf/solr/collection1/
    gora/trunk/gora-solr/src/test/conf/solr/collection1/conf/
    gora/trunk/gora-solr/src/test/conf/solr/collection1/conf/schema.xml
    gora/trunk/gora-solr/src/test/conf/solr/collection1/conf/solrconfig.xml
    gora/trunk/gora-solr/src/test/conf/solr/solr.xml
    gora/trunk/gora-solr/src/test/java/
    gora/trunk/gora-solr/src/test/java/org/
    gora/trunk/gora-solr/src/test/java/org/apache/
    gora/trunk/gora-solr/src/test/java/org/apache/gora/
    gora/trunk/gora-solr/src/test/java/org/apache/gora/solr/
    gora/trunk/gora-solr/src/test/java/org/apache/gora/solr/GoraSolrTestDriver.java
    gora/trunk/gora-solr/src/test/java/org/apache/gora/solr/store/
    gora/trunk/gora-solr/src/test/java/org/apache/gora/solr/store/TestSolrStore.java
Modified:
    gora/trunk/pom.xml

Added: gora/trunk/gora-solr/pom.xml
URL: http://svn.apache.org/viewvc/gora/trunk/gora-solr/pom.xml?rev=1498171&view=auto
==============================================================================
--- gora/trunk/gora-solr/pom.xml (added)
+++ gora/trunk/gora-solr/pom.xml Sun Jun 30 19:10:53 2013
@@ -0,0 +1,222 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <!-- 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. -->
+  <modelVersion>4.0.0</modelVersion>
+
+  <parent>
+    <groupId>org.apache.gora</groupId>
+    <artifactId>gora</artifactId>
+    <version>0.4-SNAPSHOT</version>
+    <relativePath>../</relativePath>
+  </parent>
+  <artifactId>gora-solr</artifactId>
+  <packaging>bundle</packaging>
+
+  <name>Apache Gora :: Solr</name>
+
+  <properties>
+    <osgi.import>*</osgi.import>
+    <osgi.export>org.apache.gora.solr*;version="${project.version}";-noimport:=true</osgi.export>
+  </properties>
+
+  <build>
+    <directory>target</directory>
+    <outputDirectory>target/classes</outputDirectory>
+    <finalName>${project.artifactId}-${project.version}</finalName>
+    <testOutputDirectory>target/test-classes</testOutputDirectory>
+    <testSourceDirectory>src/test/java</testSourceDirectory>
+    <sourceDirectory>src/main/java</sourceDirectory>
+    <testResources>
+      <testResource>
+        <directory>${project.basedir}/src/test/conf/</directory>
+        <includes>
+          <include>**</include>
+        </includes>
+      </testResource>
+    </testResources>
+    <plugins>
+      <plugin>
+        <groupId>org.codehaus.mojo</groupId>
+        <artifactId>build-helper-maven-plugin</artifactId>
+        <version>${build-helper-maven-plugin.version}</version>
+        <executions>
+          <execution>
+            <phase>generate-sources</phase>
+            <goals>
+              <goal>add-source</goal>
+            </goals>
+            <configuration>
+              <sources>
+                <source>src/examples/java</source>
+              </sources>
+            </configuration>
+          </execution>
+        </executions>
+      </plugin>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-jar-plugin</artifactId>
+        <version>${maven-jar-plugin.version}</version>
+        <executions>
+          <execution>
+            <goals>
+              <goal>test-jar</goal>
+            </goals>
+          </execution>
+        </executions>
+      </plugin>
+    </plugins>
+  </build>
+  <repositories>
+    <repository>
+      <id>maven-restlet</id>
+      <name>Public online Restlet repository</name>
+      <url>http://maven.restlet.org</url>
+    </repository>
+  </repositories>
+
+  <dependencies>
+    <!-- Gora Internal Dependencies -->
+    <dependency>
+      <groupId>org.apache.gora</groupId>
+      <artifactId>gora-core</artifactId>
+      <exclusions>
+        <exclusion>
+          <artifactId>servlet-api</artifactId>
+          <groupId>org.mortbay.jetty</groupId>
+        </exclusion>
+        <exclusion>
+          <artifactId>servlet-api-2.5</artifactId>
+          <groupId>org.mortbay.jetty</groupId>
+        </exclusion>
+        <exclusion>
+          <artifactId>jetty-util</artifactId>
+          <groupId>org.mortbay.jetty</groupId>
+        </exclusion>
+        <exclusion>
+          <artifactId>jetty</artifactId>
+          <groupId>org.mortbay.jetty</groupId>
+        </exclusion>
+        <exclusion>
+          <groupId>com.google.guava</groupId>
+          <artifactId>guava</artifactId>
+        </exclusion>
+      </exclusions>
+    </dependency>
+
+    <dependency>
+      <groupId>org.apache.gora</groupId>
+      <artifactId>gora-core</artifactId>
+      <type>test-jar</type>
+      <scope>test</scope>
+    </dependency>
+
+    <!-- Logging Dependencies -->
+    <dependency>
+      <groupId>log4j</groupId>
+      <artifactId>log4j</artifactId>
+      <exclusions>
+        <exclusion>
+          <groupId>javax.jms</groupId>
+          <artifactId>jms</artifactId>
+        </exclusion>
+      </exclusions>
+    </dependency>
+    <dependency>
+      <groupId>org.slf4j</groupId>
+      <artifactId>slf4j-simple</artifactId>
+      <scope>test</scope>
+    </dependency>
+
+    <!-- Solr Dependencies -->
+    <dependency>
+      <groupId>org.apache.solr</groupId>
+      <artifactId>solr-core</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.solr</groupId>
+      <artifactId>solr-solrj</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>com.google.guava</groupId>
+      <artifactId>guava</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.tika</groupId>
+      <artifactId>tika-core</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.tika</groupId>
+      <artifactId>tika-parsers</artifactId>
+      <exclusions>
+        <exclusion>
+          <groupId>com.adobe.xmp</groupId>
+          <artifactId>xmpcore</artifactId>
+        </exclusion>
+        <exclusion>
+          <groupId>commons-logging</groupId>
+          <artifactId>commons-logging</artifactId>
+        </exclusion>
+        <exclusion>
+          <groupId>org.apache.geronimo.specs</groupId>
+          <artifactId>geronimo-stax-api_1.0_spec</artifactId>
+        </exclusion>
+        <exclusion>
+          <groupId>org.gagravarr</groupId>
+          <artifactId>vorbis-java-core</artifactId>
+        </exclusion>
+        <exclusion>
+          <groupId>asm</groupId>
+          <artifactId>asm</artifactId>
+        </exclusion>
+        <exclusion>
+          <groupId>org.aspectj</groupId>
+          <artifactId>aspectjrt</artifactId>
+        </exclusion>
+      </exclusions>
+    </dependency>
+    <dependency>
+      <groupId>org.eclipse.jetty</groupId>
+      <artifactId>jetty-server</artifactId>
+      <scope>compile</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.eclipse.jetty</groupId>
+      <artifactId>jetty-util</artifactId>
+      <scope>compile</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.eclipse.jetty</groupId>
+      <artifactId>jetty-webapp</artifactId>
+      <scope>compile</scope>
+    </dependency>
+
+    <!-- Testing Dependencies -->
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.solr</groupId>
+      <artifactId>solr-test-framework</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.lucene</groupId>
+      <artifactId>lucene-test-framework</artifactId>
+      <scope>test</scope>
+    </dependency>
+  </dependencies>
+
+</project>

Added: gora/trunk/gora-solr/src/main/java/org/apache/gora/solr/query/SolrQuery.java
URL: http://svn.apache.org/viewvc/gora/trunk/gora-solr/src/main/java/org/apache/gora/solr/query/SolrQuery.java?rev=1498171&view=auto
==============================================================================
--- gora/trunk/gora-solr/src/main/java/org/apache/gora/solr/query/SolrQuery.java (added)
+++ gora/trunk/gora-solr/src/main/java/org/apache/gora/solr/query/SolrQuery.java Sun Jun 30 19:10:53 2013
@@ -0,0 +1,62 @@
+/**
+ * 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.gora.solr.query;
+
+import org.apache.gora.persistency.impl.PersistentBase;
+import org.apache.gora.query.impl.QueryBase;
+import org.apache.gora.solr.store.SolrMapping;
+import org.apache.gora.solr.store.SolrStore;
+import org.apache.gora.store.DataStore;
+
+public class SolrQuery<K, T extends PersistentBase> extends QueryBase<K, T> {
+  SolrStore<K, T> store;
+
+  public SolrQuery() {
+    super(null);
+    store = null;
+  }
+  
+  public SolrQuery(DataStore<K, T> dataStore) {
+    super(dataStore);
+    store = (SolrStore<K, T>)dataStore;
+  }
+  
+  public String toSolrQuery() {
+    SolrMapping mapping = store.getMapping();
+    String fld = mapping.getPrimaryKey();
+    String q;
+    if (getKey() != null) {
+      q = fld + ":" + SolrStore.escapeQueryKey(getKey().toString());
+    } else {
+      q = fld + ":[";
+      if (getStartKey() != null) {
+        q += SolrStore.escapeQueryKey(getStartKey().toString());
+      } else {
+        q += "*";
+      }
+      q += " TO ";
+      if (getEndKey() != null) {
+        q += SolrStore.escapeQueryKey(getEndKey().toString());
+      } else {
+        q += "*";
+      }
+      q += "]";
+    }
+    return q;
+  }
+}

Added: gora/trunk/gora-solr/src/main/java/org/apache/gora/solr/query/SolrResult.java
URL: http://svn.apache.org/viewvc/gora/trunk/gora-solr/src/main/java/org/apache/gora/solr/query/SolrResult.java?rev=1498171&view=auto
==============================================================================
--- gora/trunk/gora-solr/src/main/java/org/apache/gora/solr/query/SolrResult.java (added)
+++ gora/trunk/gora-solr/src/main/java/org/apache/gora/solr/query/SolrResult.java Sun Jun 30 19:10:53 2013
@@ -0,0 +1,103 @@
+/**
+ * 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.gora.solr.query;
+
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.HashSet;
+
+import org.apache.gora.persistency.impl.PersistentBase;
+import org.apache.gora.query.Query;
+import org.apache.gora.query.impl.PartitionQueryImpl;
+import org.apache.gora.query.impl.ResultBase;
+import org.apache.gora.solr.store.SolrStore;
+import org.apache.gora.store.DataStore;
+import org.apache.solr.client.solrj.SolrServer;
+import org.apache.solr.client.solrj.SolrServerException;
+import org.apache.solr.client.solrj.response.QueryResponse;
+import org.apache.solr.common.SolrDocument;
+import org.apache.solr.common.SolrDocumentList;
+import org.apache.solr.common.params.CommonParams;
+import org.apache.solr.common.params.ModifiableSolrParams;
+
+public class SolrResult<K, T extends PersistentBase> extends ResultBase<K, T> {
+  SolrDocumentList list = null;
+  SolrStore<K, T> store;
+  String[] fields;
+  int pos = 0;
+
+  public SolrResult(DataStore<K, T> dataStore, Query<K, T> query,
+      SolrServer server, int resultsSize) throws IOException {
+    super(dataStore, query);
+    store = (SolrStore<K, T>)dataStore;
+    ModifiableSolrParams params = new ModifiableSolrParams();
+    if (query instanceof PartitionQueryImpl) {
+      query = ((PartitionQueryImpl<K, T>)query).getBaseQuery();
+    }
+    String q = ((SolrQuery<K, T>)query).toSolrQuery();
+    params.set(CommonParams.Q, q);
+    fields = query.getFields();
+    if (fields == null) {
+      params.set(CommonParams.FL, "*");
+    } else {
+      HashSet<String> uniqFields = new HashSet<String>(Arrays.asList(fields));
+      String keyFld = ((SolrStore<K, T>)dataStore).getMapping().getPrimaryKey();
+      uniqFields.add(keyFld); // return also primary key
+      StringBuilder sb = new StringBuilder();
+      for (String f : uniqFields) {
+        if (sb.length() > 0) sb.append(',');
+        sb.append(f);
+      }
+      params.set(CommonParams.FL, sb.toString());
+    }
+    params.set(CommonParams.ROWS, resultsSize);
+    try {
+      QueryResponse rsp = server.query(params);
+      list = rsp.getResults();
+    } catch (SolrServerException e) {
+      e.printStackTrace();
+      throw new IOException(e);
+    }
+  }
+
+  @SuppressWarnings("unchecked")
+  @Override
+  protected boolean nextInner() throws IOException {
+    if (list == null || pos >= list.size()) {
+      return false;
+    }
+    SolrDocument doc = list.get(pos++);
+    key = (K) doc.get(store.getMapping().getPrimaryKey());
+    persistent = store.newInstance(doc, fields);
+    return true;
+  }
+  
+  @Override
+  public void close() throws IOException {
+    if (list != null) list.clear();
+  }
+
+  @Override
+  public float getProgress() throws IOException {
+    if (list != null && list.size() > 0) {
+      return (float)pos / (float)list.size();
+    } else {
+      return 0;
+    }
+  }
+}

Added: gora/trunk/gora-solr/src/main/java/org/apache/gora/solr/store/SolrMapping.java
URL: http://svn.apache.org/viewvc/gora/trunk/gora-solr/src/main/java/org/apache/gora/solr/store/SolrMapping.java?rev=1498171&view=auto
==============================================================================
--- gora/trunk/gora-solr/src/main/java/org/apache/gora/solr/store/SolrMapping.java (added)
+++ gora/trunk/gora-solr/src/main/java/org/apache/gora/solr/store/SolrMapping.java Sun Jun 30 19:10:53 2013
@@ -0,0 +1,55 @@
+/**
+ * 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.gora.solr.store;
+
+import java.util.HashMap;
+
+public class SolrMapping {
+  HashMap<String,String> mapping;
+  String coreName;
+  String primaryKey;
+  
+  public SolrMapping() {
+    mapping = new HashMap<String,String>();
+  }
+  
+  public void addField(String goraField, String solrField) {
+    mapping.put(goraField, solrField);
+  }
+  
+  public void setPrimaryKey(String solrKey) {
+    primaryKey = solrKey;
+  }
+  
+  public void setCoreName(String coreName) {
+    this.coreName = coreName;
+  }
+  
+  public String getCoreName() {
+    return coreName;
+  }
+  
+  public String getPrimaryKey() {
+    return primaryKey;
+  }
+  
+  public String getSolrField(String goraField) {
+    return mapping.get(goraField);
+  }
+  
+}

Added: gora/trunk/gora-solr/src/main/java/org/apache/gora/solr/store/SolrStore.java
URL: http://svn.apache.org/viewvc/gora/trunk/gora-solr/src/main/java/org/apache/gora/solr/store/SolrStore.java?rev=1498171&view=auto
==============================================================================
--- gora/trunk/gora-solr/src/main/java/org/apache/gora/solr/store/SolrStore.java (added)
+++ gora/trunk/gora-solr/src/main/java/org/apache/gora/solr/store/SolrStore.java Sun Jun 30 19:10:53 2013
@@ -0,0 +1,526 @@
+/**
+ * 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.gora.solr.store;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Properties;
+
+import org.apache.avro.Schema;
+import org.apache.avro.Schema.Field;
+import org.apache.avro.util.Utf8;
+import org.apache.gora.persistency.StateManager;
+import org.apache.gora.persistency.impl.PersistentBase;
+import org.apache.gora.query.PartitionQuery;
+import org.apache.gora.query.Query;
+import org.apache.gora.query.Result;
+import org.apache.gora.query.impl.PartitionQueryImpl;
+import org.apache.gora.solr.query.SolrQuery;
+import org.apache.gora.solr.query.SolrResult;
+import org.apache.gora.store.DataStoreFactory;
+import org.apache.gora.store.impl.DataStoreBase;
+import org.apache.gora.util.AvroUtils;
+import org.apache.gora.util.IOUtils;
+import org.apache.solr.client.solrj.SolrServer;
+import org.apache.solr.client.solrj.SolrServerException;
+import org.apache.solr.client.solrj.impl.HttpSolrServer;
+import org.apache.solr.client.solrj.request.CoreAdminRequest;
+import org.apache.solr.client.solrj.response.CoreAdminResponse;
+import org.apache.solr.client.solrj.response.QueryResponse;
+import org.apache.solr.client.solrj.response.UpdateResponse;
+import org.apache.solr.common.SolrDocument;
+import org.apache.solr.common.SolrInputDocument;
+import org.apache.solr.common.params.CommonParams;
+import org.apache.solr.common.params.ModifiableSolrParams;
+import org.jdom.Document;
+import org.jdom.Element;
+import org.jdom.input.SAXBuilder;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class SolrStore<K, T extends PersistentBase>
+    extends DataStoreBase<K, T> {
+    
+    private static final Logger LOG = LoggerFactory.getLogger( SolrStore.class );
+
+    protected static final String DEFAULT_MAPPING_FILE = "gora-solr-mapping.xml";
+
+    protected static final String SOLR_URL_PROPERTY = "solr.url";
+
+    protected static final String SOLR_CONFIG_PROPERTY = "solr.config";
+
+    protected static final String SOLR_SCHEMA_PROPERTY = "solr.schema";
+    
+    protected static final String SOLR_BATCH_SIZE_PROPERTY = "solr.batchSize";
+
+    protected static final String SOLR_COMMIT_WITHIN_PROPERTY = "solr.commitWithin";
+
+    protected static final String SOLR_RESULTS_SIZE_PROPERTY = "solr.resultsSize";
+    
+    protected static final int DEFAULT_BATCH_SIZE = 100;
+
+    protected static final int DEFAULT_COMMIT_WITHIN = 1000;
+
+    protected static final int DEFAULT_RESULTS_SIZE = 100;
+
+    private SolrMapping mapping;
+
+    private String solrServerUrl, solrConfig, solrSchema;
+
+    private SolrServer server, adminServer;
+
+    private ArrayList<SolrInputDocument> batch;
+
+    private int batchSize = DEFAULT_BATCH_SIZE;
+
+    private int commitWithin = DEFAULT_COMMIT_WITHIN;
+
+    private int resultsSize = DEFAULT_RESULTS_SIZE;
+
+    @Override
+    public void initialize( Class<K> keyClass, Class<T> persistentClass, Properties properties ) {
+        super.initialize( keyClass, persistentClass, properties );
+        String mappingFile = DataStoreFactory.getMappingFile( properties, this, DEFAULT_MAPPING_FILE );
+        try {
+            mapping = readMapping( mappingFile );
+        }
+        catch ( IOException e ) {
+            LOG.error( e.getMessage() );
+            LOG.error( e.getStackTrace().toString() );
+        }
+
+        solrServerUrl = DataStoreFactory.findProperty( properties, this, SOLR_URL_PROPERTY, null );
+        solrConfig = DataStoreFactory.findProperty( properties, this, SOLR_CONFIG_PROPERTY, null );
+        solrSchema = DataStoreFactory.findProperty( properties, this, SOLR_SCHEMA_PROPERTY, null );
+        LOG.info( "Using Solr server at " + solrServerUrl );
+        adminServer = new HttpSolrServer( solrServerUrl );
+        server = new HttpSolrServer( solrServerUrl + "/" + mapping.getCoreName() );
+        if ( autoCreateSchema ) {
+            createSchema();
+        }
+        String batchSizeString = DataStoreFactory.findProperty( properties, this, SOLR_BATCH_SIZE_PROPERTY, null );
+        if ( batchSizeString != null ) {
+            try {
+                batchSize = Integer.parseInt( batchSizeString );
+            }
+            catch ( NumberFormatException nfe ) {
+                LOG.warn( "Invalid batch size '" + batchSizeString + "', using default " + DEFAULT_BATCH_SIZE );
+            }
+        }
+        batch = new ArrayList<SolrInputDocument>( batchSize );
+        String commitWithinString = DataStoreFactory.findProperty( properties, this, SOLR_COMMIT_WITHIN_PROPERTY, null );
+        if ( commitWithinString != null ) {
+            try {
+                commitWithin = Integer.parseInt( commitWithinString );
+            }
+            catch ( NumberFormatException nfe ) {
+                LOG.warn( "Invalid commit within '" + commitWithinString + "', using default " + DEFAULT_COMMIT_WITHIN );
+            }
+        }
+        String resultsSizeString = DataStoreFactory.findProperty( properties, this, SOLR_RESULTS_SIZE_PROPERTY, null );
+        if ( resultsSizeString != null ) {
+            try {
+                resultsSize = Integer.parseInt( resultsSizeString );
+            }
+            catch ( NumberFormatException nfe ) {
+                LOG.warn( "Invalid results size '" + resultsSizeString + "', using default " + DEFAULT_RESULTS_SIZE );
+            }
+        }
+    }
+
+    @SuppressWarnings("unchecked")
+    private SolrMapping readMapping( String filename )
+        throws IOException {
+        SolrMapping map = new SolrMapping();
+        try {
+            SAXBuilder builder = new SAXBuilder();
+            Document doc = builder.build( getClass().getClassLoader().getResourceAsStream( filename ) );
+
+            List<Element> classes = doc.getRootElement().getChildren( "class" );
+
+            for ( Element classElement : classes ) {
+                if ( classElement.getAttributeValue( "keyClass" ).equals( keyClass.getCanonicalName() )
+                    && classElement.getAttributeValue( "name" ).equals( persistentClass.getCanonicalName() ) ) {
+
+                    String tableName = getSchemaName( classElement.getAttributeValue( "table" ), persistentClass );
+                    map.setCoreName( tableName );
+
+                    Element primaryKeyEl = classElement.getChild( "primarykey" );
+                    map.setPrimaryKey( primaryKeyEl.getAttributeValue( "column" ) );
+
+                    List<Element> fields = classElement.getChildren( "field" );
+
+                    for ( Element field : fields ) {
+                        String fieldName = field.getAttributeValue( "name" );
+                        String columnName = field.getAttributeValue( "column" );
+                        map.addField( fieldName, columnName );
+                    }
+                    break;
+                }
+            }
+        }
+        catch ( Exception ex ) {
+            throw new IOException( ex );
+        }
+
+        return map;
+    }
+
+    public SolrMapping getMapping() {
+        return mapping;
+    }
+
+    @Override
+    public String getSchemaName() {
+        return mapping.getCoreName();
+    }
+
+    @Override
+    public void createSchema() {
+        try {
+            if ( !schemaExists() )
+                CoreAdminRequest.createCore( mapping.getCoreName(), mapping.getCoreName(), adminServer, solrConfig,
+                                             solrSchema );
+        }
+        catch ( Exception e ) {
+            LOG.error( e.getMessage(), e.getStackTrace().toString() );
+        }
+    }
+
+    @Override
+    /** Default implementation deletes and recreates the schema*/
+    public void truncateSchema() {
+        try {
+            server.deleteByQuery( "*:*" );
+            server.commit();
+        }
+        catch ( Exception e ) {
+            // ignore?
+            LOG.error( e.getMessage(), e.getStackTrace().toString() );
+        }
+    }
+
+    @Override
+    public void deleteSchema() {
+        // XXX should this be only in truncateSchema ???
+        try {
+            server.deleteByQuery( "*:*" );
+            server.commit();
+        }
+        catch ( Exception e ) {
+            // ignore?
+            // LOG.error(e.getMessage());
+            // LOG.error(e.getStackTrace().toString());
+        }
+        try {
+            CoreAdminRequest.unloadCore( mapping.getCoreName(), adminServer );
+        }
+        catch ( Exception e ) {
+            if ( e.getMessage().contains( "No such core" ) ) {
+                return; // it's ok, the core is not there
+            }
+            else {
+                LOG.error( e.getMessage(), e.getStackTrace().toString() );
+            }
+        }
+    }
+
+    @Override
+    public boolean schemaExists() {
+        boolean exists = false;
+        try {
+            CoreAdminResponse rsp = CoreAdminRequest.getStatus( mapping.getCoreName(), adminServer );
+            exists = rsp.getUptime( mapping.getCoreName() ) != null;
+        }
+        catch ( Exception e ) {
+            LOG.error( e.getMessage(), e.getStackTrace().toString() );
+        }
+        return exists;
+    }
+
+    private static final String toDelimitedString( String[] arr, String sep ) {
+        if ( arr == null || arr.length == 0 ) {
+            return "";
+        }
+        StringBuilder sb = new StringBuilder();
+        for ( int i = 0; i < arr.length; i++ ) {
+            if ( i > 0 )
+                sb.append( sep );
+            sb.append( arr[i] );
+        }
+        return sb.toString();
+    }
+
+    public static String escapeQueryKey( String key ) {
+        if ( key == null ) {
+            return null;
+        }
+        StringBuilder sb = new StringBuilder();
+        for ( int i = 0; i < key.length(); i++ ) {
+            char c = key.charAt( i );
+            switch ( c ) {
+                case ':':
+                case '*':
+                    sb.append( "\\" + c );
+                    break;
+                default:
+                    sb.append( c );
+            }
+        }
+        return sb.toString();
+    }
+
+    @Override
+    public T get( K key, String[] fields ) {
+        ModifiableSolrParams params = new ModifiableSolrParams();
+        params.set( CommonParams.QT, "/get" );
+        params.set( CommonParams.FL, toDelimitedString( fields, "," ) );
+        params.set( "id",  key.toString() );
+        try {
+            QueryResponse rsp = server.query( params );
+            Object o = rsp.getResponse().get( "doc" );
+            if ( o == null ) {
+                return null;
+            }
+            return newInstance( (SolrDocument)o, fields );
+        }
+        catch ( Exception e ) {
+            LOG.error( e.getMessage(), e.getStackTrace().toString() );
+        }
+        return null;
+    }
+
+    public T newInstance( SolrDocument doc, String[] fields )
+        throws IOException {
+        T persistent = newPersistent();
+        if ( fields == null ) {
+            fields = fieldMap.keySet().toArray( new String[fieldMap.size()] );
+        }
+        String pk = mapping.getPrimaryKey();
+        for ( String f : fields ) {
+            Field field = fieldMap.get( f );
+            Schema fieldSchema = field.schema();
+            String sf = null;
+            if ( pk.equals( f ) ) {
+                sf = f;
+            }
+            else {
+                sf = mapping.getSolrField( f );                
+            }
+            Object sv = doc.get( sf );
+            Object v;
+            if ( sv == null ) {
+                continue;
+            }
+            switch ( fieldSchema.getType() ) {
+                case MAP:
+                case ARRAY:
+                case RECORD:
+                    v = IOUtils.deserialize( (byte[]) sv, datumReader, fieldSchema, persistent.get( field.pos() ) );
+                    persistent.put( field.pos(), v );
+                    break;
+                case ENUM:
+                    v = AvroUtils.getEnumValue( fieldSchema, (String) sv );
+                    persistent.put( field.pos(), v );
+                    break;
+                case FIXED:
+                    throw new IOException( "???" );
+                    // break;
+                case BYTES:
+                    persistent.put( field.pos(), ByteBuffer.wrap( (byte[]) sv ) );
+                    break;
+                case BOOLEAN:
+                case DOUBLE:
+                case FLOAT:
+                case INT:
+                case LONG:
+                    persistent.put( field.pos(), sv );
+                    break;
+                case STRING:
+                    persistent.put( field.pos(), new Utf8( sv.toString() ) );
+                    break;
+                case UNION:
+                    LOG.error( "Union is not supported yet" );
+                    break;
+                default:
+                    LOG.error( "Unknown field type: " + fieldSchema.getType() );
+            }
+            persistent.setDirty( field.pos() );
+        }
+        persistent.clearDirty();
+        return persistent;
+    }
+
+    @Override
+    public void put( K key, T persistent ) {
+        Schema schema = persistent.getSchema();
+        StateManager stateManager = persistent.getStateManager();
+        if ( !stateManager.isDirty( persistent ) ) {
+            // nothing to do
+            return;
+        }
+        SolrInputDocument doc = new SolrInputDocument();
+        // add primary key
+        doc.addField( mapping.getPrimaryKey(), key );
+        // populate the doc
+        List<Field> fields = schema.getFields();
+        for ( Field field : fields ) {
+            String sf = mapping.getSolrField( field.name() );
+            // Solr will append values to fields in a SolrInputDocument, even the key
+            // mapping won't find the primary
+            if ( sf == null ) {
+                continue;
+            }
+            Schema fieldSchema = field.schema();
+            Object v = persistent.get( field.pos() );
+            if ( v == null ) {
+                continue;
+            }
+            switch ( fieldSchema.getType() ) {
+                case MAP:
+                case ARRAY:
+                case RECORD:
+                    byte[] data = null;
+                    try {
+                        data = IOUtils.serialize( datumWriter, fieldSchema, v );
+                    }
+                    catch ( IOException e ) {
+                        LOG.error( e.getMessage(), e.getStackTrace().toString() );
+                    }
+                    doc.addField( sf, data );
+                    break;
+                case BYTES:
+                    doc.addField( sf, ( (ByteBuffer) v ).array() );
+                    break;
+                case ENUM:
+                case STRING:
+                    doc.addField( sf, v.toString() );
+                    break;
+                case BOOLEAN:
+                case DOUBLE:
+                case FLOAT:
+                case INT:
+                case LONG:
+                    doc.addField( sf, v );
+                    break;
+                case UNION:
+                    LOG.error( "Union is not supported yet" );
+                    break;
+                default:
+                    LOG.error( "Unknown field type: " + fieldSchema.getType() );
+            }
+        }
+        System.out.println( "DOCUMENT: " + doc );
+        batch.add( doc );
+        if ( batch.size() >= batchSize ) {
+            try {
+                add( batch, commitWithin );
+                batch.clear();
+            }
+            catch ( Exception e ) {
+                LOG.error( e.getMessage(), e.getStackTrace().toString() );
+            }
+        }
+    }
+
+    @Override
+    public boolean delete( K key ) {
+        String keyField = mapping.getPrimaryKey();
+        try {
+            UpdateResponse rsp = server.deleteByQuery( keyField + ":" + escapeQueryKey( key.toString() ) );
+            server.commit();
+            LOG.info( rsp.toString() );
+            return true;
+        }
+        catch ( Exception e ) {
+            LOG.error( e.getMessage(), e.getStackTrace().toString() );
+        }
+        return false;
+    }
+
+    @Override
+    public long deleteByQuery( Query<K, T> query ) {
+        String q = ( (SolrQuery<K, T>) query ).toSolrQuery();
+        try {
+            UpdateResponse rsp = server.deleteByQuery( q );
+            server.commit();
+            LOG.info( rsp.toString() );
+        }
+        catch ( Exception e ) {
+            LOG.error( e.getMessage(), e.getStackTrace().toString() );
+        }
+        return 0;
+    }
+
+    @Override
+    public Result<K, T> execute( Query<K, T> query ) {
+        try {
+            return new SolrResult<K, T>( this, query, server, resultsSize );
+        }
+        catch ( IOException e ) {
+            LOG.error( e.getMessage(), e.getStackTrace().toString() );
+        }
+        return null;
+    }
+
+    @Override
+    public Query<K, T> newQuery() {
+        return new SolrQuery<K, T>( this );
+    }
+
+    @Override
+    public List<PartitionQuery<K, T>> getPartitions( Query<K, T> query )
+        throws IOException {
+        // TODO: implement this using Hadoop DB support
+
+        ArrayList<PartitionQuery<K, T>> partitions = new ArrayList<PartitionQuery<K, T>>();
+        partitions.add( new PartitionQueryImpl<K, T>( query ) );
+
+        return partitions;
+    }
+
+    @Override
+    public void flush() {
+        try {
+            if ( batch.size() > 0 ) {
+                add( batch, commitWithin );
+                batch.clear();
+            }
+        }
+        catch ( Exception e ) {
+            LOG.error(e.getMessage(), e.getStackTrace());
+        }
+    }
+
+    @Override
+    public void close() {
+        // In testing, the index gets closed before the commit in flush() can happen
+        // so an exception gets thrown
+        //flush();
+    }
+    
+    private void add(ArrayList<SolrInputDocument> batch, int commitWithin) throws SolrServerException, IOException {
+        if (commitWithin == 0) {
+            server.add( batch );
+            server.commit( false, true, true );
+        }
+        else {
+            server.add( batch, commitWithin );            
+        }
+    }
+    
+}

Added: gora/trunk/gora-solr/src/test/conf/gora-solr-mapping.xml
URL: http://svn.apache.org/viewvc/gora/trunk/gora-solr/src/test/conf/gora-solr-mapping.xml?rev=1498171&view=auto
==============================================================================
--- gora/trunk/gora-solr/src/test/conf/gora-solr-mapping.xml (added)
+++ gora/trunk/gora-solr/src/test/conf/gora-solr-mapping.xml Sun Jun 30 19:10:53 2013
@@ -0,0 +1,35 @@
+<?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.
+-->
+
+<gora-orm>
+  <class name="org.apache.gora.examples.generated.Employee" keyClass="java.lang.String" table="Employee">
+    <primarykey column="ssn"/>
+    <field name="name" column="name"/>
+    <field name="dateOfBirth" column="dateOfBirth"/>
+    <field name="salary" column="salary"/>
+  </class>
+
+  <class name="org.apache.gora.examples.generated.WebPage" keyClass="java.lang.String" table="WebPage">
+    <primarykey column="url"/>
+    <field name="content" column="content"/>
+    <field name="parsedContent" column="parsedContent"/>
+    <field name="outlinks" column="outlinks"/>
+    <field name="metadata" column="metadata"/>
+  </class>
+</gora-orm>
+

Added: gora/trunk/gora-solr/src/test/conf/gora.properties
URL: http://svn.apache.org/viewvc/gora/trunk/gora-solr/src/test/conf/gora.properties?rev=1498171&view=auto
==============================================================================
--- gora/trunk/gora-solr/src/test/conf/gora.properties (added)
+++ gora/trunk/gora-solr/src/test/conf/gora.properties Sun Jun 30 19:10:53 2013
@@ -0,0 +1 @@
+gora.solrstore.solr.url=http://localhost:9876/solr

Added: gora/trunk/gora-solr/src/test/conf/solr/Employee/conf/schema.xml
URL: http://svn.apache.org/viewvc/gora/trunk/gora-solr/src/test/conf/solr/Employee/conf/schema.xml?rev=1498171&view=auto
==============================================================================
--- gora/trunk/gora-solr/src/test/conf/solr/Employee/conf/schema.xml (added)
+++ gora/trunk/gora-solr/src/test/conf/solr/Employee/conf/schema.xml Sun Jun 30 19:10:53 2013
@@ -0,0 +1,42 @@
+<?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="testexample" version="1.5">
+
+  <fields>
+
+    <!-- Common Fields -->
+    <field name="_version_" type="long" indexed="true" stored="true"/>
+
+    <!-- Employee Fields -->
+    <field name="ssn"         type="string" indexed="true" stored="true" required="true" multiValued="false" /> 
+    <field name="name"        type="string" indexed="true" stored="true" />
+    <field name="dateOfBirth" type="long" stored="true" /> 
+    <field name="salary"      type="int" stored="true" /> 
+
+  </fields>
+
+  <uniqueKey>ssn</uniqueKey>
+
+  <types>
+    <fieldType name="string" class="solr.StrField" sortMissingLast="true" />
+    <fieldType name="int" class="solr.TrieIntField" precisionStep="0" positionIncrementGap="0"/>
+    <fieldType name="long" class="solr.TrieLongField" precisionStep="0" positionIncrementGap="0"/>
+  </types>  
+
+</schema>

Added: gora/trunk/gora-solr/src/test/conf/solr/Employee/conf/solrconfig.xml
URL: http://svn.apache.org/viewvc/gora/trunk/gora-solr/src/test/conf/solr/Employee/conf/solrconfig.xml?rev=1498171&view=auto
==============================================================================
--- gora/trunk/gora-solr/src/test/conf/solr/Employee/conf/solrconfig.xml (added)
+++ gora/trunk/gora-solr/src/test/conf/solr/Employee/conf/solrconfig.xml Sun Jun 30 19:10:53 2013
@@ -0,0 +1,107 @@
+<?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.NRTCachingDirectoryFactory}"/> 
+  <codecFactory class="solr.SchemaCodecFactory"/>
+  <schemaFactory class="ClassicIndexSchemaFactory"/>
+  <indexConfig>
+    <lockType>${solr.lock.type:native}</lockType>
+  </indexConfig>
+
+  <jmx />
+
+  <updateHandler class="solr.DirectUpdateHandler2">
+    <updateLog>
+      <str name="dir">${solr.ulog.dir:}</str>
+    </updateLog>
+  </updateHandler>
+  
+  <query>
+    <maxBooleanClauses>1024</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>
+    <listener event="newSearcher" class="solr.QuerySenderListener">
+      <arr name="queries">
+      </arr>
+    </listener>
+    <listener event="firstSearcher" class="solr.QuerySenderListener">
+      <arr name="queries">
+        <lst>
+          <str name="q">static firstSearcher warming in solrconfig.xml</str>
+        </lst>
+      </arr>
+    </listener>
+    <useColdSearcher>false</useColdSearcher>
+    <maxWarmingSearchers>2</maxWarmingSearchers>
+  </query>
+
+  <requestDispatcher handleSelect="false" >
+    <requestParsers enableRemoteStreaming="true" 
+                    multipartUploadLimitInKB="2048000"
+                    formdataUploadLimitInKB="2048"
+                    addHttpRequestToContext="false"/>
+    <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">ssn</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">ssn</str>
+    </lst>
+  </requestHandler>
+
+  <requestHandler name="/get" class="solr.RealTimeGetHandler">
+    <lst name="defaults">
+      <str name="omitHeader">true</str>
+    </lst>
+  </requestHandler>
+
+  <requestHandler name="/update" class="solr.UpdateRequestHandler">
+  </requestHandler>
+</config>

Added: gora/trunk/gora-solr/src/test/conf/solr/WebPage/conf/schema.xml
URL: http://svn.apache.org/viewvc/gora/trunk/gora-solr/src/test/conf/solr/WebPage/conf/schema.xml?rev=1498171&view=auto
==============================================================================
--- gora/trunk/gora-solr/src/test/conf/solr/WebPage/conf/schema.xml (added)
+++ gora/trunk/gora-solr/src/test/conf/solr/WebPage/conf/schema.xml Sun Jun 30 19:10:53 2013
@@ -0,0 +1,43 @@
+<?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="testexample" version="1.5">
+
+  <fields>
+
+    <!-- Common Fields -->
+    <field name="_version_" type="long" indexed="true" stored="true"/>
+
+    <!-- WebPage Fields -->
+    <field name="url"           type="string" indexed="true" stored="true" required="true" multiValued="false" />
+    <field name="parsedContent" type="binary" stored="true" /> 
+    <field name="content"       type="binary" stored="true" /> 
+    <field name="outlinks"      type="binary" stored="true" /> 
+    <field name="metadata"      type="binary" stored="true" />    
+
+  </fields>
+
+  <uniqueKey>url</uniqueKey>
+  
+  <types>
+    <fieldType name="string" class="solr.StrField" sortMissingLast="true" />
+    <fieldType name="long" class="solr.TrieLongField" precisionStep="0" positionIncrementGap="0"/>
+    <fieldtype name="binary" class="solr.BinaryField"/>
+  </types>  
+
+</schema>

Added: gora/trunk/gora-solr/src/test/conf/solr/WebPage/conf/solrconfig.xml
URL: http://svn.apache.org/viewvc/gora/trunk/gora-solr/src/test/conf/solr/WebPage/conf/solrconfig.xml?rev=1498171&view=auto
==============================================================================
--- gora/trunk/gora-solr/src/test/conf/solr/WebPage/conf/solrconfig.xml (added)
+++ gora/trunk/gora-solr/src/test/conf/solr/WebPage/conf/solrconfig.xml Sun Jun 30 19:10:53 2013
@@ -0,0 +1,107 @@
+<?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.NRTCachingDirectoryFactory}"/> 
+  <codecFactory class="solr.SchemaCodecFactory"/>
+  <schemaFactory class="ClassicIndexSchemaFactory"/>
+  <indexConfig>
+    <lockType>${solr.lock.type:native}</lockType>
+  </indexConfig>
+
+  <jmx />
+
+  <updateHandler class="solr.DirectUpdateHandler2">
+    <updateLog>
+      <str name="dir">${solr.ulog.dir:}</str>
+    </updateLog>
+  </updateHandler>
+  
+  <query>
+    <maxBooleanClauses>1024</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>
+    <listener event="newSearcher" class="solr.QuerySenderListener">
+      <arr name="queries">
+      </arr>
+    </listener>
+    <listener event="firstSearcher" class="solr.QuerySenderListener">
+      <arr name="queries">
+        <lst>
+          <str name="q">static firstSearcher warming in solrconfig.xml</str>
+        </lst>
+      </arr>
+    </listener>
+    <useColdSearcher>false</useColdSearcher>
+    <maxWarmingSearchers>2</maxWarmingSearchers>
+  </query>
+
+  <requestDispatcher handleSelect="false" >
+    <requestParsers enableRemoteStreaming="true" 
+                    multipartUploadLimitInKB="2048000"
+                    formdataUploadLimitInKB="2048"
+                    addHttpRequestToContext="false"/>
+    <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">url</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">url</str>
+    </lst>
+  </requestHandler>
+
+  <requestHandler name="/get" class="solr.RealTimeGetHandler">
+    <lst name="defaults">
+      <str name="omitHeader">true</str>
+    </lst>
+  </requestHandler>
+
+  <requestHandler name="/update" class="solr.UpdateRequestHandler">
+  </requestHandler>
+</config>

Added: gora/trunk/gora-solr/src/test/conf/solr/collection1/conf/schema.xml
URL: http://svn.apache.org/viewvc/gora/trunk/gora-solr/src/test/conf/solr/collection1/conf/schema.xml?rev=1498171&view=auto
==============================================================================
--- gora/trunk/gora-solr/src/test/conf/solr/collection1/conf/schema.xml (added)
+++ gora/trunk/gora-solr/src/test/conf/solr/collection1/conf/schema.xml Sun Jun 30 19:10:53 2013
@@ -0,0 +1,32 @@
+<?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="testexample" version="1.5">
+  <fields>
+    <!-- Common Fields -->
+    <field name="id"        type="string" indexed="true" stored="true" required="true" multiValued="false" /> 
+    <field name="_version_" type="long" indexed="true" stored="true"/>
+  </fields>
+
+  <uniqueKey>id</uniqueKey>
+
+  <types>
+    <fieldType name="string" class="solr.StrField" sortMissingLast="true" />
+    <fieldType name="long" class="solr.TrieLongField" precisionStep="0" positionIncrementGap="0"/>
+  </types>  
+</schema>

Added: gora/trunk/gora-solr/src/test/conf/solr/collection1/conf/solrconfig.xml
URL: http://svn.apache.org/viewvc/gora/trunk/gora-solr/src/test/conf/solr/collection1/conf/solrconfig.xml?rev=1498171&view=auto
==============================================================================
--- gora/trunk/gora-solr/src/test/conf/solr/collection1/conf/solrconfig.xml (added)
+++ gora/trunk/gora-solr/src/test/conf/solr/collection1/conf/solrconfig.xml Sun Jun 30 19:10:53 2013
@@ -0,0 +1,113 @@
+<?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.NRTCachingDirectoryFactory}"/> 
+  <codecFactory class="solr.SchemaCodecFactory"/>
+  <schemaFactory class="ClassicIndexSchemaFactory"/>
+  <indexConfig>
+    <lockType>${solr.lock.type:native}</lockType>
+  </indexConfig>
+
+  <jmx />
+
+  <updateHandler class="solr.DirectUpdateHandler2">
+    <updateLog>
+      <str name="dir">${solr.ulog.dir:}</str>
+    </updateLog>
+     <autoCommit> 
+       <maxTime>15000</maxTime> 
+       <openSearcher>false</openSearcher> 
+     </autoCommit>
+  </updateHandler>
+  
+  <query>
+    <maxBooleanClauses>1024</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>
+    <listener event="newSearcher" class="solr.QuerySenderListener">
+      <arr name="queries">
+      </arr>
+    </listener>
+    <listener event="firstSearcher" class="solr.QuerySenderListener">
+      <arr name="queries">
+        <lst>
+          <str name="q">static firstSearcher warming in solrconfig.xml</str>
+        </lst>
+      </arr>
+    </listener>
+    <useColdSearcher>false</useColdSearcher>
+    <maxWarmingSearchers>2</maxWarmingSearchers>
+  </query>
+
+  <requestDispatcher handleSelect="false" >
+    <requestParsers enableRemoteStreaming="true" 
+                    multipartUploadLimitInKB="2048000"
+                    formdataUploadLimitInKB="2048"
+                    addHttpRequestToContext="false"/>
+    <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">id</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">id</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>
+</config>

Added: gora/trunk/gora-solr/src/test/conf/solr/solr.xml
URL: http://svn.apache.org/viewvc/gora/trunk/gora-solr/src/test/conf/solr/solr.xml?rev=1498171&view=auto
==============================================================================
--- gora/trunk/gora-solr/src/test/conf/solr/solr.xml (added)
+++ gora/trunk/gora-solr/src/test/conf/solr/solr.xml Sun Jun 30 19:10:53 2013
@@ -0,0 +1,36 @@
+<?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.
+-->
+
+<!--
+   This is an example of a simple "solr.xml" file for configuring one or 
+   more Solr Cores, as well as allowing Cores to be added, removed, and 
+   reloaded via HTTP requests.
+
+   More information about options available in this configuration file, 
+   and Solr Core administration can be found online:
+   http://wiki.apache.org/solr/CoreAdmin
+-->
+
+<solr persistent="false">
+
+  <cores adminPath="/admin/cores" host="${host:}" hostPort="${jetty.port:8983}" hostContext="${hostContext:solr}">
+    <core name="Employee" instanceDir="Employee" />
+    <core name="WebPage" instanceDir="WebPage" />
+  </cores>
+
+</solr>

Added: gora/trunk/gora-solr/src/test/java/org/apache/gora/solr/GoraSolrTestDriver.java
URL: http://svn.apache.org/viewvc/gora/trunk/gora-solr/src/test/java/org/apache/gora/solr/GoraSolrTestDriver.java?rev=1498171&view=auto
==============================================================================
--- gora/trunk/gora-solr/src/test/java/org/apache/gora/solr/GoraSolrTestDriver.java (added)
+++ gora/trunk/gora-solr/src/test/java/org/apache/gora/solr/GoraSolrTestDriver.java Sun Jun 30 19:10:53 2013
@@ -0,0 +1,55 @@
+/**
+ * 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.gora.solr;
+
+import java.util.Properties;
+
+import org.apache.gora.GoraTestDriver;
+import org.apache.gora.solr.store.SolrStore;
+import org.apache.solr.client.solrj.embedded.JettySolrRunner;
+
+public class GoraSolrTestDriver extends GoraTestDriver {
+  JettySolrRunner solr;
+
+  public GoraSolrTestDriver() {
+    super(SolrStore.class);
+  }
+
+  @Override
+  public void setUpClass() throws Exception {
+    super.setUpClass();
+    solr = new JettySolrRunner("solr","/solr", 9876);
+    solr.start();
+  }
+
+  @Override
+  public void tearDownClass() throws Exception {
+    super.tearDownClass();
+    if (solr != null) {
+      solr.stop();
+      solr = null;
+    }
+  }
+
+  @Override
+  protected void setProperties(Properties properties) {
+    // TODO Auto-generated method stub
+    super.setProperties(properties);
+  }
+
+}

Added: gora/trunk/gora-solr/src/test/java/org/apache/gora/solr/store/TestSolrStore.java
URL: http://svn.apache.org/viewvc/gora/trunk/gora-solr/src/test/java/org/apache/gora/solr/store/TestSolrStore.java?rev=1498171&view=auto
==============================================================================
--- gora/trunk/gora-solr/src/test/java/org/apache/gora/solr/store/TestSolrStore.java (added)
+++ gora/trunk/gora-solr/src/test/java/org/apache/gora/solr/store/TestSolrStore.java Sun Jun 30 19:10:53 2013
@@ -0,0 +1,94 @@
+/**
+ * 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.gora.solr.store;
+
+import java.io.IOException;
+
+import org.apache.gora.examples.generated.Employee;
+import org.apache.gora.examples.generated.WebPage;
+import org.apache.gora.solr.GoraSolrTestDriver;
+import org.apache.gora.store.DataStore;
+import org.apache.gora.store.DataStoreFactory;
+import org.apache.gora.store.DataStoreTestBase;
+
+public class TestSolrStore extends DataStoreTestBase {
+  
+  static {
+    setTestDriver(new GoraSolrTestDriver());
+  }
+
+  @Override
+  protected DataStore<String, Employee> createEmployeeDataStore()
+      throws IOException {
+    SolrStore<String, Employee> store = new SolrStore<String, Employee>();
+    store.initialize(String.class, Employee.class, DataStoreFactory.createProps());
+    return store;
+  }
+
+  @Override
+  protected DataStore<String, WebPage> createWebPageDataStore()
+      throws IOException {
+    SolrStore<String, WebPage> store = new SolrStore<String, WebPage>();
+    store.initialize(String.class, WebPage.class, DataStoreFactory.createProps());
+    return store;
+  }
+
+
+  public void testGetRecursive() {
+  }
+
+  public void testGetDoubleRecursive() {
+  }
+
+  public void testGetNested() {
+  }
+
+  public void testGet3UnionField() {
+  }
+
+  public void testQuery() {
+  }
+
+  public void testQueryStartKey() {
+  }
+
+  public void testQueryEndKey() {
+  }
+
+  public void testQueryKeyRange() {
+  }
+
+  public void testQueryWebPageSingleKey() {
+  }
+
+  public void testQueryWebPageSingleKeyDefaultFields() {
+  }
+
+  public void testDeleteByQuery() {
+  }
+
+  public void testGetPartitions() {
+  }
+
+  public void testUpdate() {
+  }
+
+  public void testDeleteByQueryFields() {
+  }
+
+}

Modified: gora/trunk/pom.xml
URL: http://svn.apache.org/viewvc/gora/trunk/pom.xml?rev=1498171&r1=1498170&r2=1498171&view=diff
==============================================================================
--- gora/trunk/pom.xml (original)
+++ gora/trunk/pom.xml Sun Jun 30 19:10:53 2013
@@ -611,7 +611,7 @@
         <restlet.version>2.1.1</restlet.version>
 
         <!-- Misc Dependencies -->
-        <guava.version>10.0.1</guava.version>
+        <guava.version>14.0.1</guava.version>
         <commons-lang.version>2.6</commons-lang.version>
         <jdom.version>1.1.2</jdom.version>
         <hsqldb.version>2.2.8</hsqldb.version>
@@ -868,11 +868,6 @@
               <version>49.1</version>
             </dependency>
             <dependency>
-              <groupId>com.google.guava</groupId>
-              <artifactId>guava</artifactId>
-              <version>14.0.1</version>
-            </dependency>
-            <dependency>
               <groupId>commons-codec</groupId>
               <artifactId>commons-codec</artifactId>
               <version>1.7</version>