You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@geode.apache.org by as...@apache.org on 2015/11/11 22:23:56 UTC

[24/50] [abbrv] incubator-geode git commit: Adding xml parsing and generation logic

Adding xml parsing and generation logic

We now have an xsd for the lucene elements, and a LuceneXmlParser
service. Geode already has a mechanism to plug in additional xml parsers
like LuceneXmlParsers by using the java service loader, which I have
done.

I've written a LuceneIndexCreation object to match other configuration
objects that get generated when a cache is parsed. This creation is
attached to regions on index creation time so that when xml is
generated, the creation object and generate the appropriate xml snippet.


Project: http://git-wip-us.apache.org/repos/asf/incubator-geode/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-geode/commit/5011ee51
Tree: http://git-wip-us.apache.org/repos/asf/incubator-geode/tree/5011ee51
Diff: http://git-wip-us.apache.org/repos/asf/incubator-geode/diff/5011ee51

Branch: refs/heads/develop
Commit: 5011ee516d86c7dd116aa8707f561898e3a63541
Parents: d88ef88
Author: Dan Smith <up...@apache.org>
Authored: Wed Oct 7 13:44:10 2015 -0700
Committer: Dan Smith <up...@apache.org>
Committed: Thu Oct 8 10:26:08 2015 -0700

----------------------------------------------------------------------
 .../LuceneIndexForPartitionedRegion.java        | 21 +-----
 .../cache/lucene/internal/LuceneIndexImpl.java  | 16 +++-
 .../lucene/internal/LuceneServiceImpl.java      |  8 +-
 .../internal/xml/LuceneIndexCreation.java       | 76 +++++++++++++++++++
 .../internal/xml/LuceneIndexXmlGenerator.java   | 41 ++++++++++
 .../internal/xml/LuceneServiceXmlGenerator.java | 20 +++++
 .../lucene/internal/xml/LuceneXmlConstants.java | 12 +++
 .../lucene/internal/xml/LuceneXmlParser.java    | 54 ++++++++++++++
 .../lucene/lucene-1.0.xsd                       | 36 +++++++++
 ...ne.gemfire.internal.cache.xmlcache.XmlParser |  1 +
 ...neIndexXmlGeneratorIntegrationJUnitTest.java | 59 +++++++++++++++
 .../xml/LuceneIndexXmlGeneratorJUnitTest.java   | 44 +++++++++++
 ...uceneIndexXmlParserIntegrationJUnitTest.java | 78 ++++++++++++++++++++
 .../xml/LuceneIndexXmlParserJUnitTest.java      | 41 ++++++++++
 ...erIntegrationJUnitTest.createIndex.cache.xml | 16 ++++
 ...serIntegrationJUnitTest.parseIndex.cache.xml | 16 ++++
 16 files changed, 514 insertions(+), 25 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/5011ee51/gemfire-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/LuceneIndexForPartitionedRegion.java
----------------------------------------------------------------------
diff --git a/gemfire-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/LuceneIndexForPartitionedRegion.java b/gemfire-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/LuceneIndexForPartitionedRegion.java
index f9e2c1d..2bf848f 100644
--- a/gemfire-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/LuceneIndexForPartitionedRegion.java
+++ b/gemfire-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/LuceneIndexForPartitionedRegion.java
@@ -1,37 +1,17 @@
 package com.gemstone.gemfire.cache.lucene.internal;
 
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Set;
-
-import org.apache.lucene.analysis.Analyzer;
-
 import com.gemstone.gemfire.cache.Cache;
-import com.gemstone.gemfire.cache.CacheFactory;
 import com.gemstone.gemfire.cache.DataPolicy;
 import com.gemstone.gemfire.cache.PartitionAttributesFactory;
-import com.gemstone.gemfire.cache.Region;
 import com.gemstone.gemfire.cache.RegionAttributes;
-import com.gemstone.gemfire.cache.RegionFactory;
 import com.gemstone.gemfire.cache.RegionShortcut;
 import com.gemstone.gemfire.cache.asyncqueue.AsyncEventQueue;
-import com.gemstone.gemfire.cache.asyncqueue.AsyncEventQueueFactory;
 import com.gemstone.gemfire.cache.asyncqueue.internal.AsyncEventQueueFactoryImpl;
 import com.gemstone.gemfire.cache.asyncqueue.internal.AsyncEventQueueImpl;
-import com.gemstone.gemfire.cache.execute.RegionFunctionContext;
-import com.gemstone.gemfire.cache.lucene.LuceneIndex;
 import com.gemstone.gemfire.cache.lucene.internal.filesystem.ChunkKey;
 import com.gemstone.gemfire.cache.lucene.internal.filesystem.File;
-import com.gemstone.gemfire.cache.lucene.internal.repository.IndexRepository;
 import com.gemstone.gemfire.cache.lucene.internal.repository.serializer.HeterogenousLuceneSerializer;
-import com.gemstone.gemfire.cache.lucene.internal.repository.serializer.LuceneSerializer;
-import com.gemstone.gemfire.cache.partition.PartitionRegionHelper;
-import com.gemstone.gemfire.internal.cache.InternalRegionArguments;
 import com.gemstone.gemfire.internal.cache.PartitionedRegion;
-import com.gemstone.gemfire.internal.cache.RegionFactoryImpl;
-import com.gemstone.gemfire.internal.i18n.LocalizedStrings;
 
 /* wrapper of IndexWriter */
 public class LuceneIndexForPartitionedRegion extends LuceneIndexImpl {
@@ -125,6 +105,7 @@ public class LuceneIndexForPartitionedRegion extends LuceneIndexImpl {
         logger.info("The AEQ "+aeq+" is created at another member");
       }
 
+      addExtension(dataRegion);
       hasInitialized = true;
     }
   }

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/5011ee51/gemfire-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/LuceneIndexImpl.java
----------------------------------------------------------------------
diff --git a/gemfire-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/LuceneIndexImpl.java b/gemfire-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/LuceneIndexImpl.java
index c2d2ce2..3964053 100644
--- a/gemfire-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/LuceneIndexImpl.java
+++ b/gemfire-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/LuceneIndexImpl.java
@@ -11,6 +11,8 @@ import com.gemstone.gemfire.cache.Region;
 import com.gemstone.gemfire.cache.lucene.internal.filesystem.ChunkKey;
 import com.gemstone.gemfire.cache.lucene.internal.filesystem.File;
 import com.gemstone.gemfire.cache.lucene.internal.repository.RepositoryManager;
+import com.gemstone.gemfire.cache.lucene.internal.xml.LuceneIndexCreation;
+import com.gemstone.gemfire.internal.cache.PartitionedRegion;
 import com.gemstone.gemfire.internal.logging.LogService;
 
 public abstract class LuceneIndexImpl implements InternalLuceneIndex {
@@ -74,6 +76,18 @@ public abstract class LuceneIndexImpl implements InternalLuceneIndex {
     return this.analyzer;
   }
 
-  protected void initialize() {
+  protected abstract void initialize();
+  
+  /**
+   * Register an extension with the region
+   * so that xml will be generated for this index.
+   */
+  protected void addExtension(PartitionedRegion dataRegion) {
+    LuceneIndexCreation creation = new LuceneIndexCreation();
+    creation.setName(this.getName());
+    creation.setFieldNames(this.getFieldNames());
+    creation.setRegion(dataRegion);
+    creation.setFieldFieldAnalyzerMap(this.getFieldAnalyzerMap());
+    dataRegion.getExtensionPoint().addExtension(creation, creation);
   }
 }

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/5011ee51/gemfire-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/LuceneServiceImpl.java
----------------------------------------------------------------------
diff --git a/gemfire-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/LuceneServiceImpl.java b/gemfire-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/LuceneServiceImpl.java
index 2c4db9d..776d005 100644
--- a/gemfire-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/LuceneServiceImpl.java
+++ b/gemfire-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/LuceneServiceImpl.java
@@ -22,6 +22,7 @@ import com.gemstone.gemfire.cache.lucene.internal.distributed.TopEntriesCollecto
 import com.gemstone.gemfire.cache.lucene.internal.distributed.TopEntriesCollectorManager;
 import com.gemstone.gemfire.cache.lucene.internal.filesystem.ChunkKey;
 import com.gemstone.gemfire.cache.lucene.internal.filesystem.File;
+import com.gemstone.gemfire.cache.lucene.internal.xml.LuceneServiceXmlGenerator;
 import com.gemstone.gemfire.internal.DSFIDFactory;
 import com.gemstone.gemfire.internal.DataSerializableFixedID;
 import com.gemstone.gemfire.internal.cache.GemFireCacheImpl;
@@ -147,14 +148,13 @@ public class LuceneServiceImpl implements InternalLuceneService {
 
   @Override
   public XmlGenerator<Cache> getXmlGenerator() {
-    // TODO Auto-generated method stub
-    return null;
+    return new LuceneServiceXmlGenerator();
   }
 
   @Override
   public void onCreate(Extensible<Cache> source, Extensible<Cache> target) {
-    // TODO Auto-generated method stub
-
+    //This is called when CacheCreation (source) is turned into a GemfireCacheImpl (target)
+    //nothing to do there.
   }
   
   public void registerIndex(LuceneIndex index){

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/5011ee51/gemfire-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/xml/LuceneIndexCreation.java
----------------------------------------------------------------------
diff --git a/gemfire-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/xml/LuceneIndexCreation.java b/gemfire-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/xml/LuceneIndexCreation.java
new file mode 100644
index 0000000..abb147a
--- /dev/null
+++ b/gemfire-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/xml/LuceneIndexCreation.java
@@ -0,0 +1,76 @@
+package com.gemstone.gemfire.cache.lucene.internal.xml;
+
+import java.util.Map;
+
+import org.apache.lucene.analysis.Analyzer;
+
+import com.gemstone.gemfire.cache.Cache;
+import com.gemstone.gemfire.cache.Region;
+import com.gemstone.gemfire.cache.lucene.LuceneIndex;
+import com.gemstone.gemfire.cache.lucene.LuceneService;
+import com.gemstone.gemfire.cache.lucene.LuceneServiceProvider;
+import com.gemstone.gemfire.internal.cache.extension.Extensible;
+import com.gemstone.gemfire.internal.cache.extension.Extension;
+import com.gemstone.gemfire.internal.cache.xmlcache.XmlGenerator;
+
+public class LuceneIndexCreation implements LuceneIndex, Extension<Region<?, ?>> {
+  private Region region;
+  private String name;
+  private String[] fieldNames;
+  private Map<String, Analyzer> fieldFieldAnalyzerMap;
+
+  
+  public void setRegion(Region region) {
+    this.region = region;
+  }
+
+  public void setName(String name) {
+    this.name = name;
+  }
+
+  public void setFieldNames(String[] fieldNames) {
+    this.fieldNames = fieldNames;
+  }
+  
+  public Map<String, Analyzer> getFieldFieldAnalyzerMap() {
+    return fieldFieldAnalyzerMap;
+  }
+
+  public void setFieldFieldAnalyzerMap(
+      Map<String, Analyzer> fieldFieldAnalyzerMap) {
+    this.fieldFieldAnalyzerMap = fieldFieldAnalyzerMap;
+  }
+  
+  @Override
+  public Map<String, Analyzer> getFieldAnalyzerMap() {
+    return this.fieldFieldAnalyzerMap;
+  }
+
+  public String getName() {
+    return name;
+  }
+
+  public String[] getFieldNames() {
+    return fieldNames;
+  }
+
+  @Override
+  public String getRegionPath() {
+    return region.getFullPath();
+  }
+
+  @Override
+  public XmlGenerator<Region<?, ?>> getXmlGenerator() {
+    return new LuceneIndexXmlGenerator(this);
+  }
+
+  @Override
+  public void onCreate(Extensible<Region<?, ?>> source,
+      Extensible<Region<?, ?>> target) {
+    target.getExtensionPoint().addExtension(LuceneIndex.class, this);
+    Cache cache = target.getExtensionPoint().getTarget().getCache();
+    LuceneService service = LuceneServiceProvider.get(cache);
+    //TODO - should this be a different method than the public API here?
+    service.createIndex(getName(), getRegionPath(), getFieldNames());
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/5011ee51/gemfire-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/xml/LuceneIndexXmlGenerator.java
----------------------------------------------------------------------
diff --git a/gemfire-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/xml/LuceneIndexXmlGenerator.java b/gemfire-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/xml/LuceneIndexXmlGenerator.java
new file mode 100644
index 0000000..161e981
--- /dev/null
+++ b/gemfire-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/xml/LuceneIndexXmlGenerator.java
@@ -0,0 +1,41 @@
+package com.gemstone.gemfire.cache.lucene.internal.xml;
+
+import static com.gemstone.gemfire.cache.lucene.internal.xml.LuceneXmlConstants.*;
+
+import org.xml.sax.ContentHandler;
+import org.xml.sax.SAXException;
+import org.xml.sax.helpers.AttributesImpl;
+
+import com.gemstone.gemfire.cache.Region;
+import com.gemstone.gemfire.cache.lucene.LuceneIndex;
+import com.gemstone.gemfire.internal.cache.xmlcache.CacheXmlGenerator;
+import com.gemstone.gemfire.internal.cache.xmlcache.XmlGenerator;
+import com.gemstone.gemfire.internal.cache.xmlcache.XmlGeneratorUtils;
+
+public class LuceneIndexXmlGenerator implements XmlGenerator<Region<?, ?>> {
+  private final LuceneIndex index;
+
+  public LuceneIndexXmlGenerator(LuceneIndex index) {
+    this.index = index;
+  }
+
+  @Override
+  public String getNamspaceUri() {
+    return NAMESPACE;
+  }
+
+  @Override
+  public void generate(CacheXmlGenerator cacheXmlGenerator)
+      throws SAXException {
+    final ContentHandler handler = cacheXmlGenerator.getContentHandler();
+
+    handler.startPrefixMapping(PREFIX, NAMESPACE);
+
+    AttributesImpl attr = new AttributesImpl();
+    //TODO - should the type be xs:string ?
+    XmlGeneratorUtils.addAttribute(attr, NAME, index.getName());
+    XmlGeneratorUtils.addAttribute(attr, FIELDS, String.join(",", index.getFieldNames()));
+    XmlGeneratorUtils.emptyElement(cacheXmlGenerator.getContentHandler(), PREFIX, INDEX, attr);
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/5011ee51/gemfire-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/xml/LuceneServiceXmlGenerator.java
----------------------------------------------------------------------
diff --git a/gemfire-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/xml/LuceneServiceXmlGenerator.java b/gemfire-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/xml/LuceneServiceXmlGenerator.java
new file mode 100644
index 0000000..6c0da01
--- /dev/null
+++ b/gemfire-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/xml/LuceneServiceXmlGenerator.java
@@ -0,0 +1,20 @@
+package com.gemstone.gemfire.cache.lucene.internal.xml;
+
+import org.xml.sax.SAXException;
+
+import com.gemstone.gemfire.cache.Cache;
+import com.gemstone.gemfire.internal.cache.xmlcache.CacheXmlGenerator;
+import com.gemstone.gemfire.internal.cache.xmlcache.XmlGenerator;
+
+public final class LuceneServiceXmlGenerator implements XmlGenerator<Cache> {
+  @Override
+  public String getNamspaceUri() {
+    return LuceneXmlConstants.NAMESPACE;
+  }
+
+  @Override
+  public void generate(CacheXmlGenerator cacheXmlGenerator)
+      throws SAXException {
+    //Nothing to to the xml at the service level at the moment.
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/5011ee51/gemfire-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/xml/LuceneXmlConstants.java
----------------------------------------------------------------------
diff --git a/gemfire-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/xml/LuceneXmlConstants.java b/gemfire-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/xml/LuceneXmlConstants.java
new file mode 100644
index 0000000..97193b8
--- /dev/null
+++ b/gemfire-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/xml/LuceneXmlConstants.java
@@ -0,0 +1,12 @@
+package com.gemstone.gemfire.cache.lucene.internal.xml;
+
+public class LuceneXmlConstants {
+  public static final String NAMESPACE= "http://geode.incubator.apache.org/schema/lucene";
+  public static final String PREFIX = "lucene";
+  public static final String SERVICE = "service";
+  public static final String NAME = "name";
+  public static final String REGION = "index";
+  public static final String INDEX = "index";
+  public static final String FIELDS = "fields";
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/5011ee51/gemfire-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/xml/LuceneXmlParser.java
----------------------------------------------------------------------
diff --git a/gemfire-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/xml/LuceneXmlParser.java b/gemfire-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/xml/LuceneXmlParser.java
new file mode 100644
index 0000000..8630a44
--- /dev/null
+++ b/gemfire-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/xml/LuceneXmlParser.java
@@ -0,0 +1,54 @@
+package com.gemstone.gemfire.cache.lucene.internal.xml;
+
+import static com.gemstone.gemfire.cache.lucene.internal.xml.LuceneXmlConstants.*;
+
+import org.xml.sax.Attributes;
+import org.xml.sax.SAXException;
+
+import com.gemstone.gemfire.cache.lucene.internal.LuceneServiceImpl;
+import com.gemstone.gemfire.internal.cache.xmlcache.AbstractXmlParser;
+import com.gemstone.gemfire.internal.cache.xmlcache.RegionAttributesCreation;
+import com.gemstone.gemfire.internal.cache.xmlcache.RegionCreation;
+
+public class LuceneXmlParser extends AbstractXmlParser {
+
+  @Override
+  public String getNamspaceUri() {
+    return NAMESPACE;
+  }
+
+  @Override
+  public void startElement(String uri, String localName, String qName,
+      Attributes atts) throws SAXException {
+    
+    if(!NAMESPACE.equals(uri)) {
+      return;
+    }
+    if(INDEX.equals(localName)) {
+      startIndex(atts);
+    }
+  }
+
+  private void startIndex(Attributes atts) {
+    final RegionCreation region = (RegionCreation) stack.peek();
+    RegionAttributesCreation rac = (RegionAttributesCreation) region.getAttributes();
+    String name = atts.getValue(NAME);
+    String[] fields = atts.getValue(FIELDS).split(" *, *");
+    rac.addAsyncEventQueueId(LuceneServiceImpl.getUniqueIndexName(name, region.getFullPath()));
+    
+    
+    LuceneIndexCreation indexCreation = new LuceneIndexCreation();
+    indexCreation.setName(name);
+    indexCreation.setFieldNames(fields);
+    indexCreation.setRegion(region);
+    region.getExtensionPoint().addExtension(indexCreation, indexCreation);
+    //TODO support nested field objects by adding the creation object to the stack
+    //stack.push(indexCreation)
+  }
+
+  @Override
+  public void endElement(String uri, String localName, String qName)
+      throws SAXException {
+    //Nothing to do.
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/5011ee51/gemfire-lucene/src/main/resources/META-INF/schemas/geode.incubator.apache.org/lucene/lucene-1.0.xsd
----------------------------------------------------------------------
diff --git a/gemfire-lucene/src/main/resources/META-INF/schemas/geode.incubator.apache.org/lucene/lucene-1.0.xsd b/gemfire-lucene/src/main/resources/META-INF/schemas/geode.incubator.apache.org/lucene/lucene-1.0.xsd
new file mode 100644
index 0000000..66a4aad
--- /dev/null
+++ b/gemfire-lucene/src/main/resources/META-INF/schemas/geode.incubator.apache.org/lucene/lucene-1.0.xsd
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xsd:schema
+    targetNamespace="http://geode.incubator.apache.org/schema/lucene"
+    xmlns:gpdb="http://geode.incubator.apache.org/schema/lucene"
+    xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+    elementFormDefault="qualified"
+    attributeFormDefault="unqualified"
+    version="1.0">
+  
+  <xsd:import
+      namespace="http://schema.pivotal.io/gemfire/cache"
+      schemaLocation="http://schema.pivotal.io/gemfire/cache/cache-9.0.xsd"/>
+  
+  <xsd:annotation>
+    <xsd:documentation><![CDATA[
+XML schema for Lucene indexes in Geode.
+
+  <cache
+    xmlns="http://schema.pivotal.io/gemfire/cache"
+    xmlns:lucene="http://geode.incubator.apache.org/schema/lucene"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xsi:schemaLocation="http://schema.pivotal.io/gemfire/cache
+        http://schema.pivotal.io/gemfire/cache/cache-9.0.xsd
+        http://geode.incubator.apache.org/schema/lucene
+        http://geode.incubator.apache.org/schema/lucene/lucene-1.0.xsd"
+    version="9.0">
+    
+    ]]></xsd:documentation>
+  </xsd:annotation>
+  <xsd:element name="index">
+    <xsd:complexType>
+    	<xsd:attribute name="name" type="xsd:string"/>
+    	<xsd:attribute name="fields" type="xsd:string"/>
+    </xsd:complexType>
+  </xsd:element>
+</xsd:schema>

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/5011ee51/gemfire-lucene/src/main/resources/META-INF/services/com.gemstone.gemfire.internal.cache.xmlcache.XmlParser
----------------------------------------------------------------------
diff --git a/gemfire-lucene/src/main/resources/META-INF/services/com.gemstone.gemfire.internal.cache.xmlcache.XmlParser b/gemfire-lucene/src/main/resources/META-INF/services/com.gemstone.gemfire.internal.cache.xmlcache.XmlParser
new file mode 100644
index 0000000..fc3abc0
--- /dev/null
+++ b/gemfire-lucene/src/main/resources/META-INF/services/com.gemstone.gemfire.internal.cache.xmlcache.XmlParser
@@ -0,0 +1 @@
+com.gemstone.gemfire.cache.lucene.internal.xml.LuceneXmlParser
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/5011ee51/gemfire-lucene/src/test/java/com/gemstone/gemfire/cache/lucene/internal/xml/LuceneIndexXmlGeneratorIntegrationJUnitTest.java
----------------------------------------------------------------------
diff --git a/gemfire-lucene/src/test/java/com/gemstone/gemfire/cache/lucene/internal/xml/LuceneIndexXmlGeneratorIntegrationJUnitTest.java b/gemfire-lucene/src/test/java/com/gemstone/gemfire/cache/lucene/internal/xml/LuceneIndexXmlGeneratorIntegrationJUnitTest.java
new file mode 100644
index 0000000..65c73f7
--- /dev/null
+++ b/gemfire-lucene/src/test/java/com/gemstone/gemfire/cache/lucene/internal/xml/LuceneIndexXmlGeneratorIntegrationJUnitTest.java
@@ -0,0 +1,59 @@
+package com.gemstone.gemfire.cache.lucene.internal.xml;
+
+import static org.junit.Assert.*;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.PrintWriter;
+import java.nio.charset.Charset;
+
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+
+import com.gemstone.gemfire.cache.Cache;
+import com.gemstone.gemfire.cache.CacheFactory;
+import com.gemstone.gemfire.cache.RegionShortcut;
+import com.gemstone.gemfire.cache.lucene.LuceneIndex;
+import com.gemstone.gemfire.cache.lucene.LuceneService;
+import com.gemstone.gemfire.cache.lucene.LuceneServiceProvider;
+import com.gemstone.gemfire.internal.cache.xmlcache.CacheXmlGenerator;
+import com.gemstone.gemfire.test.junit.categories.IntegrationTest;
+
+@Category(IntegrationTest.class)
+public class LuceneIndexXmlGeneratorIntegrationJUnitTest {
+  
+  /**
+   * Test of generating and reading cache configuration back in.
+   */
+  @Test
+  public void generateWithFields() {
+    Cache cache = new CacheFactory().set("mcast-port", "0").create();
+    cache.createRegionFactory(RegionShortcut.PARTITION).create("region");
+    LuceneService service = LuceneServiceProvider.get(cache);
+    
+    service.createIndex("index", "region", "a", "b", "c");
+    
+    ByteArrayOutputStream baos = new ByteArrayOutputStream();
+    PrintWriter pw = new PrintWriter(baos);
+    CacheXmlGenerator.generate(cache, pw, true, false, false);
+    pw.flush();
+    
+    cache.close();
+    cache = new CacheFactory().set("mcast-port", "0").create();
+    
+    byte[] bytes = baos.toByteArray();
+    ByteArrayInputStream in = new ByteArrayInputStream(bytes);
+    System.out.println("---FILE---");
+    System.out.println(new String(bytes, Charset.defaultCharset()));
+    cache.loadCacheXml(new ByteArrayInputStream(bytes));
+    
+    LuceneService service2 = LuceneServiceProvider.get(cache);
+    assertTrue(service != service2);
+    
+    LuceneIndex index = service2.getIndex("index", "region");
+    assertNotNull(index);
+    
+    assertArrayEquals(new String[] {"a", "b", "c"}, index.getFieldNames());
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/5011ee51/gemfire-lucene/src/test/java/com/gemstone/gemfire/cache/lucene/internal/xml/LuceneIndexXmlGeneratorJUnitTest.java
----------------------------------------------------------------------
diff --git a/gemfire-lucene/src/test/java/com/gemstone/gemfire/cache/lucene/internal/xml/LuceneIndexXmlGeneratorJUnitTest.java b/gemfire-lucene/src/test/java/com/gemstone/gemfire/cache/lucene/internal/xml/LuceneIndexXmlGeneratorJUnitTest.java
new file mode 100644
index 0000000..a31e7e1
--- /dev/null
+++ b/gemfire-lucene/src/test/java/com/gemstone/gemfire/cache/lucene/internal/xml/LuceneIndexXmlGeneratorJUnitTest.java
@@ -0,0 +1,44 @@
+package com.gemstone.gemfire.cache.lucene.internal.xml;
+
+import static org.junit.Assert.*;
+import static org.mockito.Matchers.*;
+
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mockito;
+import org.xml.sax.Attributes;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.SAXException;
+
+import com.gemstone.gemfire.cache.lucene.LuceneIndex;
+import com.gemstone.gemfire.internal.cache.xmlcache.CacheXmlGenerator;
+import com.gemstone.gemfire.test.junit.categories.UnitTest;
+
+@Category(UnitTest.class)
+public class LuceneIndexXmlGeneratorJUnitTest {
+  
+  /**
+   * Test of generating and reading cache configuration back in.
+   * @throws SAXException 
+   */
+  @Test
+  public void generateWithFields() throws SAXException {
+    LuceneIndex index = Mockito.mock(LuceneIndex.class);
+    Mockito.when(index.getName()).thenReturn("index");
+    Mockito.when(index.getFieldNames()).thenReturn(new String[] {"a", "b"});
+    
+    LuceneIndexXmlGenerator generator = new LuceneIndexXmlGenerator(index);
+    CacheXmlGenerator cacheXmlGenerator = Mockito.mock(CacheXmlGenerator.class);
+    ContentHandler handler = Mockito.mock(ContentHandler.class);
+    Mockito.when(cacheXmlGenerator.getContentHandler()).thenReturn(handler);
+    generator.generate(cacheXmlGenerator);
+    
+    ArgumentCaptor<Attributes> captor = new ArgumentCaptor<>();
+    Mockito.verify(handler).startElement(eq(""), eq("index"), eq("lucene:index"), captor.capture());
+    Attributes value = captor.getValue();
+    assertEquals("index", value.getValue(LuceneXmlConstants.NAME));
+    assertEquals("a,b", value.getValue(LuceneXmlConstants.FIELDS));
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/5011ee51/gemfire-lucene/src/test/java/com/gemstone/gemfire/cache/lucene/internal/xml/LuceneIndexXmlParserIntegrationJUnitTest.java
----------------------------------------------------------------------
diff --git a/gemfire-lucene/src/test/java/com/gemstone/gemfire/cache/lucene/internal/xml/LuceneIndexXmlParserIntegrationJUnitTest.java b/gemfire-lucene/src/test/java/com/gemstone/gemfire/cache/lucene/internal/xml/LuceneIndexXmlParserIntegrationJUnitTest.java
new file mode 100644
index 0000000..56a726f
--- /dev/null
+++ b/gemfire-lucene/src/test/java/com/gemstone/gemfire/cache/lucene/internal/xml/LuceneIndexXmlParserIntegrationJUnitTest.java
@@ -0,0 +1,78 @@
+package com.gemstone.gemfire.cache.lucene.internal.xml;
+
+import static org.junit.Assert.*;
+
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+import org.junit.rules.TestName;
+
+import com.gemstone.gemfire.cache.Cache;
+import com.gemstone.gemfire.cache.CacheFactory;
+import com.gemstone.gemfire.cache.lucene.LuceneIndex;
+import com.gemstone.gemfire.cache.lucene.LuceneService;
+import com.gemstone.gemfire.cache.lucene.LuceneServiceProvider;
+import com.gemstone.gemfire.internal.cache.extension.Extension;
+import com.gemstone.gemfire.internal.cache.xmlcache.CacheCreation;
+import com.gemstone.gemfire.internal.cache.xmlcache.CacheXmlParser;
+import com.gemstone.gemfire.internal.cache.xmlcache.RegionCreation;
+import com.gemstone.gemfire.test.junit.categories.UnitTest;
+import com.gemstone.gemfire.util.test.TestUtil;
+
+@Category(UnitTest.class)
+public class LuceneIndexXmlParserIntegrationJUnitTest {
+
+  @Rule
+  public TestName name = new TestName();
+  
+  /**
+   * Test that we parse the index fields correctly
+   */
+  @Test
+  public void parseIndex() throws FileNotFoundException {
+    CacheXmlParser parser = CacheXmlParser.parse(new FileInputStream(getXmlFileForTest()));
+    CacheCreation cache = parser.getCacheCreation();
+    RegionCreation region = (RegionCreation) cache.getRegion("region");
+    Map<String, String[]> expectedIndexes = new HashMap<String, String[]>();
+    expectedIndexes.put("index1", new String[] {"a", "b", "c", "d"});
+    expectedIndexes.put("index2", new String[] { "f", "g"});
+    for(Extension extension : region.getExtensionPoint().getExtensions()) {
+      LuceneIndexCreation index = (LuceneIndexCreation) extension;
+      assertEquals("/region", index.getRegionPath());
+      assertArrayEquals(expectedIndexes.remove(index.getName()), index.getFieldNames());
+    }
+    
+    assertEquals(Collections.emptyMap(),expectedIndexes);
+  }
+
+  /**
+   * Test that the Index creation objects get appropriately translated
+   * into a real index.
+   * @throws FileNotFoundException
+   */
+  @Test
+  public void createIndex() throws FileNotFoundException {
+    CacheFactory cf = new CacheFactory();
+    cf.set("mcast-port", "0");
+    cf.set("cache-xml-file", getXmlFileForTest());
+    Cache cache = cf.create();
+
+    LuceneService service = LuceneServiceProvider.get(cache);
+    assertEquals(2, service.getAllIndexes().size());
+    LuceneIndex index1 = service.getIndex("index1", "/region");
+    LuceneIndex index2 = service.getIndex("index2", "/region");
+    assertArrayEquals(index1.getFieldNames(), new String[] {"a", "b", "c", "d"});
+    assertArrayEquals(index2.getFieldNames(), new String[] { "f", "g"});
+  }
+
+  private String getXmlFileForTest() {
+    return TestUtil.getResourcePath(getClass(), getClass().getSimpleName() + "." + name.getMethodName() + ".cache.xml");
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/5011ee51/gemfire-lucene/src/test/java/com/gemstone/gemfire/cache/lucene/internal/xml/LuceneIndexXmlParserJUnitTest.java
----------------------------------------------------------------------
diff --git a/gemfire-lucene/src/test/java/com/gemstone/gemfire/cache/lucene/internal/xml/LuceneIndexXmlParserJUnitTest.java b/gemfire-lucene/src/test/java/com/gemstone/gemfire/cache/lucene/internal/xml/LuceneIndexXmlParserJUnitTest.java
new file mode 100644
index 0000000..808c11e
--- /dev/null
+++ b/gemfire-lucene/src/test/java/com/gemstone/gemfire/cache/lucene/internal/xml/LuceneIndexXmlParserJUnitTest.java
@@ -0,0 +1,41 @@
+package com.gemstone.gemfire.cache.lucene.internal.xml;
+
+import static org.junit.Assert.*;
+
+import java.util.Stack;
+
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+import org.xml.sax.SAXException;
+import org.xml.sax.helpers.AttributesImpl;
+
+import com.gemstone.gemfire.internal.cache.xmlcache.CacheCreation;
+import com.gemstone.gemfire.internal.cache.xmlcache.RegionCreation;
+import com.gemstone.gemfire.internal.cache.xmlcache.XmlGeneratorUtils;
+import com.gemstone.gemfire.test.junit.categories.UnitTest;
+
+@Category(UnitTest.class)
+public class LuceneIndexXmlParserJUnitTest {
+  
+  @Test
+  public void generateWithFields() throws SAXException {
+    LuceneXmlParser parser = new LuceneXmlParser();
+    AttributesImpl attrs = new AttributesImpl();
+    CacheCreation cache = new CacheCreation();
+    RegionCreation rc = new RegionCreation(cache, "region");
+    Stack<Object> stack = new Stack<Object>();
+    stack.push(cache);
+    stack.push(rc);
+    parser.setStack(stack);
+    XmlGeneratorUtils.addAttribute(attrs, LuceneXmlConstants.NAME, "index");
+    XmlGeneratorUtils.addAttribute(attrs, LuceneXmlConstants.FIELDS, "a,b,c");
+    parser.startElement(LuceneXmlConstants.NAMESPACE, LuceneXmlConstants.INDEX, null, attrs);
+    parser.endElement(LuceneXmlConstants.NAMESPACE, LuceneXmlConstants.INDEX, null);
+    
+    LuceneIndexCreation index = (LuceneIndexCreation) rc.getExtensionPoint().getExtensions().iterator().next();
+    assertEquals("index", index.getName());
+    assertArrayEquals(new String[] {"a", "b", "c"}, index.getFieldNames());
+  }
+  
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/5011ee51/gemfire-lucene/src/test/resources/com/gemstone/gemfire/cache/lucene/internal/xml/LuceneIndexXmlParserIntegrationJUnitTest.createIndex.cache.xml
----------------------------------------------------------------------
diff --git a/gemfire-lucene/src/test/resources/com/gemstone/gemfire/cache/lucene/internal/xml/LuceneIndexXmlParserIntegrationJUnitTest.createIndex.cache.xml b/gemfire-lucene/src/test/resources/com/gemstone/gemfire/cache/lucene/internal/xml/LuceneIndexXmlParserIntegrationJUnitTest.createIndex.cache.xml
new file mode 100644
index 0000000..8350650
--- /dev/null
+++ b/gemfire-lucene/src/test/resources/com/gemstone/gemfire/cache/lucene/internal/xml/LuceneIndexXmlParserIntegrationJUnitTest.createIndex.cache.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<cache
+    xmlns="http://schema.pivotal.io/gemfire/cache"
+    xmlns:lucene="http://geode.incubator.apache.org/schema/lucene"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xsi:schemaLocation="http://schema.pivotal.io/gemfire/cache
+        http://schema.pivotal.io/gemfire/cache/cache-9.0.xsd
+        http://geode.incubator.apache.org/schema/lucene
+        http://geode.incubator.apache.org/schema/lucene/lucene-1.0.xsd"
+    version="9.0">
+
+	<region name="region" refid="PARTITION">
+    	<lucene:index name="index1" fields="a, b,c,d"/>
+    	<lucene:index name="index2" fields="f,g"/>
+    </region>    
+</cache>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/5011ee51/gemfire-lucene/src/test/resources/com/gemstone/gemfire/cache/lucene/internal/xml/LuceneIndexXmlParserIntegrationJUnitTest.parseIndex.cache.xml
----------------------------------------------------------------------
diff --git a/gemfire-lucene/src/test/resources/com/gemstone/gemfire/cache/lucene/internal/xml/LuceneIndexXmlParserIntegrationJUnitTest.parseIndex.cache.xml b/gemfire-lucene/src/test/resources/com/gemstone/gemfire/cache/lucene/internal/xml/LuceneIndexXmlParserIntegrationJUnitTest.parseIndex.cache.xml
new file mode 100644
index 0000000..8350650
--- /dev/null
+++ b/gemfire-lucene/src/test/resources/com/gemstone/gemfire/cache/lucene/internal/xml/LuceneIndexXmlParserIntegrationJUnitTest.parseIndex.cache.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<cache
+    xmlns="http://schema.pivotal.io/gemfire/cache"
+    xmlns:lucene="http://geode.incubator.apache.org/schema/lucene"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xsi:schemaLocation="http://schema.pivotal.io/gemfire/cache
+        http://schema.pivotal.io/gemfire/cache/cache-9.0.xsd
+        http://geode.incubator.apache.org/schema/lucene
+        http://geode.incubator.apache.org/schema/lucene/lucene-1.0.xsd"
+    version="9.0">
+
+	<region name="region" refid="PARTITION">
+    	<lucene:index name="index1" fields="a, b,c,d"/>
+    	<lucene:index name="index2" fields="f,g"/>
+    </region>    
+</cache>
\ No newline at end of file