You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@geode.apache.org by je...@apache.org on 2018/03/05 17:00:09 UTC

[geode] branch develop updated: GEODE-4385: Add list jndi-binding option (#1547)

This is an automated email from the ASF dual-hosted git repository.

jensdeppe pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/geode.git


The following commit(s) were added to refs/heads/develop by this push:
     new a281d54  GEODE-4385: Add list jndi-binding option (#1547)
a281d54 is described below

commit a281d54f2777b31178d47829e3ba282578d8cf4b
Author: Jens Deppe <jd...@pivotal.io>
AuthorDate: Mon Mar 5 09:00:02 2018 -0800

    GEODE-4385: Add list jndi-binding option (#1547)
---
 .../apache/geode/internal/jndi/JNDIInvoker.java    | 21 ++++++
 .../cli/commands/ListJndiBindingCommand.java       | 65 ++++++++++++++++
 .../cli/functions/ListJndiBindingFunction.java     | 58 +++++++++++++++
 .../sanctioned-geode-core-serializables.txt        |  3 +-
 .../commands/ListJndiBindingCommandDUnitTest.java  | 69 +++++++++++++++++
 .../functions/CreateJndiBindingFunctionTest.java   | 87 ++++++++++++++++++++++
 .../cli/functions/ListJndiBindingFunctionTest.java | 83 +++++++++++++++++++++
 7 files changed, 385 insertions(+), 1 deletion(-)

diff --git a/geode-core/src/main/java/org/apache/geode/internal/jndi/JNDIInvoker.java b/geode-core/src/main/java/org/apache/geode/internal/jndi/JNDIInvoker.java
index 99898c5..f439047 100644
--- a/geode-core/src/main/java/org/apache/geode/internal/jndi/JNDIInvoker.java
+++ b/geode-core/src/main/java/org/apache/geode/internal/jndi/JNDIInvoker.java
@@ -16,6 +16,7 @@ package org.apache.geode.internal.jndi;
 
 import java.lang.reflect.Method;
 import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.Hashtable;
 import java.util.List;
 import java.util.Map;
@@ -379,4 +380,24 @@ public class JNDIInvoker {
   public static int getNoOfAvailableDataSources() {
     return dataSourceList.size();
   }
+
+  public static Map<String, String> getBindingNamesRecursively(Context ctx) throws Exception {
+    Map<String, String> result = new HashMap<>();
+    NamingEnumeration<Binding> enumeration = ctx.listBindings("");
+
+    while (enumeration.hasMore()) {
+      Binding binding = enumeration.next();
+      String name = binding.getName();
+      String separator = name.endsWith(":") ? "" : "/";
+      Object o = binding.getObject();
+      if (o instanceof Context) {
+        Map<String, String> innerBindings = getBindingNamesRecursively((Context) o);
+        innerBindings.forEach((k, v) -> result.put(name + separator + k, v));
+      } else {
+        result.put(name, binding.getClassName());
+      }
+    }
+
+    return result;
+  }
 }
diff --git a/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/ListJndiBindingCommand.java b/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/ListJndiBindingCommand.java
new file mode 100644
index 0000000..2634afb
--- /dev/null
+++ b/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/ListJndiBindingCommand.java
@@ -0,0 +1,65 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more contributor license
+ * agreements. See the NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the License. You may obtain a
+ * copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package org.apache.geode.management.internal.cli.commands;
+
+import java.io.Serializable;
+import java.util.List;
+import java.util.Set;
+
+import org.apache.logging.log4j.Logger;
+import org.springframework.shell.core.annotation.CliCommand;
+
+import org.apache.geode.cache.execute.Function;
+import org.apache.geode.distributed.DistributedMember;
+import org.apache.geode.internal.logging.LogService;
+import org.apache.geode.management.cli.Result;
+import org.apache.geode.management.internal.cli.functions.CliFunctionResult;
+import org.apache.geode.management.internal.cli.functions.ListJndiBindingFunction;
+import org.apache.geode.management.internal.cli.result.ResultBuilder;
+import org.apache.geode.management.internal.cli.result.TabularResultData;
+
+public class ListJndiBindingCommand implements GfshCommand {
+  private static final Logger logger = LogService.getLogger();
+
+  private static final String LIST_JNDIBINDING = "list jndi-binding";
+  private static final String LIST_JNDIBINDING__HELP = "List all jndi bindings.";
+  private static final Function LIST_BINDING_FUNCTION = new ListJndiBindingFunction();
+
+  @CliCommand(value = LIST_JNDIBINDING, help = LIST_JNDIBINDING__HELP)
+  public Result listJndiBinding() {
+    Result result = null;
+    TabularResultData tabularData = ResultBuilder.createTabularResultData();
+
+    Set<DistributedMember> members = findMembers(null, null);
+    if (members.size() == 0) {
+      return ResultBuilder.createUserErrorResult("No members found");
+    }
+
+    List<CliFunctionResult> rc = executeAndGetFunctionResult(LIST_BINDING_FUNCTION, null, members);
+    for (CliFunctionResult oneResult : rc) {
+      Serializable[] serializables = oneResult.getSerializables();
+      for (int i = 0; i < serializables.length; i += 2) {
+        tabularData.accumulate("Member", oneResult.getMemberIdOrName());
+        tabularData.accumulate("Name", serializables[i]);
+        tabularData.accumulate("Class", serializables[i + 1]);
+      }
+    }
+
+    result = ResultBuilder.buildResult(tabularData);
+
+    return result;
+  }
+}
diff --git a/geode-core/src/main/java/org/apache/geode/management/internal/cli/functions/ListJndiBindingFunction.java b/geode-core/src/main/java/org/apache/geode/management/internal/cli/functions/ListJndiBindingFunction.java
new file mode 100644
index 0000000..1f17ff4
--- /dev/null
+++ b/geode-core/src/main/java/org/apache/geode/management/internal/cli/functions/ListJndiBindingFunction.java
@@ -0,0 +1,58 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more contributor license
+ * agreements. See the NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the License. You may obtain a
+ * copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package org.apache.geode.management.internal.cli.functions;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+import javax.naming.Context;
+import javax.naming.NameClassPair;
+
+import org.apache.geode.cache.execute.FunctionContext;
+import org.apache.geode.cache.execute.ResultSender;
+import org.apache.geode.internal.cache.execute.InternalFunction;
+import org.apache.geode.internal.jndi.JNDIInvoker;
+
+public class ListJndiBindingFunction implements InternalFunction {
+
+  private static final long serialVersionUID = 5254506785395069200L;
+
+  @Override
+  public void execute(FunctionContext context) {
+    List<NameClassPair> namePairs = new ArrayList<>();
+    CliFunctionResult result;
+
+    try {
+      Context ctx = JNDIInvoker.getJNDIContext();
+      Map<String, String> bindings = JNDIInvoker.getBindingNamesRecursively(ctx);
+      List<String> resultValues = bindings.entrySet().stream()
+          .flatMap((e) -> Arrays.stream(new String[] {e.getKey(), e.getValue()}))
+          .collect(Collectors.toList());
+      result = new CliFunctionResult(context.getMemberName(),
+          resultValues.toArray(new Serializable[] {}));
+    } catch (Exception e) {
+      result =
+          new CliFunctionResult(context.getMemberName(), e, "Unable to retrieve JNDI bindings");
+    }
+
+    ResultSender<Object> sender = context.getResultSender();
+    sender.lastResult(result);
+  }
+}
diff --git a/geode-core/src/main/resources/org/apache/geode/internal/sanctioned-geode-core-serializables.txt b/geode-core/src/main/resources/org/apache/geode/internal/sanctioned-geode-core-serializables.txt
index e7e00b2..16ab501 100644
--- a/geode-core/src/main/resources/org/apache/geode/internal/sanctioned-geode-core-serializables.txt
+++ b/geode-core/src/main/resources/org/apache/geode/internal/sanctioned-geode-core-serializables.txt
@@ -552,6 +552,7 @@ org/apache/geode/management/internal/cli/functions/ListDiskStoresFunction,false
 org/apache/geode/management/internal/cli/functions/ListDurableCqNamesFunction,true,1
 org/apache/geode/management/internal/cli/functions/ListFunctionFunction,true,1
 org/apache/geode/management/internal/cli/functions/ListIndexFunction,false
+org/apache/geode/management/internal/cli/functions/ListJndiBindingFunction,true,5254506785395069200
 org/apache/geode/management/internal/cli/functions/NetstatFunction,true,1
 org/apache/geode/management/internal/cli/functions/NetstatFunction$NetstatFunctionArgument,true,1,lineSeparator:java/lang/String,withlsof:boolean
 org/apache/geode/management/internal/cli/functions/NetstatFunction$NetstatFunctionResult,true,1,compressedBytes:org/apache/geode/management/internal/cli/CliUtil$DeflaterInflaterData,headerInfo:java/lang/String,host:java/lang/String
@@ -586,10 +587,10 @@ org/apache/geode/management/internal/cli/util/LogFilter$LineFilterResult,false
 org/apache/geode/management/internal/cli/util/MemberInformation,true,1,cacheXmlFilePath:java/lang/String,cpuUsage:java/lang/String,groups:java/lang/String,heapUsage:java/lang/String,host:java/lang/String,id:java/lang/String,initHeapSize:java/lang/String,locatorBindAddress:java/lang/String,locatorPort:int,locators:java/lang/String,logFilePath:java/lang/String,maxHeapSize:java/lang/String,name:java/lang/String,processId:java/lang/String,serverBindAddress:java/lang/String,statArchiveFilePat [...]
 org/apache/geode/management/internal/cli/util/VisualVmNotFoundException,true,-8491645604829510102
 org/apache/geode/management/internal/configuration/domain/SharedConfigurationStatus,false
+org/apache/geode/management/internal/configuration/functions/DownloadJarFunction,true,1
 org/apache/geode/management/internal/configuration/functions/GetClusterConfigurationFunction,false
 org/apache/geode/management/internal/configuration/functions/GetRegionNamesFunction,false
 org/apache/geode/management/internal/configuration/functions/RecreateCacheFunction,false
-org/apache/geode/management/internal/configuration/functions/DownloadJarFunction,true,1
 org/apache/geode/management/internal/web/domain/QueryParameterSource,true,34131123582155,objectName:javax/management/ObjectName,queryExpression:javax/management/QueryExp
 org/apache/geode/management/internal/web/shell/MBeanAccessException,true,813768898269516238
 org/apache/geode/memcached/GemFireMemcachedServer$Protocol,false
diff --git a/geode-core/src/test/java/org/apache/geode/management/internal/cli/commands/ListJndiBindingCommandDUnitTest.java b/geode-core/src/test/java/org/apache/geode/management/internal/cli/commands/ListJndiBindingCommandDUnitTest.java
new file mode 100644
index 0000000..36ae73e
--- /dev/null
+++ b/geode-core/src/test/java/org/apache/geode/management/internal/cli/commands/ListJndiBindingCommandDUnitTest.java
@@ -0,0 +1,69 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more contributor license
+ * agreements. See the NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the License. You may obtain a
+ * copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package org.apache.geode.management.internal.cli.commands;
+
+import java.util.Properties;
+
+import org.junit.BeforeClass;
+import org.junit.ClassRule;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+
+import org.apache.geode.distributed.ConfigurationProperties;
+import org.apache.geode.management.internal.cli.functions.ListJndiBindingFunction;
+import org.apache.geode.test.dunit.rules.ClusterStartupRule;
+import org.apache.geode.test.dunit.rules.MemberVM;
+import org.apache.geode.test.junit.categories.DistributedTest;
+import org.apache.geode.test.junit.rules.GfshCommandRule;
+
+@Category(DistributedTest.class)
+public class ListJndiBindingCommandDUnitTest {
+
+  private static MemberVM locator, server;
+
+  @ClassRule
+  public static ClusterStartupRule cluster = new ClusterStartupRule();
+
+  @ClassRule
+  public static GfshCommandRule gfsh = new GfshCommandRule();
+
+  @BeforeClass
+  public static void before() throws Exception {
+    Properties props = new Properties();
+    props.setProperty(ConfigurationProperties.SERIALIZABLE_OBJECT_FILTER,
+        ListJndiBindingFunction.class.getName());
+
+    locator = cluster.startLocatorVM(0);
+    server = cluster.startServerVM(1, props, locator.getPort());
+
+    gfsh.connectAndVerify(locator);
+  }
+
+  @Test
+  public void listJndiBinding() {
+    gfsh.executeAndAssertThat(
+        "create jndi-binding --name=jndi1 --type=SIMPLE --jdbc-driver-class=org.apache.derby.jdbc.EmbeddedDriver --connection-url=\"jdbc:derby:newDB;create=true\"")
+        .statusIsSuccess().tableHasColumnOnlyWithValues("Member", "server-1");
+
+    gfsh.executeAndAssertThat("list jndi-binding").statusIsSuccess()
+        .tableHasColumnWithExactValuesInAnyOrder("Name", "java:jndi1", "java:UserTransaction",
+            "java:TransactionManager")
+        .tableHasColumnWithExactValuesInAnyOrder("Class",
+            "org.apache.geode.internal.datasource.GemFireBasicDataSource",
+            "org.apache.geode.internal.jta.UserTransactionImpl",
+            "org.apache.geode.internal.jta.TransactionManagerImpl");
+  }
+}
diff --git a/geode-core/src/test/java/org/apache/geode/management/internal/cli/functions/CreateJndiBindingFunctionTest.java b/geode-core/src/test/java/org/apache/geode/management/internal/cli/functions/CreateJndiBindingFunctionTest.java
new file mode 100644
index 0000000..4679e56
--- /dev/null
+++ b/geode-core/src/test/java/org/apache/geode/management/internal/cli/functions/CreateJndiBindingFunctionTest.java
@@ -0,0 +1,87 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more contributor license
+ * agreements. See the NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the License. You may obtain a
+ * copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package org.apache.geode.management.internal.cli.functions;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import java.util.Map;
+import java.util.logging.Level;
+
+import javax.naming.Context;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+import org.mockito.ArgumentCaptor;
+
+import org.apache.geode.cache.execute.FunctionContext;
+import org.apache.geode.cache.execute.ResultSender;
+import org.apache.geode.distributed.DistributedSystem;
+import org.apache.geode.internal.jndi.JNDIInvoker;
+import org.apache.geode.internal.logging.LocalLogWriter;
+import org.apache.geode.test.junit.categories.IntegrationTest;
+
+@Category(IntegrationTest.class)
+public class CreateJndiBindingFunctionTest {
+
+  private CreateJndiBindingFunction createBindingFunction;
+  private FunctionContext<JndiBindingConfiguration> context;
+  private DistributedSystem distributedSystem;
+  private ResultSender resultSender;
+  private ArgumentCaptor<CliFunctionResult> resultCaptor;
+
+  @Before
+  public void setup() {
+    createBindingFunction = spy(new CreateJndiBindingFunction());
+    context = mock(FunctionContext.class);
+    distributedSystem = mock(DistributedSystem.class);
+    resultSender = mock(ResultSender.class);
+    resultCaptor = ArgumentCaptor.forClass(CliFunctionResult.class);
+
+    when(distributedSystem.getLogWriter()).thenReturn(new LocalLogWriter(Level.FINE.intValue()));
+
+    JNDIInvoker.mapTransactions(distributedSystem);
+  }
+
+  @Test
+  public void createJndiBindingIsSuccessful() throws Exception {
+    JndiBindingConfiguration config = new JndiBindingConfiguration();
+    config.setJndiName("jndi1");
+    config.setType(JndiBindingConfiguration.DATASOURCE_TYPE.SIMPLE);
+    config.setJdbcDriver("org.apache.derby.jdbc.EmbeddedDriver");
+    config.setConnectionUrl("jdbc:derby:newDB;create=true");
+    when(context.getArguments()).thenReturn(config);
+    when(context.getMemberName()).thenReturn("mock-member");
+    when(context.getResultSender()).thenReturn(resultSender);
+
+    createBindingFunction.execute(context);
+
+    verify(resultSender).lastResult(resultCaptor.capture());
+    CliFunctionResult result = resultCaptor.getValue();
+    assertThat(result.isSuccessful()).isTrue();
+
+    Context ctx = JNDIInvoker.getJNDIContext();
+    Map<String, String> bindings = JNDIInvoker.getBindingNamesRecursively(ctx);
+
+    assertThat(bindings.keySet()).containsExactlyInAnyOrder("java:jndi1", "java:UserTransaction",
+        "java:TransactionManager");
+  }
+
+}
diff --git a/geode-core/src/test/java/org/apache/geode/management/internal/cli/functions/ListJndiBindingFunctionTest.java b/geode-core/src/test/java/org/apache/geode/management/internal/cli/functions/ListJndiBindingFunctionTest.java
new file mode 100644
index 0000000..4a13fd8
--- /dev/null
+++ b/geode-core/src/test/java/org/apache/geode/management/internal/cli/functions/ListJndiBindingFunctionTest.java
@@ -0,0 +1,83 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more contributor license
+ * agreements. See the NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the License. You may obtain a
+ * copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package org.apache.geode.management.internal.cli.functions;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import java.util.logging.Level;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+import org.mockito.ArgumentCaptor;
+
+import org.apache.geode.cache.execute.FunctionContext;
+import org.apache.geode.cache.execute.ResultSender;
+import org.apache.geode.distributed.DistributedSystem;
+import org.apache.geode.internal.jndi.JNDIInvoker;
+import org.apache.geode.internal.logging.LocalLogWriter;
+import org.apache.geode.test.junit.categories.IntegrationTest;
+
+@Category(IntegrationTest.class)
+public class ListJndiBindingFunctionTest {
+
+  private ListJndiBindingFunction listJndiBindingFunction;
+  private FunctionContext context;
+  private DistributedSystem distributedSystem;
+  private ResultSender resultSender;
+  private ArgumentCaptor<CliFunctionResult> resultCaptor;
+
+  @Before
+  public void setup() {
+    listJndiBindingFunction = spy(new ListJndiBindingFunction());
+    context = mock(FunctionContext.class);
+    distributedSystem = mock(DistributedSystem.class);
+    resultSender = mock(ResultSender.class);
+    resultCaptor = ArgumentCaptor.forClass(CliFunctionResult.class);
+
+    when(distributedSystem.getLogWriter()).thenReturn(new LocalLogWriter(Level.FINE.intValue()));
+
+    JNDIInvoker.mapTransactions(distributedSystem);
+
+    JndiBindingConfiguration config = new JndiBindingConfiguration();
+    config.setJndiName("jndi1");
+    config.setType(JndiBindingConfiguration.DATASOURCE_TYPE.SIMPLE);
+    config.setJdbcDriver("org.apache.derby.jdbc.EmbeddedDriver");
+    config.setConnectionUrl("jdbc:derby:newDB;create=true");
+    JNDIInvoker.mapDatasource(config.getParamsAsMap(), config.getDatasourceConfigurations());
+  }
+
+  @Test
+  public void listJndiBindingIsSuccessful() throws Exception {
+    when(context.getResultSender()).thenReturn(resultSender);
+
+    listJndiBindingFunction.execute(context);
+
+    verify(resultSender).lastResult(resultCaptor.capture());
+    CliFunctionResult result = resultCaptor.getValue();
+
+    assertThat(result.isSuccessful()).isTrue();
+    assertThat(result.getSerializables()).containsExactlyInAnyOrder("java:UserTransaction",
+        "org.apache.geode.internal.jta.UserTransactionImpl", "java:TransactionManager",
+        "org.apache.geode.internal.jta.TransactionManagerImpl", "java:jndi1",
+        "org.apache.geode.internal.datasource.GemFireBasicDataSource");
+  }
+
+}

-- 
To stop receiving notification emails like this one, please contact
jensdeppe@apache.org.