You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@geode.apache.org by ag...@apache.org on 2016/05/03 23:46:07 UTC

[53/60] [abbrv] incubator-geode git commit: GEODE-11-Added-xml-support-for-analyzer-per-field

GEODE-11-Added-xml-support-for-analyzer-per-field


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

Branch: refs/heads/feature/GEODE-1209
Commit: 2a786ee7aa3de5da4ffeeb841f6bbbcce55186f2
Parents: 8e74498
Author: Barry Oglesby <bo...@pivotal.io>
Authored: Fri Apr 29 15:58:49 2016 -0700
Committer: Barry Oglesby <bo...@pivotal.io>
Committed: Mon May 2 14:03:07 2016 -0700

----------------------------------------------------------------------
 .../gemfire/internal/i18n/LocalizedStrings.java |  2 +
 .../gemfire/cache/lucene/LuceneIndex.java       |  2 +-
 .../LuceneIndexForReplicatedRegion.java         |  2 +-
 .../cache/lucene/internal/LuceneIndexImpl.java  | 14 ++-
 .../lucene/internal/LuceneServiceImpl.java      | 21 +++--
 .../internal/xml/LuceneIndexCreation.java       | 42 +++++----
 .../internal/xml/LuceneIndexXmlGenerator.java   |  5 +
 .../lucene/internal/xml/LuceneXmlConstants.java |  1 +
 .../lucene/internal/xml/LuceneXmlParser.java    | 27 +++++-
 .../geode.apache.org/lucene/lucene-1.0.xsd      |  1 +
 ...uceneIndexXmlParserIntegrationJUnitTest.java | 52 +++++++++--
 .../xml/LuceneIndexXmlParserJUnitTest.java      | 97 ++++++++++++++------
 ...erIntegrationJUnitTest.createIndex.cache.xml |  7 +-
 ...nJUnitTest.parseIndexWithAnalyzers.cache.xml | 36 ++++++++
 14 files changed, 241 insertions(+), 68 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/2a786ee7/geode-core/src/main/java/com/gemstone/gemfire/internal/i18n/LocalizedStrings.java
----------------------------------------------------------------------
diff --git a/geode-core/src/main/java/com/gemstone/gemfire/internal/i18n/LocalizedStrings.java b/geode-core/src/main/java/com/gemstone/gemfire/internal/i18n/LocalizedStrings.java
index ff960ca..a6bbb86 100644
--- a/geode-core/src/main/java/com/gemstone/gemfire/internal/i18n/LocalizedStrings.java
+++ b/geode-core/src/main/java/com/gemstone/gemfire/internal/i18n/LocalizedStrings.java
@@ -2127,6 +2127,8 @@ public class LocalizedStrings extends ParentLocalizedStrings {
   public static final StringId SwaggerConfig_DOC_TITLE = new StringId(6621, "Apache Geode Documentation");
   public static final StringId SwaggerConfig_DOC_LINK = new StringId(6622, "http://geode.incubator.apache.org/docs/");
 
+  public static final StringId LuceneXmlParser_CLASS_0_IS_NOT_AN_INSTANCE_OF_ANALYZER = new StringId(6623, "Class \"{0}\" is not an instance of Analyzer.");
+
   /** Testing strings, messageId 90000-99999 **/
   
   /** These are simple messages for testing, translated with Babelfish. **/

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/2a786ee7/geode-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/LuceneIndex.java
----------------------------------------------------------------------
diff --git a/geode-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/LuceneIndex.java b/geode-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/LuceneIndex.java
index 7475fde..743045b 100644
--- a/geode-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/LuceneIndex.java
+++ b/geode-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/LuceneIndex.java
@@ -54,6 +54,6 @@ public interface LuceneIndex {
   /**
    * @return the field to analyzer map
    */
-  public Map<String, Analyzer> getFieldAnalyzerMap();
+  public Map<String, Analyzer> getFieldAnalyzers();
   
 }

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/2a786ee7/geode-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/LuceneIndexForReplicatedRegion.java
----------------------------------------------------------------------
diff --git a/geode-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/LuceneIndexForReplicatedRegion.java b/geode-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/LuceneIndexForReplicatedRegion.java
index 7c585cf..cd07672 100644
--- a/geode-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/LuceneIndexForReplicatedRegion.java
+++ b/geode-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/LuceneIndexForReplicatedRegion.java
@@ -41,7 +41,7 @@ public class LuceneIndexForReplicatedRegion extends LuceneIndexImpl {
   }
 
   @Override
-  public Map<String, Analyzer> getFieldAnalyzerMap() {
+  public Map<String, Analyzer> getFieldAnalyzers() {
     throw new UnsupportedOperationException("Lucene indexes on replicated regions is not yet implemented");
   }
 

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/2a786ee7/geode-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/LuceneIndexImpl.java
----------------------------------------------------------------------
diff --git a/geode-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/LuceneIndexImpl.java b/geode-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/LuceneIndexImpl.java
index f869755..f530f8c 100644
--- a/geode-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/LuceneIndexImpl.java
+++ b/geode-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/LuceneIndexImpl.java
@@ -19,6 +19,7 @@
 
 package com.gemstone.gemfire.cache.lucene.internal;
 
+import java.util.Collections;
 import java.util.Map;
 
 import org.apache.logging.log4j.Logger;
@@ -47,6 +48,7 @@ public abstract class LuceneIndexImpl implements InternalLuceneIndex {
   protected String indexName;
   protected String regionPath;
   protected boolean hasInitialized = false;
+  protected Map<String, Analyzer> fieldAnalyzers;
 
   @Override
   public String getName() {
@@ -68,10 +70,8 @@ public abstract class LuceneIndexImpl implements InternalLuceneIndex {
   }
 
   @Override
-  public Map<String, Analyzer> getFieldAnalyzerMap() {
-    // TODO Auto-generated method stub
-    // Will do that later: Gester
-    return null;
+  public Map<String, Analyzer> getFieldAnalyzers() {
+    return this.fieldAnalyzers;
   }
 
   public RepositoryManager getRepositoryManager() {
@@ -90,6 +90,10 @@ public abstract class LuceneIndexImpl implements InternalLuceneIndex {
     return this.analyzer;
   }
 
+  public void setFieldAnalyzers(Map<String, Analyzer> fieldAnalyzers) {
+    this.fieldAnalyzers = Collections.unmodifiableMap(fieldAnalyzers);
+  }
+
   protected abstract void initialize();
   
   /**
@@ -101,7 +105,7 @@ public abstract class LuceneIndexImpl implements InternalLuceneIndex {
     creation.setName(this.getName());
     creation.addFieldNames(this.getFieldNames());
     creation.setRegion(dataRegion);
-    creation.setFieldFieldAnalyzerMap(this.getFieldAnalyzerMap());
+    creation.setFieldAnalyzers(this.getFieldAnalyzers());
     dataRegion.getExtensionPoint().addExtension(creation);
   }
 }

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/2a786ee7/geode-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/LuceneServiceImpl.java
----------------------------------------------------------------------
diff --git a/geode-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/LuceneServiceImpl.java b/geode-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/LuceneServiceImpl.java
index 9d6aed4..58a9b20 100644
--- a/geode-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/LuceneServiceImpl.java
+++ b/geode-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/LuceneServiceImpl.java
@@ -22,6 +22,7 @@ package com.gemstone.gemfire.cache.lucene.internal;
 import java.util.Collection;
 import java.util.HashMap;
 import java.util.Map;
+import java.util.Set;
 
 import org.apache.logging.log4j.Logger;
 import org.apache.lucene.analysis.Analyzer;
@@ -102,19 +103,21 @@ public class LuceneServiceImpl implements InternalLuceneService {
   public void createIndex(String indexName, String regionPath, String... fields) {
     StandardAnalyzer analyzer = new StandardAnalyzer();
     
-    createIndex(indexName, regionPath, analyzer, fields);
+    createIndex(indexName, regionPath, analyzer, null, fields);
   }
   
   @Override
-  public void createIndex(String indexName, String regionPath, Map<String, Analyzer> analyzerPerField) {
-    Analyzer analyzer = new PerFieldAnalyzerWrapper(new StandardAnalyzer(), analyzerPerField);
-    String[] fields = (String[])analyzerPerField.keySet().toArray(new String[analyzerPerField.keySet().size()]);
+  public void createIndex(String indexName, String regionPath, Map<String, Analyzer> fieldAnalyzers) {
+    Analyzer analyzer = new PerFieldAnalyzerWrapper(new StandardAnalyzer(), fieldAnalyzers);
+    Set<String> fieldsSet = fieldAnalyzers.keySet();
+    String[] fields = (String[])fieldsSet.toArray(new String[fieldsSet.size()]);
 
-    createIndex(indexName, regionPath, analyzer, fields);
+    createIndex(indexName, regionPath, analyzer, fieldAnalyzers, fields);
   }
 
   private void createIndex(final String indexName, String regionPath,
-      final Analyzer analyzer, final String... fields) {
+      final Analyzer analyzer, final Map<String, Analyzer> fieldAnalyzers,
+      final String... fields) {
 
     if(!regionPath.startsWith("/")) {
       regionPath = "/" + regionPath;
@@ -143,7 +146,7 @@ public class LuceneServiceImpl implements InternalLuceneService {
       @Override
       public void afterCreate(Region region) {
         if(region.getFullPath().equals(dataRegionPath)) {
-          afterDataRegionCreated(indexName, analyzer, dataRegionPath, fields);
+          afterDataRegionCreated(indexName, analyzer, dataRegionPath, fieldAnalyzers, fields);
           cache.removeRegionListener(this);
         }
       }
@@ -158,11 +161,11 @@ public class LuceneServiceImpl implements InternalLuceneService {
    */
   public void afterDataRegionCreated(final String indexName,
       final Analyzer analyzer, final String dataRegionPath,
-      final String... fields) {
+      final Map<String, Analyzer> fieldAnalyzers, final String... fields) {
     LuceneIndexImpl index = createIndexRegions(indexName, dataRegionPath);
     index.setSearchableFields(fields);
-    // for this API, set index to use the default StandardAnalyzer for each field
     index.setAnalyzer(analyzer);
+    index.setFieldAnalyzers(fieldAnalyzers);
     index.initialize();
     registerIndex(index);
   }

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/2a786ee7/geode-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/xml/LuceneIndexCreation.java
----------------------------------------------------------------------
diff --git a/geode-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/xml/LuceneIndexCreation.java b/geode-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/xml/LuceneIndexCreation.java
index e664895..86a10e4 100644
--- a/geode-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/xml/LuceneIndexCreation.java
+++ b/geode-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/xml/LuceneIndexCreation.java
@@ -19,12 +19,10 @@
 
 package com.gemstone.gemfire.cache.lucene.internal.xml;
 
-import java.util.Arrays;
-import java.util.LinkedHashSet;
-import java.util.Map;
-import java.util.Set;
+import java.util.*;
 
 import org.apache.lucene.analysis.Analyzer;
+import org.apache.lucene.analysis.miscellaneous.PerFieldAnalyzerWrapper;
 import org.apache.lucene.analysis.standard.StandardAnalyzer;
 
 import com.gemstone.gemfire.cache.Cache;
@@ -41,7 +39,7 @@ public class LuceneIndexCreation implements LuceneIndex, Extension<Region<?, ?>>
   private Region region;
   private String name;
   private Set<String> fieldNames = new LinkedHashSet<String>();
-  private Map<String, Analyzer> fieldFieldAnalyzerMap;
+  private Map<String, Analyzer> fieldAnalyzers;
 
   
   public void setRegion(Region region) {
@@ -52,18 +50,17 @@ public class LuceneIndexCreation implements LuceneIndex, Extension<Region<?, ?>>
     this.name = name;
   }
 
-  public Map<String, Analyzer> getFieldFieldAnalyzerMap() {
-    return fieldFieldAnalyzerMap;
-  }
-
-  public void setFieldFieldAnalyzerMap(
-      Map<String, Analyzer> fieldFieldAnalyzerMap) {
-    this.fieldFieldAnalyzerMap = fieldFieldAnalyzerMap;
+  public void setFieldAnalyzers(
+      Map<String, Analyzer> fieldAnalyzers) {
+    this.fieldAnalyzers = fieldAnalyzers;
   }
   
   @Override
-  public Map<String, Analyzer> getFieldAnalyzerMap() {
-    return this.fieldFieldAnalyzerMap;
+  public Map<String, Analyzer> getFieldAnalyzers() {
+    if (this.fieldAnalyzers == null) {
+      this.fieldAnalyzers = new HashMap<>();
+    }
+    return this.fieldAnalyzers;
   }
 
   public String getName() {
@@ -87,7 +84,6 @@ public class LuceneIndexCreation implements LuceneIndex, Extension<Region<?, ?>>
   @Override
   public void onCreate(Extensible<Region<?, ?>> source,
       Extensible<Region<?, ?>> target) {
-    target.getExtensionPoint().addExtension(this);
     Cache cache = target.getExtensionPoint().getTarget().getCache();
     LuceneServiceImpl service = (LuceneServiceImpl) LuceneServiceProvider.get(cache);
     Region region = target.getExtensionPoint().getTarget();
@@ -97,15 +93,25 @@ public class LuceneIndexCreation implements LuceneIndex, Extension<Region<?, ?>>
     //TODO - this may only work for PRs. We need to intercept the attributes
     //before the region is created with a RegionListener.
     region.getAttributesMutator().addAsyncEventQueueId(aeqId);
-    service.afterDataRegionCreated(getName(), new StandardAnalyzer(), getRegionPath(), getFieldNames());
+    Analyzer analyzer = null;
+    if (this.fieldAnalyzers == null) {
+      analyzer = new StandardAnalyzer();
+    } else {
+      analyzer = new PerFieldAnalyzerWrapper(new StandardAnalyzer(), this.fieldAnalyzers);
+    }
+    service.afterDataRegionCreated(getName(), analyzer, getRegionPath(), this.fieldAnalyzers, getFieldNames());
+  }
+
+  protected void addField(String name) {
+    this.fieldNames.add(name);
   }
 
-  public void addField(String name) {
+  protected void addFieldAndAnalyzer(String name, Analyzer analyzer) {
     this.fieldNames.add(name);
+    getFieldAnalyzers().put(name, analyzer);
   }
 
   public void addFieldNames(String[] fieldNames) {
     this.fieldNames.addAll(Arrays.asList(fieldNames));
-    
   }
 }

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/2a786ee7/geode-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/xml/LuceneIndexXmlGenerator.java
----------------------------------------------------------------------
diff --git a/geode-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/xml/LuceneIndexXmlGenerator.java b/geode-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/xml/LuceneIndexXmlGenerator.java
index 6399a80..37c9ca2 100644
--- a/geode-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/xml/LuceneIndexXmlGenerator.java
+++ b/geode-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/xml/LuceneIndexXmlGenerator.java
@@ -21,6 +21,7 @@ package com.gemstone.gemfire.cache.lucene.internal.xml;
 
 import static com.gemstone.gemfire.cache.lucene.internal.xml.LuceneXmlConstants.*;
 
+import org.apache.lucene.analysis.Analyzer;
 import org.xml.sax.ContentHandler;
 import org.xml.sax.SAXException;
 import org.xml.sax.helpers.AttributesImpl;
@@ -57,6 +58,10 @@ public class LuceneIndexXmlGenerator implements XmlGenerator<Region<?, ?>> {
     for(String field : index.getFieldNames()) {
       AttributesImpl fieldAttr = new AttributesImpl();
       XmlGeneratorUtils.addAttribute(fieldAttr, NAME, field);
+      Analyzer analyzer = index.getFieldAnalyzers().get(field);
+      if (analyzer != null) {
+        XmlGeneratorUtils.addAttribute(fieldAttr, ANALYZER, analyzer.getClass().getName());
+      }
       XmlGeneratorUtils.emptyElement(handler, PREFIX, FIELD, fieldAttr);
     }
     XmlGeneratorUtils.endElement(handler, PREFIX, INDEX);

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/2a786ee7/geode-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/xml/LuceneXmlConstants.java
----------------------------------------------------------------------
diff --git a/geode-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/xml/LuceneXmlConstants.java b/geode-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/xml/LuceneXmlConstants.java
index bc80180..91d1643 100644
--- a/geode-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/xml/LuceneXmlConstants.java
+++ b/geode-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/xml/LuceneXmlConstants.java
@@ -27,5 +27,6 @@ public class LuceneXmlConstants {
   public static final String REGION = "index";
   public static final String INDEX = "index";
   public static final String FIELD = "field";
+  public static final String ANALYZER = "analyzer";
 
 }

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/2a786ee7/geode-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/xml/LuceneXmlParser.java
----------------------------------------------------------------------
diff --git a/geode-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/xml/LuceneXmlParser.java b/geode-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/xml/LuceneXmlParser.java
index 764f461..40bf0ac 100644
--- a/geode-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/xml/LuceneXmlParser.java
+++ b/geode-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/xml/LuceneXmlParser.java
@@ -21,6 +21,10 @@ package com.gemstone.gemfire.cache.lucene.internal.xml;
 
 import static com.gemstone.gemfire.cache.lucene.internal.xml.LuceneXmlConstants.*;
 
+import com.gemstone.gemfire.cache.CacheXmlException;
+import com.gemstone.gemfire.internal.InternalDataSerializer;
+import com.gemstone.gemfire.internal.i18n.LocalizedStrings;
+import org.apache.lucene.analysis.Analyzer;
 import org.xml.sax.Attributes;
 import org.xml.sax.SAXException;
 
@@ -58,7 +62,13 @@ public class LuceneXmlParser extends AbstractXmlParser {
     }
     LuceneIndexCreation creation = (LuceneIndexCreation) stack.peek();
     String name = atts.getValue(NAME);
-    creation.addField(name);
+    String className = atts.getValue(ANALYZER);
+    if (className == null) {
+      creation.addField(name);
+    } else {
+      Analyzer analyzer = createAnalyzer(className);
+      creation.addFieldAndAnalyzer(name, analyzer);
+    }
   }
 
   private void startIndex(Attributes atts) {
@@ -94,4 +104,19 @@ public class LuceneXmlParser extends AbstractXmlParser {
     //Remove the index creation from the stack
     stack.pop();
   }
+
+  private Analyzer createAnalyzer(String className) {
+    Object obj;
+    try {
+      Class c = InternalDataSerializer.getCachedClass(className);
+      obj = c.newInstance();
+    }
+    catch (Exception ex) {
+      throw new CacheXmlException(LocalizedStrings.CacheXmlParser_WHILE_INSTANTIATING_A_0.toLocalizedString(className), ex);
+    }
+    if (!(obj instanceof Analyzer)) {
+      throw new CacheXmlException(LocalizedStrings.LuceneXmlParser_CLASS_0_IS_NOT_AN_INSTANCE_OF_ANALYZER.toLocalizedString(className));
+    }
+    return (Analyzer) obj;
+  }
 }

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/2a786ee7/geode-lucene/src/main/resources/META-INF/schemas/geode.apache.org/lucene/lucene-1.0.xsd
----------------------------------------------------------------------
diff --git a/geode-lucene/src/main/resources/META-INF/schemas/geode.apache.org/lucene/lucene-1.0.xsd b/geode-lucene/src/main/resources/META-INF/schemas/geode.apache.org/lucene/lucene-1.0.xsd
index 6fd7306..ec82c2f 100644
--- a/geode-lucene/src/main/resources/META-INF/schemas/geode.apache.org/lucene/lucene-1.0.xsd
+++ b/geode-lucene/src/main/resources/META-INF/schemas/geode.apache.org/lucene/lucene-1.0.xsd
@@ -48,6 +48,7 @@ XML schema for Lucene indexes in Geode.
     	  <xsd:element name="field" maxOccurs="unbounded">
 			<xsd:complexType>
 				<xsd:attribute name="name" type="xsd:string" />
+				<xsd:attribute name="analyzer" type="xsd:string" />
 			</xsd:complexType>
     	  </xsd:element>
     	</xsd:sequence>

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/2a786ee7/geode-lucene/src/test/java/com/gemstone/gemfire/cache/lucene/internal/xml/LuceneIndexXmlParserIntegrationJUnitTest.java
----------------------------------------------------------------------
diff --git a/geode-lucene/src/test/java/com/gemstone/gemfire/cache/lucene/internal/xml/LuceneIndexXmlParserIntegrationJUnitTest.java b/geode-lucene/src/test/java/com/gemstone/gemfire/cache/lucene/internal/xml/LuceneIndexXmlParserIntegrationJUnitTest.java
index 62b4f5a..f2972d4 100644
--- a/geode-lucene/src/test/java/com/gemstone/gemfire/cache/lucene/internal/xml/LuceneIndexXmlParserIntegrationJUnitTest.java
+++ b/geode-lucene/src/test/java/com/gemstone/gemfire/cache/lucene/internal/xml/LuceneIndexXmlParserIntegrationJUnitTest.java
@@ -27,6 +27,10 @@ import java.util.Collections;
 import java.util.HashMap;
 import java.util.Map;
 
+import org.apache.lucene.analysis.Analyzer;
+import org.apache.lucene.analysis.core.KeywordAnalyzer;
+import org.apache.lucene.analysis.core.SimpleAnalyzer;
+import org.apache.lucene.analysis.standard.ClassicAnalyzer;
 import org.junit.After;
 import org.junit.Rule;
 import org.junit.Test;
@@ -65,21 +69,55 @@ public class LuceneIndexXmlParserIntegrationJUnitTest {
    */
   @Test
   public void parseIndex() throws FileNotFoundException {
-    CacheXmlParser parser = CacheXmlParser.parse(new FileInputStream(getXmlFileForTest()));
-    CacheCreation cache = parser.getCacheCreation();
-    RegionCreation region = (RegionCreation) cache.getRegion("region");
+    RegionCreation region = createRegionCreation("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"});
+    expectedIndexes.put("index2", new String[] {"f", "g"});
+    validateExpectedIndexes(region, expectedIndexes);
+  }
+
+  @Test
+  public void parseIndexWithAnalyzers() throws FileNotFoundException {
+    RegionCreation region = createRegionCreation("region");
+
+    // Validate expected indexes
+    Map<String, String[]> expectedIndexes = new HashMap<String, String[]>();
+    expectedIndexes.put("index", new String[] {"a", "b", "c"});
+    validateExpectedIndexes(region, expectedIndexes);
+
+    // Validate expected analyzers
+    Map<String, Map<String,Class<? extends Analyzer>>> expectedIndexAnalyzers = new HashMap<>();
+    Map<String,Class<? extends Analyzer>> expectedFieldAnalyzers = new HashMap<>();
+    expectedFieldAnalyzers.put("a", KeywordAnalyzer.class);
+    expectedFieldAnalyzers.put("b", SimpleAnalyzer.class);
+    expectedFieldAnalyzers.put("c", ClassicAnalyzer.class);
+    expectedIndexAnalyzers.put("index", expectedFieldAnalyzers);
+    validateExpectedAnalyzers(region, expectedIndexAnalyzers);
+  }
+
+  private RegionCreation createRegionCreation(String regionName) throws FileNotFoundException {
+    CacheXmlParser parser = CacheXmlParser.parse(new FileInputStream(getXmlFileForTest()));
+    CacheCreation cache = parser.getCacheCreation();
+    return (RegionCreation) cache.getRegion(regionName);
+  }
+
+  private void validateExpectedIndexes(RegionCreation region, Map<String, String[]> expectedIndexes) {
     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);
   }
 
+  private void validateExpectedAnalyzers(RegionCreation region, Map<String, Map<String,Class<? extends Analyzer>>> expectedIndexAnalyzers) {
+    for(Extension extension : region.getExtensionPoint().getExtensions()) {
+      LuceneIndexCreation index = (LuceneIndexCreation) extension;
+      expectedIndexAnalyzers.remove(index.getName());
+    }
+    assertEquals(Collections.emptyMap(),expectedIndexAnalyzers);
+  }
+
   /**
    * Test that the Index creation objects get appropriately translated
    * into a real index.
@@ -93,11 +131,13 @@ public class LuceneIndexXmlParserIntegrationJUnitTest {
     Cache cache = cf.create();
 
     LuceneService service = LuceneServiceProvider.get(cache);
-    assertEquals(2, service.getAllIndexes().size());
+    assertEquals(3, service.getAllIndexes().size());
     LuceneIndex index1 = service.getIndex("index1", "/region");
     LuceneIndex index2 = service.getIndex("index2", "/region");
+    LuceneIndex index3 = service.getIndex("index3", "/region");
     assertArrayEquals(index1.getFieldNames(), new String[] {"a", "b", "c", "d"});
     assertArrayEquals(index2.getFieldNames(), new String[] { "f", "g"});
+    assertArrayEquals(index3.getFieldNames(), new String[] { "h", "i", "j"});
   }
 
   private String getXmlFileForTest() {

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/2a786ee7/geode-lucene/src/test/java/com/gemstone/gemfire/cache/lucene/internal/xml/LuceneIndexXmlParserJUnitTest.java
----------------------------------------------------------------------
diff --git a/geode-lucene/src/test/java/com/gemstone/gemfire/cache/lucene/internal/xml/LuceneIndexXmlParserJUnitTest.java b/geode-lucene/src/test/java/com/gemstone/gemfire/cache/lucene/internal/xml/LuceneIndexXmlParserJUnitTest.java
index 298c92f..cae2142 100644
--- a/geode-lucene/src/test/java/com/gemstone/gemfire/cache/lucene/internal/xml/LuceneIndexXmlParserJUnitTest.java
+++ b/geode-lucene/src/test/java/com/gemstone/gemfire/cache/lucene/internal/xml/LuceneIndexXmlParserJUnitTest.java
@@ -21,8 +21,13 @@ package com.gemstone.gemfire.cache.lucene.internal.xml;
 
 import static org.junit.Assert.*;
 
+import java.util.Map;
 import java.util.Stack;
 
+import org.apache.lucene.analysis.Analyzer;
+import org.apache.lucene.analysis.core.KeywordAnalyzer;
+import org.junit.After;
+import org.junit.Before;
 import org.junit.Test;
 import org.junit.experimental.categories.Category;
 import org.xml.sax.SAXException;
@@ -35,38 +40,78 @@ 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();
+
+  private LuceneXmlParser parser;
+
+  private RegionCreation rc;
+
+  private Stack<Object> stack;
+
+  @Before
+  public void setUp() {
+    this.parser = new LuceneXmlParser();
     CacheCreation cache = new CacheCreation();
-    RegionCreation rc = new RegionCreation(cache, "region");
-    Stack<Object> stack = new Stack<Object>();
+    this.rc = new RegionCreation(cache, "region");
+    this.stack = new Stack<Object>();
     stack.push(cache);
     stack.push(rc);
-    parser.setStack(stack);
+    this.parser.setStack(stack);
+  }
+
+  @After
+  public void tearDown() {
+    this.parser = null;
+    this.rc = null;
+    this.stack = null;
+  }
+
+  @Test
+  public void generateWithFields() throws SAXException {
+    AttributesImpl attrs = new AttributesImpl();
     XmlGeneratorUtils.addAttribute(attrs, LuceneXmlConstants.NAME, "index");
-    parser.startElement(LuceneXmlConstants.NAMESPACE, LuceneXmlConstants.INDEX, null, attrs);
-    
-    AttributesImpl field1 = new AttributesImpl();
-    XmlGeneratorUtils.addAttribute(field1, LuceneXmlConstants.NAME, "field1");
-    AttributesImpl field2 = new AttributesImpl();
-    XmlGeneratorUtils.addAttribute(field2, LuceneXmlConstants.NAME, "field2");
-    
-    parser.startElement(LuceneXmlConstants.NAMESPACE, LuceneXmlConstants.FIELD, null, field1);
-    parser.endElement(LuceneXmlConstants.NAMESPACE, LuceneXmlConstants.FIELD, null);
-    parser.startElement(LuceneXmlConstants.NAMESPACE, LuceneXmlConstants.FIELD, null, field2);
-    parser.endElement(LuceneXmlConstants.NAMESPACE, LuceneXmlConstants.FIELD, null);
-    
-    
-    parser.endElement(LuceneXmlConstants.NAMESPACE, LuceneXmlConstants.INDEX, null);
-    assertEquals(rc, stack.peek());
+    this.parser.startElement(LuceneXmlConstants.NAMESPACE, LuceneXmlConstants.INDEX, null, attrs);
+
+    addField("field1");
+    addField("field2");
+    addField("field3", KeywordAnalyzer.class.getName());
+
+    this.parser.endElement(LuceneXmlConstants.NAMESPACE, LuceneXmlConstants.INDEX, null);
+    assertEquals(this.rc, this.stack.peek());
     
-    LuceneIndexCreation index = (LuceneIndexCreation) rc.getExtensionPoint().getExtensions().iterator().next();
+    LuceneIndexCreation index = (LuceneIndexCreation) this.rc.getExtensionPoint().getExtensions().iterator().next();
     assertEquals("index", index.getName());
-    assertArrayEquals(new String[] {"field1", "field2"}, index.getFieldNames());
+    assertArrayEquals(new String[] {"field1", "field2", "field3"}, index.getFieldNames());
+
+    // Assert analyzers
+    Map<String, Analyzer> fieldAnalyzers = index.getFieldAnalyzers();
+    assertEquals(1, fieldAnalyzers.size());
+    assertTrue(fieldAnalyzers.containsKey("field3"));
+    assertTrue(fieldAnalyzers.get("field3") instanceof KeywordAnalyzer);
+  }
+
+  @Test
+  public void attemptInvalidAnalyzerClass() throws SAXException {
+    AttributesImpl attrs = new AttributesImpl();
+    XmlGeneratorUtils.addAttribute(attrs, LuceneXmlConstants.NAME, "index");
+    this.parser.startElement(LuceneXmlConstants.NAMESPACE, LuceneXmlConstants.INDEX, null, attrs);
+    try {
+      addField("field", "some.invalid.class");
+      fail("Should not have been able to add a field with an invalid analyzer class name");
+    } catch (Exception e) {
+    }
   }
-  
 
+  private void addField(String fieldName) throws SAXException {
+    addField(fieldName, null);
+  }
+
+  private void addField(String fieldName, String analyzerClassName) throws SAXException {
+    AttributesImpl field = new AttributesImpl();
+    XmlGeneratorUtils.addAttribute(field, LuceneXmlConstants.NAME, fieldName);
+    if (analyzerClassName != null) {
+      XmlGeneratorUtils.addAttribute(field, LuceneXmlConstants.ANALYZER, analyzerClassName);
+    }
+    this.parser.startElement(LuceneXmlConstants.NAMESPACE, LuceneXmlConstants.FIELD, null, field);
+    this.parser.endElement(LuceneXmlConstants.NAMESPACE, LuceneXmlConstants.FIELD, null);
+  }
 }

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/2a786ee7/geode-lucene/src/test/resources/com/gemstone/gemfire/cache/lucene/internal/xml/LuceneIndexXmlParserIntegrationJUnitTest.createIndex.cache.xml
----------------------------------------------------------------------
diff --git a/geode-lucene/src/test/resources/com/gemstone/gemfire/cache/lucene/internal/xml/LuceneIndexXmlParserIntegrationJUnitTest.createIndex.cache.xml b/geode-lucene/src/test/resources/com/gemstone/gemfire/cache/lucene/internal/xml/LuceneIndexXmlParserIntegrationJUnitTest.createIndex.cache.xml
index 89d5bef..acbf2c3 100644
--- a/geode-lucene/src/test/resources/com/gemstone/gemfire/cache/lucene/internal/xml/LuceneIndexXmlParserIntegrationJUnitTest.createIndex.cache.xml
+++ b/geode-lucene/src/test/resources/com/gemstone/gemfire/cache/lucene/internal/xml/LuceneIndexXmlParserIntegrationJUnitTest.createIndex.cache.xml
@@ -37,5 +37,10 @@
     	  <lucene:field name="f"/>
     	  <lucene:field name="g"/>
     	</lucene:index>
-    </region>    
+		<lucene:index name="index3">
+		  <lucene:field name="h" analyzer="org.apache.lucene.analysis.core.KeywordAnalyzer"/>
+		  <lucene:field name="i" analyzer="org.apache.lucene.analysis.core.SimpleAnalyzer"/>
+		  <lucene:field name="j" analyzer="org.apache.lucene.analysis.standard.ClassicAnalyzer"/>
+		</lucene:index>
+    </region>
 </cache>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/2a786ee7/geode-lucene/src/test/resources/com/gemstone/gemfire/cache/lucene/internal/xml/LuceneIndexXmlParserIntegrationJUnitTest.parseIndexWithAnalyzers.cache.xml
----------------------------------------------------------------------
diff --git a/geode-lucene/src/test/resources/com/gemstone/gemfire/cache/lucene/internal/xml/LuceneIndexXmlParserIntegrationJUnitTest.parseIndexWithAnalyzers.cache.xml b/geode-lucene/src/test/resources/com/gemstone/gemfire/cache/lucene/internal/xml/LuceneIndexXmlParserIntegrationJUnitTest.parseIndexWithAnalyzers.cache.xml
new file mode 100644
index 0000000..eed71fc
--- /dev/null
+++ b/geode-lucene/src/test/resources/com/gemstone/gemfire/cache/lucene/internal/xml/LuceneIndexXmlParserIntegrationJUnitTest.parseIndexWithAnalyzers.cache.xml
@@ -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.
+-->
+
+<cache
+    xmlns="http://geode.apache.org/schema/cache"
+    xmlns:lucene="http://geode.apache.org/schema/lucene"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xsi:schemaLocation="http://geode.apache.org/schema/cache
+        http://geode.apache.org/schema/cache/cache-1.0.xsd
+        http://geode.apache.org/schema/lucene
+        http://geode.apache.org/schema/lucene/lucene-1.0.xsd"
+    version="1.0">
+
+	<region name="region" refid="PARTITION">
+		<lucene:index name="index">
+		  <lucene:field name="a" analyzer="org.apache.lucene.analysis.core.KeywordAnalyzer"/>
+		  <lucene:field name="b" analyzer="org.apache.lucene.analysis.core.SimpleAnalyzer"/>
+		  <lucene:field name="c" analyzer="org.apache.lucene.analysis.standard.ClassicAnalyzer"/>
+		</lucene:index>
+    </region>
+</cache>
\ No newline at end of file