geode-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From zho...@apache.org
Subject incubator-geode git commit: GEODE-11: GFSH commands for Lucene
Date Mon, 11 Jul 2016 19:11:59 GMT
Repository: incubator-geode
Updated Branches:
  refs/heads/develop 48f6e6ec5 -> 82adda1cf


GEODE-11: GFSH commands for Lucene

Signed-off-by: Aparna Dharmakkan <adharmakkan@pivotal.io>

GEODE-11: Implementing GFSH command for listing lucene indexes.

Added the LuceneIndexCommands class that implements the list lucene index functionality in GFSH and the LuceneListIndexFunction class
that gets the information about lucene indexes from the cache. Also added a test to verify this functionality. The
org.springframework.shell.core.CommandMarker file is required to register the lucene commands in GFSH.

Signed-off-by: Gester Zhou <gzhou@pivotal.io>

GEODE-11: Adding JUnit test for LuceneIndexCommands

Added a JUnit test for getIndexListing()
Signed-off-by: Gester Zhou <gzhou@pivotal.io>

Adding a unit test for list lucene indexes gfsh command
Signed-off-by: Gester Zhou <gzhou@pivotal.io>

GEODE-11 Adding lucene create index gfsh command

Added lucene create index command and dunit tests.

Signed-off-by: Aparna Dharmakkan <adharmakkan@pivotal.io>

GEODE-11: Create lucene index gfsh command

Added a GFSH command to create a lucene index. Added DUnit and JUnit tests. Also added JUnit test for LucenListIndexFunction.
Made changes according to review comments.

Signed-off-by: Gester Zhou <gzhou@pivotal.io>

GEODE-1652: merge pull request 190, fix the conflicts

This closes #190


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

Branch: refs/heads/develop
Commit: 82adda1cf7eb55d39c29f99d06d73f9d9ad7b0dc
Parents: 48f6e6e
Author: Dan Smith <dsmith@pivotal.io>
Authored: Fri Jul 1 10:45:04 2016 -0700
Committer: zhouxh <gzhou@pivotal.io>
Committed: Mon Jul 11 12:09:31 2016 -0700

----------------------------------------------------------------------
 .../management/internal/cli/CliUtil.java        |  32 +++
 .../cli/functions/RegionCreateFunction.java     |  53 +---
 .../lucene/internal/cli/LuceneCliStrings.java   |  48 ++++
 .../internal/cli/LuceneIndexCommands.java       | 249 +++++++++++++++++++
 .../lucene/internal/cli/LuceneIndexDetails.java | 107 ++++++++
 .../lucene/internal/cli/LuceneIndexInfo.java    |  59 +++++
 .../functions/LuceneCreateIndexFunction.java    | 106 ++++++++
 .../cli/functions/LuceneListIndexFunction.java  |  66 +++++
 ...org.springframework.shell.core.CommandMarker |   2 +
 .../cli/LuceneIndexCommandsDUnitTest.java       | 197 +++++++++++++++
 .../cli/LuceneIndexCommandsJUnitTest.java       | 185 ++++++++++++++
 .../LuceneCreateIndexFunctionJUnitTest.java     | 126 ++++++++++
 .../LuceneListIndexFunctionJUnitTest.java       | 102 ++++++++
 13 files changed, 1289 insertions(+), 43 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/82adda1c/geode-core/src/main/java/com/gemstone/gemfire/management/internal/cli/CliUtil.java
----------------------------------------------------------------------
diff --git a/geode-core/src/main/java/com/gemstone/gemfire/management/internal/cli/CliUtil.java b/geode-core/src/main/java/com/gemstone/gemfire/management/internal/cli/CliUtil.java
index 30ae97b..94dee73 100755
--- a/geode-core/src/main/java/com/gemstone/gemfire/management/internal/cli/CliUtil.java
+++ b/geode-core/src/main/java/com/gemstone/gemfire/management/internal/cli/CliUtil.java
@@ -359,6 +359,38 @@ public class CliUtil {
     return stackAsString;
   }
 
+  @SuppressWarnings("unchecked")
+  public static <K> Class<K> forName(String classToLoadName, String neededFor) {
+    Class<K> loadedClass = null;
+    try {
+      // Set Constraints
+      ClassPathLoader classPathLoader = ClassPathLoader.getLatest();
+      if (classToLoadName != null && !classToLoadName.isEmpty()) {
+        loadedClass = (Class<K>) classPathLoader.forName(classToLoadName);
+      }
+    } catch (ClassNotFoundException | NoClassDefFoundError e) {
+      throw new RuntimeException(CliStrings.format(CliStrings.CREATE_REGION__MSG__COULDNOT_FIND_CLASS_0_SPECIFIED_FOR_1, new Object[] {classToLoadName, neededFor}), e);
+    }
+    catch (ClassCastException e) {
+      throw new RuntimeException(CliStrings.format(CliStrings.CREATE_REGION__MSG__CLASS_SPECIFIED_FOR_0_SPECIFIED_FOR_1_IS_NOT_OF_EXPECTED_TYPE, new Object[] {classToLoadName, neededFor}), e);
+    }
+
+    return loadedClass;
+  }
+
+  public static <K> K newInstance(Class<K> klass, String neededFor) {
+    K instance = null;
+    try {
+      instance = klass.newInstance();
+    } catch (InstantiationException e) {
+      throw new RuntimeException(CliStrings.format(CliStrings.CREATE_REGION__MSG__COULDNOT_INSTANTIATE_CLASS_0_SPECIFIED_FOR_1, new Object[] {klass, neededFor}), e);
+    } catch (IllegalAccessException e) {
+      throw new RuntimeException(CliStrings.format(CliStrings.CREATE_REGION__MSG__COULDNOT_ACCESS_CLASS_0_SPECIFIED_FOR_1, new Object[] {klass, neededFor}), e);
+    }
+
+    return instance;
+  }
+
   static class CustomFileFilter implements FileFilter {
     private String extensionWithDot;
 

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/82adda1c/geode-core/src/main/java/com/gemstone/gemfire/management/internal/cli/functions/RegionCreateFunction.java
----------------------------------------------------------------------
diff --git a/geode-core/src/main/java/com/gemstone/gemfire/management/internal/cli/functions/RegionCreateFunction.java b/geode-core/src/main/java/com/gemstone/gemfire/management/internal/cli/functions/RegionCreateFunction.java
index 7e060c2..48c0876 100644
--- a/geode-core/src/main/java/com/gemstone/gemfire/management/internal/cli/functions/RegionCreateFunction.java
+++ b/geode-core/src/main/java/com/gemstone/gemfire/management/internal/cli/functions/RegionCreateFunction.java
@@ -37,7 +37,6 @@ import com.gemstone.gemfire.cache.execute.FunctionAdapter;
 import com.gemstone.gemfire.cache.execute.FunctionContext;
 import com.gemstone.gemfire.cache.execute.ResultSender;
 import com.gemstone.gemfire.compression.Compressor;
-import com.gemstone.gemfire.internal.ClassPathLoader;
 import com.gemstone.gemfire.internal.InternalEntity;
 import com.gemstone.gemfire.internal.cache.xmlcache.CacheXml;
 import com.gemstone.gemfire.internal.i18n.LocalizedStrings;
@@ -205,12 +204,12 @@ public class RegionCreateFunction extends FunctionAdapter implements InternalEnt
     final String keyConstraint = regionCreateArgs.getKeyConstraint();
     final String valueConstraint = regionCreateArgs.getValueConstraint();
     if (keyConstraint != null && !keyConstraint.isEmpty()) {
-      Class<K> keyConstraintClass = forName(keyConstraint, CliStrings.CREATE_REGION__KEYCONSTRAINT);
+      Class<K> keyConstraintClass = CliUtil.forName(keyConstraint, CliStrings.CREATE_REGION__KEYCONSTRAINT);
       factory.setKeyConstraint(keyConstraintClass);
     }
 
     if (valueConstraint != null && !valueConstraint.isEmpty()) {
-      Class<V> valueConstraintClass = forName(valueConstraint, CliStrings.CREATE_REGION__VALUECONSTRAINT);
+      Class<V> valueConstraintClass = CliUtil.forName(valueConstraint, CliStrings.CREATE_REGION__VALUECONSTRAINT);
       factory.setValueConstraint(valueConstraintClass);
     }
 
@@ -296,27 +295,27 @@ public class RegionCreateFunction extends FunctionAdapter implements InternalEnt
     final Set<String> cacheListeners = regionCreateArgs.getCacheListeners();
     if (cacheListeners != null && !cacheListeners.isEmpty()) {
       for (String cacheListener : cacheListeners) {
-        Class<CacheListener<K, V>> cacheListenerKlass = forName(cacheListener, CliStrings.CREATE_REGION__CACHELISTENER);
-        factory.addCacheListener(newInstance(cacheListenerKlass, CliStrings.CREATE_REGION__CACHELISTENER));
+        Class<CacheListener<K, V>> cacheListenerKlass = CliUtil.forName(cacheListener, CliStrings.CREATE_REGION__CACHELISTENER);
+        factory.addCacheListener(CliUtil.newInstance(cacheListenerKlass, CliStrings.CREATE_REGION__CACHELISTENER));
       }
     }
 
     // Compression provider
     if(regionCreateArgs.isSetCompressor()) {
-      Class<Compressor> compressorKlass = forName(regionCreateArgs.getCompressor(), CliStrings.CREATE_REGION__COMPRESSOR);
-      factory.setCompressor(newInstance(compressorKlass, CliStrings.CREATE_REGION__COMPRESSOR));
+      Class<Compressor> compressorKlass = CliUtil.forName(regionCreateArgs.getCompressor(), CliStrings.CREATE_REGION__COMPRESSOR);
+      factory.setCompressor(CliUtil.newInstance(compressorKlass, CliStrings.CREATE_REGION__COMPRESSOR));
     }
     
     final String cacheLoader = regionCreateArgs.getCacheLoader();
     if (cacheLoader != null) {
-      Class<CacheLoader<K, V>> cacheLoaderKlass = forName(cacheLoader, CliStrings.CREATE_REGION__CACHELOADER);
-      factory.setCacheLoader(newInstance(cacheLoaderKlass, CliStrings.CREATE_REGION__CACHELOADER));
+      Class<CacheLoader<K, V>> cacheLoaderKlass = CliUtil.forName(cacheLoader, CliStrings.CREATE_REGION__CACHELOADER);
+      factory.setCacheLoader(CliUtil.newInstance(cacheLoaderKlass, CliStrings.CREATE_REGION__CACHELOADER));
     }
 
     final String cacheWriter = regionCreateArgs.getCacheWriter();
     if (cacheWriter != null) {
-      Class<CacheWriter<K, V>> cacheWriterKlass = forName(cacheWriter, CliStrings.CREATE_REGION__CACHEWRITER);
-      factory.setCacheWriter(newInstance(cacheWriterKlass, CliStrings.CREATE_REGION__CACHEWRITER));
+      Class<CacheWriter<K, V>> cacheWriterKlass = CliUtil.forName(cacheWriter, CliStrings.CREATE_REGION__CACHEWRITER);
+      factory.setCacheWriter(CliUtil.newInstance(cacheWriterKlass, CliStrings.CREATE_REGION__CACHEWRITER));
     }
     
     String regionName = regionPathData.getName();
@@ -376,38 +375,6 @@ public class RegionCreateFunction extends FunctionAdapter implements InternalEnt
     return prAttrFactory.create();
   }
 
-  @SuppressWarnings("unchecked")
-  private static <K> Class<K> forName(String classToLoadName, String neededFor) {
-    Class<K> loadedClass = null;
-    try {
-      // Set Constraints
-      ClassPathLoader classPathLoader = ClassPathLoader.getLatest();
-      if (classToLoadName != null && !classToLoadName.isEmpty()) {
-        loadedClass = (Class<K>) classPathLoader.forName(classToLoadName);
-      }
-    } catch (ClassNotFoundException | NoClassDefFoundError e) {
-      throw new RuntimeException(CliStrings.format(CliStrings.CREATE_REGION__MSG__COULDNOT_FIND_CLASS_0_SPECIFIED_FOR_1, new Object[] {classToLoadName, neededFor}), e);
-    }
-    catch (ClassCastException e) {
-      throw new RuntimeException(CliStrings.format(CliStrings.CREATE_REGION__MSG__CLASS_SPECIFIED_FOR_0_SPECIFIED_FOR_1_IS_NOT_OF_EXPECTED_TYPE, new Object[] {classToLoadName, neededFor}), e);
-    }
-
-    return loadedClass;
-  }
-
-  private static <K> K newInstance(Class<K> klass, String neededFor) {
-    K instance = null;
-    try {
-      instance = klass.newInstance();
-    } catch (InstantiationException e) {
-      throw new RuntimeException(CliStrings.format(CliStrings.CREATE_REGION__MSG__COULDNOT_INSTANTIATE_CLASS_0_SPECIFIED_FOR_1, new Object[] {klass, neededFor}), e);
-    } catch (IllegalAccessException e) {
-      throw new RuntimeException(CliStrings.format(CliStrings.CREATE_REGION__MSG__COULDNOT_ACCESS_CLASS_0_SPECIFIED_FOR_1, new Object[] {klass, neededFor}), e);
-    }
-
-    return instance;
-  }
-
   @Override
   public String getId() {
     return ID;

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/82adda1c/geode-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/cli/LuceneCliStrings.java
----------------------------------------------------------------------
diff --git a/geode-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/cli/LuceneCliStrings.java b/geode-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/cli/LuceneCliStrings.java
new file mode 100644
index 0000000..3248e75
--- /dev/null
+++ b/geode-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/cli/LuceneCliStrings.java
@@ -0,0 +1,48 @@
+/*
+ * 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 com.gemstone.gemfire.cache.lucene.internal.cli;
+
+public class LuceneCliStrings {
+  //List Lucene Index commands
+  public static final String LUCENE_LIST_INDEX = "list lucene index";
+  public static final String LUCENE_LIST_INDEX__HELP = "Display the list of lucene indexes created for all members.";
+  public static final String LUCENE_LIST_INDEX__ERROR_MESSAGE = "An error occurred while collecting all lucene index information across the Geode cluster: %1$s";
+  public static final String LUCENE_LIST_INDEX__INDEXES_NOT_FOUND_MESSAGE = "No lucene indexes Found";
+
+  public static final String LUCENE_CREATE_INDEX = "create lucene index";
+  public static final String LUCENE_CREATE_INDEX__HELP = "Create a lucene index that can be used to execute queries.";
+  public static final String LUCENE_CREATE_INDEX__NAME = "name";
+  public static final String LUCENE_CREATE_INDEX__NAME__HELP = "Name of the lucene index to create.";
+  public static final String LUCENE_CREATE_INDEX__REGION = "region";
+  public static final String LUCENE_CREATE_INDEX__REGION_HELP = "Name/Path of the region where the lucene index is created on.";
+  public static final String LUCENE_CREATE_INDEX__FIELD = "field";
+  public static final String LUCENE_CREATE_INDEX__FIELD_HELP = "fields on the region values which are stored in the lucene index.";
+  public static final String LUCENE_CREATE_INDEX__ANALYZER = "analyzer";
+  public static final String LUCENE_CREATE_INDEX__ANALYZER_HELP = "Type of the analyzer for each field.";
+  public static final String LUCENE_CREATE_INDEX__GROUP = "group";
+  public static final String LUCENE_CREATE_INDEX__GROUP__HELP = "Group of members in which the lucene index will be created.";
+
+  public static final String CREATE_INDEX__SUCCESS__MSG = "Index successfully created with following details";
+  public static final String CREATE_INDEX__FAILURE__MSG = "Failed to create index \"{0}\" due to following reasons";
+  public static final String CREATE_INDEX__NAME__MSG = "Name       : {0}";
+  public static final String CREATE_INDEX__REGIONPATH__MSG = "RegionPath : {0}";
+  public static final String CREATE_INDEX__MEMBER__MSG = "Members which contain the index";
+  public static final String CREATE_INDEX__NUMBER__AND__MEMBER = "{0}. {1}";
+  public static final String CREATE_INDEX__EXCEPTION__OCCURRED__ON = "Occurred on following members";
+}

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/82adda1c/geode-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/cli/LuceneIndexCommands.java
----------------------------------------------------------------------
diff --git a/geode-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/cli/LuceneIndexCommands.java b/geode-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/cli/LuceneIndexCommands.java
new file mode 100755
index 0000000..796d9f7
--- /dev/null
+++ b/geode-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/cli/LuceneIndexCommands.java
@@ -0,0 +1,249 @@
+/*
+ * 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 com.gemstone.gemfire.cache.lucene.internal.cli;
+
+import static com.gemstone.gemfire.cache.operations.OperationContext.*;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeSet;
+import java.util.stream.Collectors;
+
+import com.gemstone.gemfire.SystemFailure;
+import com.gemstone.gemfire.cache.Cache;
+import com.gemstone.gemfire.cache.CacheFactory;
+import com.gemstone.gemfire.cache.execute.Execution;
+import com.gemstone.gemfire.cache.execute.FunctionInvocationTargetException;
+import com.gemstone.gemfire.cache.execute.ResultCollector;
+import com.gemstone.gemfire.cache.lucene.internal.cli.functions.LuceneCreateIndexFunction;
+import com.gemstone.gemfire.cache.lucene.internal.cli.functions.LuceneListIndexFunction;
+import com.gemstone.gemfire.distributed.DistributedMember;
+import com.gemstone.gemfire.internal.cache.execute.AbstractExecution;
+import com.gemstone.gemfire.internal.security.GeodeSecurityUtil;
+import com.gemstone.gemfire.management.cli.CliMetaData;
+import com.gemstone.gemfire.management.cli.ConverterHint;
+import com.gemstone.gemfire.management.cli.Result;
+import com.gemstone.gemfire.management.internal.cli.CliUtil;
+import com.gemstone.gemfire.management.internal.cli.commands.AbstractCommandsSupport;
+
+import com.gemstone.gemfire.management.internal.cli.domain.IndexInfo;
+import com.gemstone.gemfire.management.internal.cli.functions.CliFunctionResult;
+import com.gemstone.gemfire.management.internal.cli.i18n.CliStrings;
+import com.gemstone.gemfire.management.internal.cli.result.CommandResultException;
+import com.gemstone.gemfire.management.internal.cli.result.ErrorResultData;
+import com.gemstone.gemfire.management.internal.cli.result.InfoResultData;
+import com.gemstone.gemfire.management.internal.cli.result.ResultBuilder;
+import com.gemstone.gemfire.management.internal.cli.result.TabularResultData;
+import com.gemstone.gemfire.management.internal.configuration.SharedConfigurationWriter;
+import com.gemstone.gemfire.management.internal.configuration.domain.XmlEntity;
+import com.gemstone.gemfire.management.internal.security.ResourceOperation;
+import com.gemstone.gemfire.security.GeodePermission.Operation;
+import com.gemstone.gemfire.security.GeodePermission.Resource;
+
+import org.springframework.shell.core.annotation.CliCommand;
+import org.springframework.shell.core.annotation.CliOption;
+
+/**
+ * The LuceneIndexCommands class encapsulates all Geode shell (Gfsh) commands related to Lucene indexes defined in Geode.
+ * </p>
+ * @see AbstractCommandsSupport
+ * @see LuceneIndexDetails
+ * @see LuceneListIndexFunction
+ */
+@SuppressWarnings("unused")
+public class LuceneIndexCommands extends AbstractCommandsSupport {
+
+  private static final LuceneCreateIndexFunction createIndexFunction = new LuceneCreateIndexFunction();
+
+  @CliCommand(value = LuceneCliStrings.LUCENE_LIST_INDEX, help = LuceneCliStrings.LUCENE_LIST_INDEX__HELP)
+  @CliMetaData(shellOnly = false, relatedTopic={CliStrings.TOPIC_GEODE_REGION, CliStrings.TOPIC_GEODE_DATA })
+  @ResourceOperation(resource = Resource.CLUSTER, operation = Operation.READ)
+  public Result listIndex() {
+    try {
+      return toTabularResult(getIndexListing());
+    }
+    catch (FunctionInvocationTargetException ignore) {
+      return ResultBuilder.createGemFireErrorResult(CliStrings.format(CliStrings.COULD_NOT_EXECUTE_COMMAND_TRY_AGAIN,
+        LuceneCliStrings.LUCENE_LIST_INDEX));
+    }
+    catch (VirtualMachineError e) {
+      SystemFailure.initiateFailure(e);
+      throw e;
+    }
+    catch (Throwable t) {
+      SystemFailure.checkFailure();
+      getCache().getLogger().error(t);
+      return ResultBuilder.createGemFireErrorResult(String.format(LuceneCliStrings.LUCENE_LIST_INDEX__ERROR_MESSAGE,
+        toString(t, isDebugging())));
+    }
+  }
+
+  @SuppressWarnings("unchecked")
+  protected List<LuceneIndexDetails> getIndexListing() {
+    final Execution functionExecutor = getMembersFunctionExecutor(getMembers(getCache()));
+
+    if (functionExecutor instanceof AbstractExecution) {
+      ((AbstractExecution) functionExecutor).setIgnoreDepartedMembers(true);
+    }
+
+    final ResultCollector resultsCollector = functionExecutor.execute(new LuceneListIndexFunction());
+    final List<Set<LuceneIndexDetails>> results = (List<Set<LuceneIndexDetails>>) resultsCollector.getResult();
+
+    return results.stream()
+      .flatMap(set -> set.stream())
+      .sorted()
+      .collect(Collectors.toList());
+  }
+
+  protected Result toTabularResult(final List<LuceneIndexDetails> indexDetailsList) {
+    if (!indexDetailsList.isEmpty()) {
+      final TabularResultData indexData = ResultBuilder.createTabularResultData();
+
+      for (final LuceneIndexDetails indexDetails : indexDetailsList) {
+        indexData.accumulate("Index Name", indexDetails.getIndexName());
+        indexData.accumulate("Region Path", indexDetails.getRegionPath());
+        indexData.accumulate("Indexed Fields", indexDetails.getSearchableFieldNamesString());
+        indexData.accumulate("Field Analyzer", indexDetails.getFieldAnalyzersString());
+      }
+      return ResultBuilder.buildResult(indexData);
+    }
+    else {
+      return ResultBuilder.createInfoResult(LuceneCliStrings.LUCENE_LIST_INDEX__INDEXES_NOT_FOUND_MESSAGE);
+    }
+  }
+
+  @CliCommand(value = LuceneCliStrings.LUCENE_CREATE_INDEX, help = LuceneCliStrings.LUCENE_CREATE_INDEX__HELP)
+  @CliMetaData(shellOnly = false, relatedTopic={CliStrings.TOPIC_GEODE_REGION, CliStrings.TOPIC_GEODE_DATA }, writesToSharedConfiguration=true)
+  //TODO : Add optionContext for indexName
+  public Result createIndex(
+    @CliOption(key = LuceneCliStrings.LUCENE_CREATE_INDEX__NAME,
+      mandatory=true,
+      help = LuceneCliStrings.LUCENE_CREATE_INDEX__NAME__HELP) final String indexName,
+
+    @CliOption (key = LuceneCliStrings.LUCENE_CREATE_INDEX__REGION,
+      mandatory = true,
+      optionContext = ConverterHint.REGIONPATH,
+      help = LuceneCliStrings.LUCENE_CREATE_INDEX__REGION_HELP) final String regionPath,
+
+    @CliOption(key = LuceneCliStrings.LUCENE_CREATE_INDEX__FIELD,
+      mandatory = true,
+      help = LuceneCliStrings.LUCENE_CREATE_INDEX__FIELD_HELP)
+    @CliMetaData (valueSeparator = ",") final String[] fields,
+
+    @CliOption(key = LuceneCliStrings.LUCENE_CREATE_INDEX__ANALYZER,
+      mandatory = false,
+      unspecifiedDefaultValue = CliMetaData.ANNOTATION_NULL_VALUE,
+      help = LuceneCliStrings.LUCENE_CREATE_INDEX__ANALYZER_HELP)
+    @CliMetaData (valueSeparator = ",") final String[] analyzers,
+
+    @CliOption (key = LuceneCliStrings.LUCENE_CREATE_INDEX__GROUP,
+      optionContext = ConverterHint.MEMBERGROUP,
+      unspecifiedDefaultValue = CliMetaData.ANNOTATION_NULL_VALUE,
+      help = LuceneCliStrings.LUCENE_CREATE_INDEX__GROUP__HELP)
+    @CliMetaData (valueSeparator = ",") final String[] groups) {
+
+    Result result = null;
+    XmlEntity xmlEntity = null;
+
+    GeodeSecurityUtil.authorizeRegionManage(regionPath);
+    try {
+      final Cache cache = getCache();
+      LuceneIndexInfo indexInfo = new LuceneIndexInfo(indexName, regionPath, fields, analyzers);
+      final ResultCollector<?, ?> rc = this.createIndexOnGroups(groups, indexInfo);
+      final List<CliFunctionResult> funcResults = (List<CliFunctionResult>) rc.getResult();
+
+      final Set<String> successfulMembers = new TreeSet<String>();
+      final Map<String, Set<String>> indexOpFailMap = new HashMap<String, Set<String>>();
+
+      for (final CliFunctionResult cliFunctionResult : funcResults) {
+
+          if (cliFunctionResult.isSuccessful()) {
+            successfulMembers.add(cliFunctionResult.getMemberIdOrName());
+
+            if (xmlEntity == null) {
+              xmlEntity = cliFunctionResult.getXmlEntity();
+            }
+          }
+          else {
+            final String exceptionMessage = cliFunctionResult.getMessage();
+            Set<String> failedMembers = indexOpFailMap.get(exceptionMessage);
+
+            if (failedMembers == null) {
+              failedMembers = new TreeSet<String>();
+            }
+            failedMembers.add(cliFunctionResult.getMemberIdOrName());
+            indexOpFailMap.put(exceptionMessage, failedMembers);
+          }
+      }
+
+      if (!successfulMembers.isEmpty()) {
+
+        final InfoResultData infoResult = ResultBuilder.createInfoResultData();
+        infoResult.addLine(LuceneCliStrings.CREATE_INDEX__SUCCESS__MSG);
+        infoResult.addLine(CliStrings.format(LuceneCliStrings.CREATE_INDEX__NAME__MSG, indexName));
+        infoResult.addLine(CliStrings.format(LuceneCliStrings.CREATE_INDEX__REGIONPATH__MSG, regionPath));
+        infoResult.addLine(LuceneCliStrings.CREATE_INDEX__MEMBER__MSG);
+
+        int num = 0;
+
+        for (final String memberId : successfulMembers) {
+          ++num;
+          infoResult.addLine(CliStrings.format(LuceneCliStrings.CREATE_INDEX__NUMBER__AND__MEMBER, num, memberId));
+        }
+        result = ResultBuilder.buildResult(infoResult);
+
+
+      } else {
+        //Group members by the exception thrown.
+        final ErrorResultData erd = ResultBuilder.createErrorResultData();
+        erd.addLine(CliStrings.format(LuceneCliStrings.CREATE_INDEX__FAILURE__MSG, indexName));
+
+        final Set<String> exceptionMessages = indexOpFailMap.keySet();
+
+        for (final String exceptionMessage : exceptionMessages) {
+          erd.addLine(exceptionMessage);
+          erd.addLine(LuceneCliStrings.CREATE_INDEX__EXCEPTION__OCCURRED__ON);
+          final Set<String> memberIds = indexOpFailMap.get(exceptionMessage);
+
+          int num = 0;
+          for (final String memberId : memberIds) {
+            ++num;
+            erd.addLine(CliStrings.format(LuceneCliStrings.CREATE_INDEX__NUMBER__AND__MEMBER, num, memberId));
+          }
+        }
+        result = ResultBuilder.buildResult(erd);
+      }
+    } catch (CommandResultException crex) {
+      result = crex.getResult();
+    } catch (Exception e) {
+      result = ResultBuilder.createGemFireErrorResult(e.getMessage());
+    }
+//    TODO - store in cluster config
+//    if (xmlEntity != null) {
+//      result.setCommandPersisted((new SharedConfigurationWriter()).addXmlEntity(xmlEntity, groups));
+//    }
+
+    return result;
+  }
+
+  protected ResultCollector<?, ?> createIndexOnGroups( String[] groups, final LuceneIndexInfo indexInfo) throws CommandResultException {
+    final Set<DistributedMember> targetMembers = CliUtil.findAllMatchingMembers(groups, null);
+    return CliUtil.executeFunction(createIndexFunction, indexInfo, targetMembers);
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/82adda1c/geode-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/cli/LuceneIndexDetails.java
----------------------------------------------------------------------
diff --git a/geode-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/cli/LuceneIndexDetails.java b/geode-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/cli/LuceneIndexDetails.java
new file mode 100644
index 0000000..c967530
--- /dev/null
+++ b/geode-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/cli/LuceneIndexDetails.java
@@ -0,0 +1,107 @@
+/*
+ * 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 com.gemstone.gemfire.cache.lucene.internal.cli;
+
+import java.io.Serializable;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Map.Entry;
+import com.gemstone.gemfire.cache.lucene.internal.LuceneIndexImpl;
+
+import org.apache.lucene.analysis.Analyzer;
+
+public class LuceneIndexDetails implements Comparable<LuceneIndexDetails>, Serializable {
+  private static final long serialVersionUID = 1L;
+
+  private final String indexName;
+  private final String regionPath;
+  private final String[] searchableFieldNames;
+  private final Map<String, String> fieldAnalyzers;
+
+  public LuceneIndexDetails(final String indexName, final String regionPath, final String[] searchableFieldNames, Map<String, Analyzer> fieldAnalyzers) {
+    this.indexName = indexName;
+    this.regionPath = regionPath;
+    this.searchableFieldNames = searchableFieldNames;
+    this.fieldAnalyzers = getAnalyzerStrings(fieldAnalyzers);
+  }
+
+  public LuceneIndexDetails(LuceneIndexImpl index) {
+    this(index.getName(), index.getRegionPath(), index.getFieldNames(), index.getFieldAnalyzers());
+  }
+
+  private Map<String, String> getAnalyzerStrings(Map<String, Analyzer> fieldAnalyzers) {
+    if(fieldAnalyzers == null) {
+      return Collections.emptyMap();
+    }
+
+    Map<String, String> results = new HashMap<>();
+
+    for (Entry<String, Analyzer> entry : fieldAnalyzers.entrySet()) {
+      final Analyzer analyzer = entry.getValue();
+      if(analyzer != null) {
+        results.put(entry.getKey(), analyzer.getClass().getSimpleName());
+      }
+    }
+    return results;
+  }
+
+  public String getSearchableFieldNamesString() {
+    return Arrays.asList(searchableFieldNames).toString();
+  }
+
+
+  public String getFieldAnalyzersString() {
+    return fieldAnalyzers.toString();
+  }
+
+  @Override
+  public String toString() {
+    final StringBuffer buffer = new StringBuffer();
+    buffer.append("{\n\tIndex Name = "+indexName);
+    buffer.append(",\tRegion Path = "+regionPath);
+    buffer.append(",\tIndexed Fields = "+getSearchableFieldNamesString());
+    buffer.append(",\tField Analyzer = "+getFieldAnalyzersString());
+    buffer.append("\n}\n");
+    return buffer.toString();
+  }
+
+
+  public String getIndexName() {
+    return indexName;
+  }
+
+  public String getRegionPath() {
+    return regionPath;
+  }
+
+  public String[] getSearchableFieldNames() {
+    return searchableFieldNames;
+  }
+
+  private static <T extends Comparable<T>> int compare(final T obj1, final T obj2) {
+    return (obj1 == null && obj2 == null ? 0 : (obj1 == null ? 1 : (obj2 == null ? -1 : obj1.compareTo(obj2))));
+  }
+
+  @Override
+  public int compareTo(final LuceneIndexDetails indexDetails) {
+    int comparisonValue = compare(getIndexName(), indexDetails.getIndexName());
+    return (comparisonValue != 0 ? comparisonValue : compare(getRegionPath(), indexDetails.getRegionPath()));
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/82adda1c/geode-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/cli/LuceneIndexInfo.java
----------------------------------------------------------------------
diff --git a/geode-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/cli/LuceneIndexInfo.java b/geode-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/cli/LuceneIndexInfo.java
new file mode 100644
index 0000000..76b7b60
--- /dev/null
+++ b/geode-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/cli/LuceneIndexInfo.java
@@ -0,0 +1,59 @@
+/*
+ * 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 com.gemstone.gemfire.cache.lucene.internal.cli;
+
+import java.io.Serializable;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Map.Entry;
+import com.gemstone.gemfire.cache.lucene.internal.LuceneIndexImpl;
+
+import org.apache.lucene.analysis.Analyzer;
+
+public class LuceneIndexInfo implements Serializable {
+  private static final long serialVersionUID = 1L;
+
+  private final String indexName;
+  private final String regionPath;
+  private final String[] searchableFieldNames;
+  private final String[] fieldAnalyzers;
+
+  public LuceneIndexInfo(final String indexName, final String regionPath, final String[] searchableFieldNames, String[] fieldAnalyzers) {
+    this.indexName = indexName;
+    this.regionPath = regionPath;
+    this.searchableFieldNames = searchableFieldNames;
+    this.fieldAnalyzers = fieldAnalyzers;
+  }
+
+  public String getIndexName() {
+    return indexName;
+  }
+
+  public String getRegionPath() {
+    return regionPath;
+  }
+
+  public String[] getSearchableFieldNames() {
+    return searchableFieldNames;
+  }
+
+  public String[] getFieldAnalyzers() {
+    return fieldAnalyzers;
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/82adda1c/geode-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/cli/functions/LuceneCreateIndexFunction.java
----------------------------------------------------------------------
diff --git a/geode-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/cli/functions/LuceneCreateIndexFunction.java b/geode-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/cli/functions/LuceneCreateIndexFunction.java
new file mode 100644
index 0000000..d943fbc
--- /dev/null
+++ b/geode-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/cli/functions/LuceneCreateIndexFunction.java
@@ -0,0 +1,106 @@
+/*
+ * 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 com.gemstone.gemfire.cache.lucene.internal.cli.functions;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import com.gemstone.gemfire.cache.Cache;
+import com.gemstone.gemfire.cache.CacheFactory;
+import com.gemstone.gemfire.cache.execute.FunctionAdapter;
+import com.gemstone.gemfire.cache.execute.FunctionContext;
+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.cache.lucene.internal.LuceneIndexImpl;
+import com.gemstone.gemfire.cache.lucene.internal.cli.LuceneCliStrings;
+import com.gemstone.gemfire.cache.lucene.internal.cli.LuceneIndexDetails;
+import com.gemstone.gemfire.cache.lucene.internal.cli.LuceneIndexInfo;
+import com.gemstone.gemfire.internal.InternalEntity;
+import com.gemstone.gemfire.management.internal.cli.CliUtil;
+import com.gemstone.gemfire.management.internal.cli.functions.CliFunctionResult;
+import com.gemstone.gemfire.management.internal.cli.i18n.CliStrings;
+import com.gemstone.gemfire.management.internal.configuration.domain.XmlEntity;
+
+import org.apache.lucene.analysis.Analyzer;
+
+
+/**
+ * The LuceneCreateIndexFunction class is a function used to create Lucene indexes.
+ * </p>
+ * @see Cache
+ * @see com.gemstone.gemfire.cache.execute.Function
+ * @see FunctionAdapter
+ * @see FunctionContext
+ * @see InternalEntity
+ * @see LuceneIndexDetails
+ */
+@SuppressWarnings("unused")
+public class LuceneCreateIndexFunction extends FunctionAdapter implements InternalEntity {
+
+  protected Cache getCache() {
+    return CacheFactory.getAnyInstance();
+  }
+
+  public String getId() {
+    return LuceneListIndexFunction.class.getName();
+  }
+
+  public void execute(final FunctionContext context) {
+    String memberId = null;
+    try {
+      final LuceneIndexInfo indexInfo = (LuceneIndexInfo) context.getArguments();
+      final Cache cache = getCache();
+      memberId = cache.getDistributedSystem().getDistributedMember().getId();
+      LuceneService service = LuceneServiceProvider.get(cache);
+
+      String[] fields = indexInfo.getSearchableFieldNames();
+      String[] analyzerName = indexInfo.getFieldAnalyzers();
+
+      if (analyzerName == null || analyzerName.length == 0) {
+        service.createIndex(indexInfo.getIndexName(), indexInfo.getRegionPath(), fields);
+      }
+      else {
+        Map<String, Analyzer> fieldAnalyzer = new HashMap<>();
+        for (int i = 0; i < fields.length; i++) {
+          Analyzer analyzer = toAnalyzer(analyzerName[i]);
+          fieldAnalyzer.put(fields[i], analyzer);
+        }
+        service.createIndex(indexInfo.getIndexName(), indexInfo.getRegionPath(), fieldAnalyzer);
+      }
+
+      //TODO - update cluster configuration by returning a valid XmlEntity
+      XmlEntity xmlEntity = null;
+      context.getResultSender().lastResult(new CliFunctionResult(memberId, xmlEntity));
+    }
+    catch (Exception e) {
+      String exceptionMessage = CliStrings.format(CliStrings.EXCEPTION_CLASS_AND_MESSAGE, e.getClass().getName(),
+        e.getMessage());
+      context.getResultSender().lastResult(new CliFunctionResult(memberId, e, e.getMessage()));
+    }
+  }
+
+  private Analyzer toAnalyzer(final String className)
+  {
+    Class<? extends Analyzer> clazz = CliUtil.forName(className, LuceneCliStrings.LUCENE_CREATE_INDEX__ANALYZER);
+    return CliUtil.newInstance(clazz, LuceneCliStrings.LUCENE_CREATE_INDEX__ANALYZER);
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/82adda1c/geode-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/cli/functions/LuceneListIndexFunction.java
----------------------------------------------------------------------
diff --git a/geode-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/cli/functions/LuceneListIndexFunction.java b/geode-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/cli/functions/LuceneListIndexFunction.java
new file mode 100755
index 0000000..4460d57
--- /dev/null
+++ b/geode-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/cli/functions/LuceneListIndexFunction.java
@@ -0,0 +1,66 @@
+/*
+ * 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 com.gemstone.gemfire.cache.lucene.internal.cli.functions;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import com.gemstone.gemfire.cache.Cache;
+import com.gemstone.gemfire.cache.CacheFactory;
+import com.gemstone.gemfire.cache.execute.FunctionAdapter;
+import com.gemstone.gemfire.cache.execute.FunctionContext;
+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.cache.lucene.internal.LuceneIndexImpl;
+import com.gemstone.gemfire.cache.lucene.internal.cli.LuceneIndexDetails;
+import com.gemstone.gemfire.internal.InternalEntity;
+
+/**
+ * The LuceneListIndexFunction class is a function used to collect the information on all lucene indexes in
+ * the entire Cache.
+ * </p>
+ * @see Cache
+ * @see com.gemstone.gemfire.cache.execute.Function
+ * @see FunctionAdapter
+ * @see FunctionContext
+ * @see InternalEntity
+ * @see LuceneIndexDetails
+ */
+@SuppressWarnings("unused")
+public class LuceneListIndexFunction extends FunctionAdapter implements InternalEntity {
+
+  protected Cache getCache() {
+    return CacheFactory.getAnyInstance();
+  }
+
+  public String getId() {
+    return LuceneListIndexFunction.class.getName();
+  }
+
+  public void execute(final FunctionContext context) {
+    final Set<LuceneIndexDetails> indexDetailsSet = new HashSet<>();
+    final Cache cache = getCache();
+    LuceneService service = LuceneServiceProvider.get(cache);
+    for (LuceneIndex index : service.getAllIndexes()) {
+      indexDetailsSet.add(new LuceneIndexDetails((LuceneIndexImpl) index));
+    }
+    context.getResultSender().lastResult(indexDetailsSet);
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/82adda1c/geode-lucene/src/main/resources/META-INF/services/org.springframework.shell.core.CommandMarker
----------------------------------------------------------------------
diff --git a/geode-lucene/src/main/resources/META-INF/services/org.springframework.shell.core.CommandMarker b/geode-lucene/src/main/resources/META-INF/services/org.springframework.shell.core.CommandMarker
new file mode 100644
index 0000000..5d37d35
--- /dev/null
+++ b/geode-lucene/src/main/resources/META-INF/services/org.springframework.shell.core.CommandMarker
@@ -0,0 +1,2 @@
+# Lucene Extensions command
+com.gemstone.gemfire.cache.lucene.internal.cli.LuceneIndexCommands
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/82adda1c/geode-lucene/src/test/java/com/gemstone/gemfire/cache/lucene/internal/cli/LuceneIndexCommandsDUnitTest.java
----------------------------------------------------------------------
diff --git a/geode-lucene/src/test/java/com/gemstone/gemfire/cache/lucene/internal/cli/LuceneIndexCommandsDUnitTest.java b/geode-lucene/src/test/java/com/gemstone/gemfire/cache/lucene/internal/cli/LuceneIndexCommandsDUnitTest.java
new file mode 100755
index 0000000..2647bcc
--- /dev/null
+++ b/geode-lucene/src/test/java/com/gemstone/gemfire/cache/lucene/internal/cli/LuceneIndexCommandsDUnitTest.java
@@ -0,0 +1,197 @@
+/*
+ * 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 com.gemstone.gemfire.cache.lucene.internal.cli;
+
+import com.gemstone.gemfire.cache.*;
+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.distributed.ConfigurationProperties;
+import com.gemstone.gemfire.management.cli.Result.Status;
+import com.gemstone.gemfire.management.internal.cli.CommandManager;
+import com.gemstone.gemfire.management.internal.cli.commands.CliCommandTestBase;
+import com.gemstone.gemfire.management.internal.cli.result.CommandResult;
+import com.gemstone.gemfire.management.internal.cli.util.CommandStringBuilder;
+import com.gemstone.gemfire.test.dunit.*;
+import com.gemstone.gemfire.test.junit.categories.DistributedTest;
+import com.sun.org.apache.regexp.internal.RE;
+
+import org.apache.lucene.analysis.Analyzer;
+import org.apache.lucene.analysis.core.KeywordAnalyzer;
+import org.apache.lucene.analysis.standard.StandardAnalyzer;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+
+import static com.gemstone.gemfire.cache.lucene.test.LuceneTestUtilities.*;
+import static com.gemstone.gemfire.test.dunit.Assert.*;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import java.util.stream.Collectors;
+
+@Category(DistributedTest.class)
+public class LuceneIndexCommandsDUnitTest extends CliCommandTestBase {
+
+  @Before
+  public void createJMXManager() {
+    disconnectAllFromDS();
+    setUpJmxManagerOnVm0ThenConnect(null);
+  }
+
+  @Test
+  public void listIndexShouldReturnExistingIndex() throws Exception {
+    final VM vm1 = Host.getHost(0).getVM(1);
+
+    createIndex(vm1);
+    CommandManager.getInstance().add(LuceneIndexCommands.class.newInstance());
+
+    CommandStringBuilder csb = new CommandStringBuilder(LuceneCliStrings.LUCENE_LIST_INDEX);
+    String resultAsString = executeCommandAndLogResult(csb);
+    assertTrue(resultAsString.contains(INDEX_NAME));
+  }
+
+  @Test
+  public void createIndexShouldCreateANewIndex() throws Exception {
+    final VM vm1 = Host.getHost(0).getVM(1);
+    vm1.invoke(() -> {getCache();});
+
+    CommandManager.getInstance().add(LuceneIndexCommands.class.newInstance());
+
+    CommandStringBuilder csb = new CommandStringBuilder(LuceneCliStrings.LUCENE_CREATE_INDEX);
+    csb.addOption(LuceneCliStrings.LUCENE_CREATE_INDEX__NAME,INDEX_NAME);
+    csb.addOption(LuceneCliStrings.LUCENE_CREATE_INDEX__REGION,REGION_NAME);
+    csb.addOption(LuceneCliStrings.LUCENE_CREATE_INDEX__FIELD,"field1,field2,field3");
+
+    String resultAsString = executeCommandAndLogResult(csb);
+
+    vm1.invoke(() -> {
+      LuceneService luceneService = LuceneServiceProvider.get(getCache());
+      createRegion();
+      final LuceneIndex index = luceneService.getIndex(INDEX_NAME, REGION_NAME);
+      assertArrayEquals(new String[] {"field1", "field2", "field3"}, index.getFieldNames());
+    });
+  }
+
+  @Test
+  public void createIndexWithAnalyzersShouldCreateANewIndex() throws Exception {
+    final VM vm1 = Host.getHost(0).getVM(1);
+    vm1.invoke(() -> {getCache();});
+
+    CommandManager.getInstance().add(LuceneIndexCommands.class.newInstance());
+
+    List<String> analyzerNames = new ArrayList<>();
+    analyzerNames.add(StandardAnalyzer.class.getCanonicalName());
+    analyzerNames.add(KeywordAnalyzer.class.getCanonicalName());
+    analyzerNames.add(StandardAnalyzer.class.getCanonicalName());
+
+
+    CommandStringBuilder csb = new CommandStringBuilder(LuceneCliStrings.LUCENE_CREATE_INDEX);
+    csb.addOption(LuceneCliStrings.LUCENE_CREATE_INDEX__NAME,INDEX_NAME);
+    csb.addOption(LuceneCliStrings.LUCENE_CREATE_INDEX__REGION,REGION_NAME);
+    csb.addOption(LuceneCliStrings.LUCENE_CREATE_INDEX__FIELD,"field1,field2,field3");
+    csb.addOption(LuceneCliStrings.LUCENE_CREATE_INDEX__ANALYZER,String.join(",",analyzerNames));
+
+    String resultAsString = executeCommandAndLogResult(csb);
+
+    vm1.invoke(() -> {
+      LuceneService luceneService = LuceneServiceProvider.get(getCache());
+      createRegion();
+      final LuceneIndex index = luceneService.getIndex(INDEX_NAME, REGION_NAME);
+      final Map<String, Analyzer> fieldAnalyzers = index.getFieldAnalyzers();
+      assertEquals(StandardAnalyzer.class, fieldAnalyzers.get("field1").getClass());
+      assertEquals(KeywordAnalyzer.class, fieldAnalyzers.get("field2").getClass());
+      assertEquals(StandardAnalyzer.class, fieldAnalyzers.get("field3").getClass());
+    });
+  }
+
+  @Test
+  public void createIndexOnGroupShouldCreateANewIndexOnGroup() throws Exception {
+    final VM vm1 = Host.getHost(0).getVM(1);
+    final VM vm2 = Host.getHost(0).getVM(2);
+    vm1.invoke(() -> {
+      getCache();
+    });
+    vm2.invoke(() -> {
+      Properties props = new Properties();
+      props.setProperty(ConfigurationProperties.GROUPS, "group1");
+      getSystem(props);
+      getCache();
+    });
+
+
+    CommandManager.getInstance().add(LuceneIndexCommands.class.newInstance());
+
+    CommandStringBuilder csb = new CommandStringBuilder(LuceneCliStrings.LUCENE_CREATE_INDEX);
+    csb.addOption(LuceneCliStrings.LUCENE_CREATE_INDEX__NAME,INDEX_NAME);
+    csb.addOption(LuceneCliStrings.LUCENE_CREATE_INDEX__REGION,REGION_NAME);
+    csb.addOption(LuceneCliStrings.LUCENE_CREATE_INDEX__FIELD,"field1,field2,field3");
+    csb.addOption(LuceneCliStrings.LUCENE_CREATE_INDEX__GROUP,"group1");
+    String resultAsString = executeCommandAndLogResult(csb);
+
+    vm2.invoke(() -> {
+      LuceneService luceneService = LuceneServiceProvider.get(getCache());
+      createRegion();
+      final LuceneIndex index = luceneService.getIndex(INDEX_NAME, REGION_NAME);
+      assertArrayEquals(new String[] {"field1", "field2", "field3"}, index.getFieldNames());
+    });
+
+    vm1.invoke(() -> {
+      LuceneService luceneService = LuceneServiceProvider.get(getCache());
+      try {
+        createRegion();
+        fail("Should have thrown an exception due to the missing index");
+      } catch(IllegalStateException expected) {
+
+      }
+    });
+  }
+
+  private void createRegion() {
+    getCache().createRegionFactory(RegionShortcut.PARTITION).create(REGION_NAME);
+  }
+
+  private String executeCommandAndLogResult(final CommandStringBuilder csb) {
+    String commandString = csb.toString();
+    writeToLog("Command String :\n ", commandString);
+    CommandResult commandResult = executeCommand(commandString);
+    String resultAsString = commandResultToString(commandResult);
+    writeToLog("Result String :\n ", resultAsString);
+    assertEquals("Command failed\n" + resultAsString, Status.OK, commandResult.getStatus());
+    return resultAsString;
+  }
+
+  private void createIndex(final VM vm1) {
+    vm1.invoke(() -> {
+      LuceneService luceneService = LuceneServiceProvider.get(getCache());
+      Map<String, Analyzer> fieldAnalyzers = new HashMap();
+      fieldAnalyzers.put("field1", new StandardAnalyzer());
+      fieldAnalyzers.put("field2", new KeywordAnalyzer());
+      fieldAnalyzers.put("field3", null);
+      luceneService.createIndex(INDEX_NAME, REGION_NAME, fieldAnalyzers);
+      createRegion();
+    });
+  }
+
+  private void writeToLog(String text, String resultAsString) {
+    System.out.println(text + ": " + getTestMethodName() + " : ");
+    System.out.println(text + ":" + resultAsString);
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/82adda1c/geode-lucene/src/test/java/com/gemstone/gemfire/cache/lucene/internal/cli/LuceneIndexCommandsJUnitTest.java
----------------------------------------------------------------------
diff --git a/geode-lucene/src/test/java/com/gemstone/gemfire/cache/lucene/internal/cli/LuceneIndexCommandsJUnitTest.java b/geode-lucene/src/test/java/com/gemstone/gemfire/cache/lucene/internal/cli/LuceneIndexCommandsJUnitTest.java
new file mode 100644
index 0000000..0ebfa10
--- /dev/null
+++ b/geode-lucene/src/test/java/com/gemstone/gemfire/cache/lucene/internal/cli/LuceneIndexCommandsJUnitTest.java
@@ -0,0 +1,185 @@
+/*
+ * 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 com.gemstone.gemfire.cache.lucene.internal.cli;
+import static com.gemstone.gemfire.internal.lang.StringUtils.trim;
+import static org.junit.Assert.*;
+import static org.mockito.Matchers.isA;
+import static org.mockito.Mockito.*;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.lucene.analysis.Analyzer;
+import org.apache.lucene.analysis.core.KeywordAnalyzer;
+import org.apache.lucene.analysis.standard.StandardAnalyzer;
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+
+import com.gemstone.gemfire.cache.Cache;
+import com.gemstone.gemfire.cache.execute.Execution;
+import com.gemstone.gemfire.cache.execute.ResultCollector;
+import com.gemstone.gemfire.cache.lucene.internal.cli.functions.LuceneListIndexFunction;
+import com.gemstone.gemfire.distributed.DistributedMember;
+import com.gemstone.gemfire.internal.cache.execute.AbstractExecution;
+import com.gemstone.gemfire.internal.util.CollectionUtils;
+import com.gemstone.gemfire.management.cli.Result;
+import com.gemstone.gemfire.management.cli.Result.Status;
+import com.gemstone.gemfire.management.internal.cli.functions.CliFunctionResult;
+import com.gemstone.gemfire.management.internal.cli.i18n.CliStrings;
+import com.gemstone.gemfire.management.internal.cli.result.CommandResult;
+import com.gemstone.gemfire.management.internal.cli.result.CommandResultException;
+import com.gemstone.gemfire.management.internal.cli.result.InfoResultData;
+import com.gemstone.gemfire.management.internal.cli.result.ResultBuilder;
+import com.gemstone.gemfire.management.internal.cli.result.TabularResultData;
+import com.gemstone.gemfire.test.junit.categories.UnitTest;
+
+/**
+ * The LuceneIndexCommandsJUnitTest class is a test suite of test cases testing the contract and functionality of the
+ * LuceneIndexCommands class.
+ * </p>
+ * @see LuceneIndexCommands
+ * @see LuceneIndexDetails
+ * @see com.gemstone.gemfire.cache.lucene.internal.cli.functions.LuceneListIndexFunction
+ * @see org.jmock.Expectations
+ * @see org.jmock.Mockery
+ * @see org.jmock.lib.legacy.ClassImposteriser
+ * @see org.junit.Assert
+ * @see org.junit.Test
+ * @since GemFire 7.0
+ */
+@Category(UnitTest.class)
+public class LuceneIndexCommandsJUnitTest {
+
+  private LuceneIndexCommands createIndexCommands(final Cache cache, final Execution functionExecutor) {
+    return new LuceneTestIndexCommands(cache, functionExecutor);
+  }
+
+  private LuceneIndexDetails createIndexDetails(final String indexName, final String regionPath, final String[] searchableFields, final Map<String, Analyzer> fieldAnalyzers) {
+    return new LuceneIndexDetails(indexName, regionPath, searchableFields, fieldAnalyzers);
+  }
+
+  @Test
+  public void testListIndex() {
+
+    final Cache mockCache = mock(Cache.class, "Cache");
+    final AbstractExecution mockFunctionExecutor = mock(AbstractExecution.class, "Function Executor");
+    final ResultCollector mockResultCollector = mock(ResultCollector.class, "ResultCollector");
+
+    String[] searchableFields={"field1","field2","field3"};
+    Map<String, Analyzer> fieldAnalyzers = new HashMap<>();
+    fieldAnalyzers.put("field1", new StandardAnalyzer());
+    fieldAnalyzers.put("field2", new KeywordAnalyzer());
+    fieldAnalyzers.put("field3", null);
+    final LuceneIndexDetails indexDetails1 = createIndexDetails("memberFive", "/Employees", searchableFields, fieldAnalyzers);
+    final LuceneIndexDetails indexDetails2 = createIndexDetails("memberSix", "/Employees", searchableFields, fieldAnalyzers);
+    final LuceneIndexDetails indexDetails3 = createIndexDetails("memberTen", "/Employees", searchableFields, fieldAnalyzers);
+
+
+    final List<LuceneIndexDetails> expectedIndexDetails = new ArrayList<>(3);
+    expectedIndexDetails.add(indexDetails1);
+    expectedIndexDetails.add(indexDetails2);
+    expectedIndexDetails.add(indexDetails3);
+
+    final List<Set<LuceneIndexDetails>> results = new ArrayList<Set<LuceneIndexDetails>>();
+
+    results.add(CollectionUtils.asSet(indexDetails2, indexDetails1,indexDetails3));
+
+
+    when(mockFunctionExecutor.execute(isA(LuceneListIndexFunction.class)))
+      .thenReturn(mockResultCollector);
+    when(mockResultCollector.getResult())
+      .thenReturn(results);
+
+    final LuceneIndexCommands commands = createIndexCommands(mockCache, mockFunctionExecutor);
+
+    CommandResult result = (CommandResult) commands.listIndex();
+    TabularResultData data = (TabularResultData) result.getResultData();
+    assertEquals(Arrays.asList("memberFive", "memberSix", "memberTen"), data.retrieveAllValues("Index Name"));
+    assertEquals(Arrays.asList("/Employees", "/Employees", "/Employees"), data.retrieveAllValues("Region Path"));
+    assertEquals(Arrays.asList("[field1, field2, field3]", "[field1, field2, field3]", "[field1, field2, field3]"), data.retrieveAllValues("Indexed Fields"));
+    assertEquals(Arrays.asList("{field1=StandardAnalyzer, field2=KeywordAnalyzer}", "{field1=StandardAnalyzer, field2=KeywordAnalyzer}", "{field1=StandardAnalyzer, field2=KeywordAnalyzer}"), data.retrieveAllValues("Field Analyzer"));
+  }
+
+  @Test
+  public void testCreateIndex() throws CommandResultException {
+    final Cache mockCache=mock(Cache.class);
+    final ResultCollector mockResultCollector = mock(ResultCollector.class);
+    final LuceneIndexCommands commands=spy(createIndexCommands(mockCache,null));
+    final String memberId="member1";
+    final List<CliFunctionResult> cliFunctionResults=new ArrayList<>();
+    cliFunctionResults.add(new CliFunctionResult(memberId,true,"Index Created"));
+
+    doReturn(mockResultCollector).when(commands).createIndexOnGroups(any(),any(LuceneIndexInfo.class));
+    doReturn(cliFunctionResults).when(mockResultCollector).getResult();
+
+    String indexName ="index";
+    String regionPath="regionPath";
+    String[] searchableFields={"field1","field2","field3"};
+    String[] fieldAnalyzers = { StandardAnalyzer.class.getCanonicalName(), KeywordAnalyzer.class.getCanonicalName(), StandardAnalyzer.class.getCanonicalName()};
+
+    Result actualResult=commands.createIndex(indexName,regionPath,searchableFields,fieldAnalyzers,null);
+    Result expectedResult = buildResult(indexName, regionPath, memberId);
+    assertEquals(Status.OK,actualResult.getStatus());
+    assertEquals(expectedResult,actualResult);
+  }
+
+  private Result buildResult(final String indexName, final String regionPath, final String memberId) {
+    final InfoResultData infoResult = ResultBuilder.createInfoResultData();
+    infoResult.addLine(LuceneCliStrings.CREATE_INDEX__SUCCESS__MSG);
+    infoResult.addLine(CliStrings.format(LuceneCliStrings.CREATE_INDEX__NAME__MSG, indexName));
+    infoResult.addLine(CliStrings.format(LuceneCliStrings.CREATE_INDEX__REGIONPATH__MSG, regionPath));
+    infoResult.addLine(LuceneCliStrings.CREATE_INDEX__MEMBER__MSG);
+    infoResult.addLine(CliStrings.format(LuceneCliStrings.CREATE_INDEX__NUMBER__AND__MEMBER, 1 , memberId));
+    return ResultBuilder.buildResult(infoResult);
+  }
+
+  private static class LuceneTestIndexCommands extends LuceneIndexCommands {
+
+    private final Cache cache;
+    private final Execution functionExecutor;
+
+    protected LuceneTestIndexCommands(final Cache cache, final Execution functionExecutor) {
+      assert cache != null : "The Cache cannot be null!";
+      this.cache = cache;
+      this.functionExecutor = functionExecutor;
+    }
+
+    @Override
+    protected Cache getCache() {
+      return this.cache;
+    }
+
+    @Override
+    protected Set<DistributedMember> getMembers(final Cache cache) {
+      assertSame(getCache(), cache);
+      return Collections.emptySet();
+    }
+
+    @Override
+    protected Execution getMembersFunctionExecutor(final Set<DistributedMember> members) {
+      Assert.assertNotNull(members);
+      return functionExecutor;
+    }
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/82adda1c/geode-lucene/src/test/java/com/gemstone/gemfire/cache/lucene/internal/cli/functions/LuceneCreateIndexFunctionJUnitTest.java
----------------------------------------------------------------------
diff --git a/geode-lucene/src/test/java/com/gemstone/gemfire/cache/lucene/internal/cli/functions/LuceneCreateIndexFunctionJUnitTest.java b/geode-lucene/src/test/java/com/gemstone/gemfire/cache/lucene/internal/cli/functions/LuceneCreateIndexFunctionJUnitTest.java
new file mode 100644
index 0000000..b81cad7
--- /dev/null
+++ b/geode-lucene/src/test/java/com/gemstone/gemfire/cache/lucene/internal/cli/functions/LuceneCreateIndexFunctionJUnitTest.java
@@ -0,0 +1,126 @@
+/*
+ * 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 com.gemstone.gemfire.cache.lucene.internal.cli.functions;
+
+import static org.junit.Assert.*;
+import static org.mockito.Mockito.*;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.lucene.analysis.Analyzer;
+import org.apache.lucene.analysis.core.KeywordAnalyzer;
+import org.apache.lucene.analysis.standard.StandardAnalyzer;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+import org.mockito.ArgumentCaptor;
+import com.gemstone.gemfire.cache.execute.FunctionContext;
+import com.gemstone.gemfire.cache.execute.ResultSender;
+import com.gemstone.gemfire.cache.lucene.internal.InternalLuceneService;
+import com.gemstone.gemfire.cache.lucene.internal.cli.LuceneIndexInfo;
+import com.gemstone.gemfire.distributed.DistributedSystem;
+import com.gemstone.gemfire.internal.cache.GemFireCacheImpl;
+import com.gemstone.gemfire.management.internal.cli.functions.CliFunctionResult;
+import com.gemstone.gemfire.management.internal.configuration.domain.XmlEntity;
+import com.gemstone.gemfire.test.fake.Fakes;
+import com.gemstone.gemfire.test.junit.categories.UnitTest;
+
+@Category(UnitTest.class)
+
+public class LuceneCreateIndexFunctionJUnitTest {
+  
+  private InternalLuceneService service;
+  private GemFireCacheImpl cache;
+  String member;
+  FunctionContext context;
+  ResultSender resultSender;
+  CliFunctionResult expectedResult;
+  
+  @Before
+  public void prepare() {
+    cache = Fakes.cache();
+    DistributedSystem ds = Fakes.distributedSystem();
+    member = ds.getDistributedMember().getId();
+    service = mock(InternalLuceneService.class);
+    when(cache.getService(InternalLuceneService.class)).thenReturn(service);
+    doNothing().when(service).createIndex(anyString(), anyString(), anyMap());
+    
+    context = mock(FunctionContext.class);
+    resultSender = mock(ResultSender.class);
+    when(context.getResultSender()).thenReturn(resultSender);
+
+    XmlEntity xmlEntity = null;
+    expectedResult = new CliFunctionResult(member, xmlEntity);
+  }
+
+  @Test
+  @SuppressWarnings("unchecked")
+  public void testExecuteWithAnalyzer() throws Throwable {
+    List<String> analyzerNames = new ArrayList<>();
+    analyzerNames.add(StandardAnalyzer.class.getCanonicalName());
+    analyzerNames.add(KeywordAnalyzer.class.getCanonicalName());
+    analyzerNames.add(StandardAnalyzer.class.getCanonicalName());
+    String [] analyzers = new String[3];
+    analyzerNames.toArray(analyzers);
+    LuceneIndexInfo indexInfo = new LuceneIndexInfo("index1", "/region1", 
+        new String[] {"field1", "field2", "field3"}, analyzers);
+    when(context.getArguments()).thenReturn(indexInfo);
+
+    LuceneCreateIndexFunction function = new LuceneCreateIndexFunction();
+    function = spy(function);
+    doReturn(cache).when(function).getCache();
+    function.execute(context);
+    
+    ArgumentCaptor<Map> analyzersCaptor = ArgumentCaptor.forClass(Map.class);
+    verify(service).createIndex(eq("index1"), eq("/region1"), analyzersCaptor.capture());
+    Map<String, Analyzer> analyzerPerField = analyzersCaptor.getValue();
+    assertEquals(3, analyzerPerField.size());
+    assertTrue(analyzerPerField.get("field1") instanceof StandardAnalyzer);
+    assertTrue(analyzerPerField.get("field2") instanceof KeywordAnalyzer);
+    assertTrue(analyzerPerField.get("field3") instanceof StandardAnalyzer);
+    
+    ArgumentCaptor<Set> resultCaptor  = ArgumentCaptor.forClass(Set.class);
+    verify(resultSender).lastResult(resultCaptor.capture());
+    CliFunctionResult result = (CliFunctionResult)resultCaptor.getValue();
+
+    assertEquals(expectedResult, result);
+  }
+
+  @Test
+  @SuppressWarnings("unchecked")
+  public void testExecuteWithoutAnalyzer() throws Throwable {
+    String fields[] = new String[] {"field1", "field2", "field3"};
+    LuceneIndexInfo indexInfo = new LuceneIndexInfo("index1", "/region1", fields, null);
+    when(context.getArguments()).thenReturn(indexInfo);
+
+    LuceneCreateIndexFunction function = new LuceneCreateIndexFunction();
+    function = spy(function);
+    doReturn(cache).when(function).getCache();
+    function.execute(context);
+    
+    verify(service).createIndex(eq("index1"), eq("/region1"), eq("field1"), eq("field2"), eq("field3"));
+
+    ArgumentCaptor<Set> resultCaptor  = ArgumentCaptor.forClass(Set.class);
+    verify(resultSender).lastResult(resultCaptor.capture());
+    CliFunctionResult result = (CliFunctionResult)resultCaptor.getValue();
+
+    assertEquals(expectedResult, result);
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/82adda1c/geode-lucene/src/test/java/com/gemstone/gemfire/cache/lucene/internal/cli/functions/LuceneListIndexFunctionJUnitTest.java
----------------------------------------------------------------------
diff --git a/geode-lucene/src/test/java/com/gemstone/gemfire/cache/lucene/internal/cli/functions/LuceneListIndexFunctionJUnitTest.java b/geode-lucene/src/test/java/com/gemstone/gemfire/cache/lucene/internal/cli/functions/LuceneListIndexFunctionJUnitTest.java
new file mode 100644
index 0000000..cb22cf8
--- /dev/null
+++ b/geode-lucene/src/test/java/com/gemstone/gemfire/cache/lucene/internal/cli/functions/LuceneListIndexFunctionJUnitTest.java
@@ -0,0 +1,102 @@
+/*
+ * 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 com.gemstone.gemfire.cache.lucene.internal.cli.functions;
+
+import static org.junit.Assert.*;
+import static org.mockito.Mockito.*;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeSet;
+
+import org.apache.lucene.analysis.Analyzer;
+import org.apache.lucene.analysis.core.KeywordAnalyzer;
+import org.apache.lucene.analysis.standard.StandardAnalyzer;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mockito;
+
+import com.gemstone.gemfire.cache.execute.FunctionContext;
+import com.gemstone.gemfire.cache.execute.ResultSender;
+import com.gemstone.gemfire.cache.lucene.LuceneIndex;
+import com.gemstone.gemfire.cache.lucene.internal.InternalLuceneService;
+import com.gemstone.gemfire.cache.lucene.internal.LuceneIndexImpl;
+import com.gemstone.gemfire.cache.lucene.internal.cli.LuceneIndexDetails;
+import com.gemstone.gemfire.internal.cache.GemFireCacheImpl;
+import com.gemstone.gemfire.test.fake.Fakes;
+import com.gemstone.gemfire.test.junit.categories.UnitTest;
+
+@Category(UnitTest.class)
+
+public class LuceneListIndexFunctionJUnitTest {
+  
+  @Test
+  @SuppressWarnings("unchecked")
+  public void testExecute() throws Throwable {
+    GemFireCacheImpl cache = Fakes.cache();
+    InternalLuceneService service = mock(InternalLuceneService.class);
+    when(cache.getService(InternalLuceneService.class)).thenReturn(service);
+    
+    FunctionContext context = mock(FunctionContext.class);
+    ResultSender resultSender = mock(ResultSender.class);
+    when(context.getResultSender()).thenReturn(resultSender);
+
+    LuceneIndexImpl index1 = getMockLuceneIndex("index1");
+    LuceneIndexImpl index2 = getMockLuceneIndex("index2");
+
+    TreeSet expectedResult = new TreeSet();
+    expectedResult.add(new LuceneIndexDetails(index1));
+    expectedResult.add(new LuceneIndexDetails(index2));
+
+    ArrayList<LuceneIndex> allIndexes = new ArrayList();
+    allIndexes.add(index1);
+    allIndexes.add(index2);
+    when(service.getAllIndexes()).thenReturn(allIndexes);
+    
+    LuceneListIndexFunction function = new LuceneListIndexFunction();
+    function = spy(function);
+    Mockito.doReturn(cache).when(function).getCache();
+    function.execute(context);
+    
+    ArgumentCaptor<Set> resultCaptor  = ArgumentCaptor.forClass(Set.class);
+    verify(resultSender).lastResult(resultCaptor.capture());
+    Set<String> result = resultCaptor.getValue();
+
+    assertEquals(2, result.size());
+    assertEquals(expectedResult, result);
+  }
+
+  private LuceneIndexImpl getMockLuceneIndex(final String indexName)
+  {
+    String[] searchableFields={"field1","field2"};
+    Map<String, Analyzer> fieldAnalyzers = new HashMap<>();
+    fieldAnalyzers.put("field1", new StandardAnalyzer());
+    fieldAnalyzers.put("field2", new KeywordAnalyzer());
+
+    LuceneIndexImpl index = mock(LuceneIndexImpl.class);
+    when(index.getName()).thenReturn(indexName);
+    when(index.getRegionPath()).thenReturn("/region");
+    when(index.getFieldNames()).thenReturn(searchableFields);
+    when(index.getFieldAnalyzers()).thenReturn(fieldAnalyzers);
+    return index;
+  }
+
+}


Mime
View raw message