You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@geode.apache.org by dh...@apache.org on 2020/04/13 21:54:03 UTC
[geode] branch develop updated: GEODE-7851: Pulse Oauth Support
(#4936)
This is an automated email from the ASF dual-hosted git repository.
dhemery 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 3f9d32d GEODE-7851: Pulse Oauth Support (#4936)
3f9d32d is described below
commit 3f9d32d571a62dfd1b53789c6fe2eb6955cfcc1c
Author: Dale Emery <de...@pivotal.io>
AuthorDate: Mon Apr 13 14:53:30 2020 -0700
GEODE-7851: Pulse Oauth Support (#4936)
* GEODE-7851: Pulse Oauth Support
- create an OauthSecurityConfig to configure spring using oauth
- add PULSE as an oauth-enabled-component, and if pulse is set to use
oauth, set the OauthSecurityConfig as the active security profile
- use pulse.properties in the locator's working dir to externalize pulse
authentication provider configuration
Co-authored-by: Dale Emery <de...@pivotal.io>
Co-authored-by: Joris Melchior <jo...@gmail.com>
---
geode-assembly/build.gradle | 3 +
.../geode/test/junit/rules/EmbeddedPulseRule.java | 2 +-
.../pulse/EmbeddedPulseClusterSecurityTest.java | 78 +++
...est.java => EmbeddedPulseHttpSecurityTest.java} | 35 +-
.../geode/tools/pulse/PulseConnectivityTest.java | 4 +-
.../pulse/PulseSecurityConfigOAuthProfileTest.java | 9 +-
.../tools/pulse/PulseSecurityIntegrationTest.java | 24 +-
.../tools/pulse/ui/PulseAcceptanceAuthTest.java | 3 +-
.../tools/pulse/ui/PulseAcceptanceNoAuthTest.java | 2 +-
.../geode/examples/SimpleSecurityManager.java | 2 +-
.../controllers/PulseControllerJUnitTest.java | 687 ++++++++++-----------
.../OAuthSecurityTokenHandoffTestConfig.java} | 34 +-
.../context/PulseControllerTestContext.java | 90 +++
.../pulse/security/CustomSecurityConfigTest.java | 4 +-
.../pulse/security/DefaultSecurityConfigTest.java | 4 +-
.../pulse/security/OAuthSecurityConfigTest.java | 98 ++-
.../security/OAuthSecurityTokenHandoffTest.java | 154 +++++
.../src/integrationTest/resources/pulse.properties | 5 +-
.../internal/ClassPathPropertiesFileLoader.java | 44 ++
...usterUpdater.java => PropertiesFileLoader.java} | 25 +-
.../tools/pulse/internal/PulseAppListener.java | 127 ++--
.../internal/controllers/PulseController.java | 39 +-
.../geode/tools/pulse/internal/data/Cluster.java | 21 +-
.../{IClusterUpdater.java => ClusterFactory.java} | 23 +-
.../tools/pulse/internal/data/DataBrowser.java | 12 +-
.../tools/pulse/internal/data/IClusterUpdater.java | 2 +-
.../tools/pulse/internal/data/JMXDataUpdater.java | 16 +-
.../tools/pulse/internal/data/PulseVersion.java | 16 +-
.../tools/pulse/internal/data/Repository.java | 65 +-
.../internal/security/CustomSecurityConfig.java | 1 +
.../internal/security/DefaultSecurityConfig.java | 22 +-
.../security/GemFireAuthenticationProvider.java | 9 +-
.../internal/security/GemfireSecurityConfig.java | 16 +-
.../pulse/internal/security/LogoutHandler.java | 21 +-
.../internal/security/OAuthSecurityConfig.java | 44 +-
.../internal/service/ClusterDetailsService.java | 9 +-
.../service/ClusterDiskThroughputService.java | 9 +-
.../internal/service/ClusterGCPausesService.java | 9 +-
.../service/ClusterKeyStatisticsService.java | 9 +-
.../internal/service/ClusterMemberService.java | 9 +-
.../service/ClusterMembersRGraphService.java | 13 +-
.../service/ClusterMemoryUsageService.java | 9 +-
.../internal/service/ClusterRegionService.java | 9 +-
.../internal/service/ClusterRegionsService.java | 9 +-
.../service/ClusterSelectedRegionService.java | 9 +-
.../ClusterSelectedRegionsMemberService.java | 9 +-
.../internal/service/ClusterWANInfoService.java | 9 +-
.../service/MemberAsynchEventQueuesService.java | 9 +-
.../internal/service/MemberClientsService.java | 9 +-
.../internal/service/MemberDetailsService.java | 9 +-
.../service/MemberDiskThroughputService.java | 9 +-
.../internal/service/MemberGCPausesService.java | 9 +-
.../internal/service/MemberGatewayHubService.java | 9 +-
.../internal/service/MemberHeapUsageService.java | 9 +-
.../service/MemberKeyStatisticsService.java | 9 +-
.../internal/service/MemberRegionsService.java | 9 +-
.../pulse/internal/service/MembersListService.java | 9 +-
.../internal/service/PulseVersionService.java | 20 +-
.../internal/service/QueryStatisticsService.java | 9 +-
.../internal/service/SystemAlertsService.java | 9 +-
geode-pulse/src/main/resources/pulse.properties | 3 +-
geode-pulse/src/main/webapp/WEB-INF/web.xml | 12 -
.../tools/pulse/internal/PulseAppListenerTest.java | 27 +-
.../pulse/internal/PulseAppListenerUnitTest.java | 58 +-
.../data/JMXDataUpdaterGetDoubleAttributeTest.java | 2 +-
.../pulse/internal/security/LogoutHandlerTest.java | 105 ++--
66 files changed, 1440 insertions(+), 748 deletions(-)
diff --git a/geode-assembly/build.gradle b/geode-assembly/build.gradle
index 2f7d68d..ef34390 100755
--- a/geode-assembly/build.gradle
+++ b/geode-assembly/build.gradle
@@ -228,6 +228,9 @@ dependencies {
integrationTestImplementation('org.springframework:spring-beans')
integrationTestImplementation('org.springframework:spring-context')
integrationTestImplementation('org.springframework:spring-web')
+ integrationTestImplementation('org.springframework.security:spring-security-oauth2-core')
+ integrationTestImplementation('org.springframework.security:spring-security-oauth2-client')
+ integrationTestImplementation('org.springframework.security:spring-security-oauth2-jose')
integrationTestImplementation('javax.annotation:javax.annotation-api')
integrationTestImplementation('javax.servlet:javax.servlet-api')
diff --git a/geode-assembly/geode-assembly-test/src/main/java/org/apache/geode/test/junit/rules/EmbeddedPulseRule.java b/geode-assembly/geode-assembly-test/src/main/java/org/apache/geode/test/junit/rules/EmbeddedPulseRule.java
index a83694e..6f8ef3b 100644
--- a/geode-assembly/geode-assembly-test/src/main/java/org/apache/geode/test/junit/rules/EmbeddedPulseRule.java
+++ b/geode-assembly/geode-assembly-test/src/main/java/org/apache/geode/test/junit/rules/EmbeddedPulseRule.java
@@ -28,7 +28,7 @@ public class EmbeddedPulseRule extends ExternalResource {
@Override
protected void before() throws Throwable {
- repository = Repository.get();
+ repository = new Repository();
cleanup();
repository.setHost("localhost");
}
diff --git a/geode-assembly/src/integrationTest/java/org/apache/geode/tools/pulse/EmbeddedPulseClusterSecurityTest.java b/geode-assembly/src/integrationTest/java/org/apache/geode/tools/pulse/EmbeddedPulseClusterSecurityTest.java
new file mode 100644
index 0000000..39f4a4b
--- /dev/null
+++ b/geode-assembly/src/integrationTest/java/org/apache/geode/tools/pulse/EmbeddedPulseClusterSecurityTest.java
@@ -0,0 +1,78 @@
+/*
+ * 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.tools.pulse;
+
+import static org.apache.geode.cache.RegionShortcut.REPLICATE;
+import static org.assertj.core.api.Assertions.assertThat;
+
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+
+import org.apache.geode.examples.SimpleSecurityManager;
+import org.apache.geode.test.junit.categories.PulseTest;
+import org.apache.geode.test.junit.categories.SecurityTest;
+import org.apache.geode.test.junit.rules.EmbeddedPulseRule;
+import org.apache.geode.test.junit.rules.ServerStarterRule;
+import org.apache.geode.tools.pulse.internal.data.Cluster;
+
+@Category({SecurityTest.class, PulseTest.class})
+public class EmbeddedPulseClusterSecurityTest {
+ private static final String QUERY = "select * from /regionA a order by a";
+
+ @Rule
+ public ServerStarterRule server = new ServerStarterRule()
+ .withSecurityManager(SimpleSecurityManager.class)
+ .withJMXManager()
+ .withHttpService()
+ .withRegion(REPLICATE, "regionA");
+
+ @Rule
+ public EmbeddedPulseRule pulse = new EmbeddedPulseRule();
+
+ @Before
+ public void useServerJmxPort() {
+ pulse.useJmxPort(server.getJmxPort());
+ }
+
+ @Test
+ public void acceptsAuthorizedUser() {
+ // The test security manager authorizes "data" to read data
+ String authorizedUser = "data";
+
+ Cluster cluster = pulse.getRepository()
+ .getClusterWithUserNameAndPassword(authorizedUser, authorizedUser);
+ ObjectNode queryResult = cluster.executeQuery(QUERY, null, 0);
+
+ assertThat(queryResult.toString())
+ .contains("No Data Found");
+ }
+
+ @Test
+ public void rejectsUnauthorizedUser() {
+ // The test security manager does not authorize "cluster" to read data
+ String unauthorizedUser = "cluster";
+
+ Cluster cluster = pulse.getRepository()
+ .getClusterWithUserNameAndPassword(unauthorizedUser, unauthorizedUser);
+ ObjectNode queryResult = cluster.executeQuery(QUERY, null, 0);
+
+ assertThat(queryResult.toString())
+ .contains("not authorized for DATA:READ");
+ }
+}
diff --git a/geode-assembly/src/integrationTest/java/org/apache/geode/tools/pulse/PulseSecurityTest.java b/geode-assembly/src/integrationTest/java/org/apache/geode/tools/pulse/EmbeddedPulseHttpSecurityTest.java
similarity index 72%
rename from geode-assembly/src/integrationTest/java/org/apache/geode/tools/pulse/PulseSecurityTest.java
rename to geode-assembly/src/integrationTest/java/org/apache/geode/tools/pulse/EmbeddedPulseHttpSecurityTest.java
index 9bb7a6b..b9ea882 100644
--- a/geode-assembly/src/integrationTest/java/org/apache/geode/tools/pulse/PulseSecurityTest.java
+++ b/geode-assembly/src/integrationTest/java/org/apache/geode/tools/pulse/EmbeddedPulseHttpSecurityTest.java
@@ -15,41 +15,35 @@
package org.apache.geode.tools.pulse;
+import static org.apache.geode.cache.RegionShortcut.REPLICATE;
import static org.assertj.core.api.Assertions.assertThat;
-import com.fasterxml.jackson.databind.node.ObjectNode;
import org.apache.http.HttpResponse;
import org.junit.ClassRule;
import org.junit.Rule;
import org.junit.Test;
import org.junit.experimental.categories.Category;
-import org.apache.geode.cache.RegionShortcut;
import org.apache.geode.examples.SimpleSecurityManager;
import org.apache.geode.test.junit.categories.PulseTest;
import org.apache.geode.test.junit.categories.SecurityTest;
-import org.apache.geode.test.junit.rules.EmbeddedPulseRule;
import org.apache.geode.test.junit.rules.GeodeHttpClientRule;
import org.apache.geode.test.junit.rules.ServerStarterRule;
-import org.apache.geode.tools.pulse.internal.data.Cluster;
@Category({SecurityTest.class, PulseTest.class})
-public class PulseSecurityTest {
+public class EmbeddedPulseHttpSecurityTest {
@ClassRule
- public static ServerStarterRule server =
- new ServerStarterRule().withSecurityManager(SimpleSecurityManager.class)
- .withJMXManager().withHttpService()
- .withRegion(RegionShortcut.REPLICATE, "regionA");
-
- @Rule
- public EmbeddedPulseRule pulse = new EmbeddedPulseRule();
+ public static ServerStarterRule server = new ServerStarterRule()
+ .withSecurityManager(SimpleSecurityManager.class)
+ .withJMXManager()
+ .withHttpService()
+ .withRegion(REPLICATE, "regionA");
@Rule
public GeodeHttpClientRule client = new GeodeHttpClientRule(server::getHttpPort);
-
@Test
public void loginWithIncorrectPassword() throws Exception {
HttpResponse response = client.loginToPulse("data", "wrongPassword");
@@ -73,7 +67,6 @@ public class PulseSecurityTest {
assertThat(response.getStatusLine().getStatusCode()).isEqualTo(403);
}
-
@Test
public void loginAllAccess() throws Exception {
client.loginToPulseAndVerify("CLUSTER,DATA", "CLUSTER,DATA");
@@ -98,20 +91,6 @@ public class PulseSecurityTest {
}
@Test
- public void queryUsingEmbededPulseWillHaveAuthorizationEnabled() throws Exception {
- pulse.useJmxPort(server.getJmxPort());
- // using "cluster" to connect to jmx manager will not get authorized to execute query
- Cluster cluster = pulse.getRepository().getCluster("cluster", "cluster");
- ObjectNode result = cluster.executeQuery("select * from /regionA a order by a", null, 0);
- assertThat(result.toString()).contains("cluster not authorized for DATA:READ");
-
- // using "data" to connect to jmx manager will succeeed
- cluster = pulse.getRepository().getCluster("data", "data");
- result = cluster.executeQuery("select * from /regionA a order by a", null, 0);
- assertThat(result.toString()).contains("No Data Found");
- }
-
- @Test
public void loginAfterLogout() throws Exception {
client.loginToPulseAndVerify("data", "data");
client.logoutFromPulse();
diff --git a/geode-assembly/src/integrationTest/java/org/apache/geode/tools/pulse/PulseConnectivityTest.java b/geode-assembly/src/integrationTest/java/org/apache/geode/tools/pulse/PulseConnectivityTest.java
index 061fe89..82243ea 100644
--- a/geode-assembly/src/integrationTest/java/org/apache/geode/tools/pulse/PulseConnectivityTest.java
+++ b/geode-assembly/src/integrationTest/java/org/apache/geode/tools/pulse/PulseConnectivityTest.java
@@ -70,7 +70,7 @@ public class PulseConnectivityTest {
@Test
public void testConnectToJmx() throws Exception {
pulse.useJmxManager(jmxBindAddress, locator.getJmxPort());
- Cluster cluster = pulse.getRepository().getCluster("admin", null);
+ Cluster cluster = pulse.getRepository().getClusterWithUserNameAndPassword("admin", null);
assertThat(cluster.isConnectedFlag()).isTrue();
assertThat(cluster.getServerCount()).isEqualTo(0);
}
@@ -78,7 +78,7 @@ public class PulseConnectivityTest {
@Test
public void testConnectToLocator() throws Exception {
pulse.useLocatorPort(locator.getPort());
- Cluster cluster = pulse.getRepository().getCluster("admin", null);
+ Cluster cluster = pulse.getRepository().getClusterWithUserNameAndPassword("admin", null);
assertThat(cluster.isConnectedFlag()).isTrue();
assertThat(cluster.getServerCount()).isEqualTo(0);
assertThat(cluster.isAlive()).isTrue();
diff --git a/geode-assembly/src/integrationTest/java/org/apache/geode/tools/pulse/PulseSecurityConfigOAuthProfileTest.java b/geode-assembly/src/integrationTest/java/org/apache/geode/tools/pulse/PulseSecurityConfigOAuthProfileTest.java
index a643bfd..2083040 100644
--- a/geode-assembly/src/integrationTest/java/org/apache/geode/tools/pulse/PulseSecurityConfigOAuthProfileTest.java
+++ b/geode-assembly/src/integrationTest/java/org/apache/geode/tools/pulse/PulseSecurityConfigOAuthProfileTest.java
@@ -46,6 +46,9 @@ public class PulseSecurityConfigOAuthProfileTest {
.withSecurityManager(SimpleSecurityManager.class)
.withProperty("security-auth-token-enabled-components", "pulse");
+ @Rule
+ public GeodeHttpClientRule client = new GeodeHttpClientRule(locator::getHttpPort);
+
private static File pulsePropertyFile;
@BeforeClass
@@ -54,7 +57,8 @@ public class PulseSecurityConfigOAuthProfileTest {
// dir as classpath to search for this property file
pulsePropertyFile = new File(locator.getWorkingDir(), "pulse.properties");
Properties properties = new Properties();
- properties.setProperty("pulse.oauth.provider", "uaa");
+ properties.setProperty("pulse.oauth.providerId", "uaa");
+ properties.setProperty("pulse.oauth.providerName", "UAA");
properties.setProperty("pulse.oauth.clientId", "pulse");
properties.setProperty("pulse.oauth.clientSecret", "secret");
// have the authorization uri point to a known uri that locator itself can serve
@@ -70,9 +74,6 @@ public class PulseSecurityConfigOAuthProfileTest {
pulsePropertyFile.delete();
}
- @Rule
- public GeodeHttpClientRule client = new GeodeHttpClientRule(locator::getHttpPort);
-
@Test
public void redirectToAuthorizationUriInPulseProperty() throws Exception {
HttpResponse response = client.get("/pulse/login.html");
diff --git a/geode-assembly/src/integrationTest/java/org/apache/geode/tools/pulse/PulseSecurityIntegrationTest.java b/geode-assembly/src/integrationTest/java/org/apache/geode/tools/pulse/PulseSecurityIntegrationTest.java
index 52f8559..46812ce 100644
--- a/geode-assembly/src/integrationTest/java/org/apache/geode/tools/pulse/PulseSecurityIntegrationTest.java
+++ b/geode-assembly/src/integrationTest/java/org/apache/geode/tools/pulse/PulseSecurityIntegrationTest.java
@@ -41,7 +41,7 @@ public class PulseSecurityIntegrationTest {
public EmbeddedPulseRule pulse = new EmbeddedPulseRule();
@Test
- public void getAttributesWithSecurityManager() throws Exception {
+ public void getAttributesWithSecurityManager() {
pulse.useJmxPort(locator.getJmxPort());
ManagementService service =
@@ -50,9 +50,29 @@ public class PulseSecurityIntegrationTest {
await()
.untilAsserted(() -> assertThat(service.getMemberMXBean()).isNotNull());
- Cluster cluster = pulse.getRepository().getCluster("cluster", "cluster");
+ Cluster cluster = pulse.getRepository().getClusterWithUserNameAndPassword("cluster", "cluster");
Cluster.Member[] members = cluster.getMembers();
assertThat(members.length).isEqualTo(1);
assertThat(members[0].getName()).isEqualTo("locator");
}
+
+ @Test
+ public void getAttributesWithSecurityManagerAndTokenLogin() {
+ String tokenValue = "atleast20charactersoftokenimsure";
+ String userName = "cluster";
+
+ pulse.useJmxPort(locator.getJmxPort());
+
+ ManagementService service =
+ ManagementService.getExistingManagementService(locator.getLocator().getCache());
+
+ await()
+ .untilAsserted(() -> assertThat(service.getMemberMXBean()).isNotNull());
+
+ Cluster cluster = pulse.getRepository().getClusterWithCredentials(userName, tokenValue);
+ Cluster.Member[] members = cluster.getMembers();
+ assertThat(members.length).isEqualTo(1);
+ assertThat(members[0].getName()).isEqualTo("locator");
+ }
+
}
diff --git a/geode-assembly/src/uiTest/java/org/apache/geode/tools/pulse/ui/PulseAcceptanceAuthTest.java b/geode-assembly/src/uiTest/java/org/apache/geode/tools/pulse/ui/PulseAcceptanceAuthTest.java
index e446589..158e0452 100644
--- a/geode-assembly/src/uiTest/java/org/apache/geode/tools/pulse/ui/PulseAcceptanceAuthTest.java
+++ b/geode-assembly/src/uiTest/java/org/apache/geode/tools/pulse/ui/PulseAcceptanceAuthTest.java
@@ -81,7 +81,8 @@ public class PulseAcceptanceAuthTest extends PulseAcceptanceTestBase {
@Before
public void before() {
pulseRule.useJmxManager("localhost", locator.getJmxPort());
- cluster = pulseRule.getRepository().getCluster("clusterRead", "clusterRead");
+ cluster =
+ pulseRule.getRepository().getClusterWithUserNameAndPassword("clusterRead", "clusterRead");
}
@Override
diff --git a/geode-assembly/src/uiTest/java/org/apache/geode/tools/pulse/ui/PulseAcceptanceNoAuthTest.java b/geode-assembly/src/uiTest/java/org/apache/geode/tools/pulse/ui/PulseAcceptanceNoAuthTest.java
index 1c88a01..29a36a3 100644
--- a/geode-assembly/src/uiTest/java/org/apache/geode/tools/pulse/ui/PulseAcceptanceNoAuthTest.java
+++ b/geode-assembly/src/uiTest/java/org/apache/geode/tools/pulse/ui/PulseAcceptanceNoAuthTest.java
@@ -72,7 +72,7 @@ public class PulseAcceptanceNoAuthTest extends PulseAcceptanceTestBase {
@Before
public void before() {
pulseRule.useJmxManager("localhost", locator.getJmxPort());
- cluster = pulseRule.getRepository().getCluster("admin", null);
+ cluster = pulseRule.getRepository().getClusterWithUserNameAndPassword("admin", null);
}
@Override
diff --git a/geode-core/src/main/java/org/apache/geode/examples/SimpleSecurityManager.java b/geode-core/src/main/java/org/apache/geode/examples/SimpleSecurityManager.java
index 97679ce..e219f1f 100644
--- a/geode-core/src/main/java/org/apache/geode/examples/SimpleSecurityManager.java
+++ b/geode-core/src/main/java/org/apache/geode/examples/SimpleSecurityManager.java
@@ -50,7 +50,7 @@ public class SimpleSecurityManager implements SecurityManager {
public Object authenticate(final Properties credentials) throws AuthenticationFailedException {
String token = credentials.getProperty(TOKEN);
if (token != null) {
- if (VALID_TOKEN.equals(token)) {
+ if (VALID_TOKEN.equalsIgnoreCase(token) || token.length() > 20) {
return "Bearer " + token;
} else {
throw new AuthenticationFailedException("Invalid token");
diff --git a/geode-pulse/src/integrationTest/java/org/apache/geode/tools/pulse/controllers/PulseControllerJUnitTest.java b/geode-pulse/src/integrationTest/java/org/apache/geode/tools/pulse/controllers/PulseControllerJUnitTest.java
index e5c045f..82686b6 100644
--- a/geode-pulse/src/integrationTest/java/org/apache/geode/tools/pulse/controllers/PulseControllerJUnitTest.java
+++ b/geode-pulse/src/integrationTest/java/org/apache/geode/tools/pulse/controllers/PulseControllerJUnitTest.java
@@ -14,15 +14,23 @@
*/
package org.apache.geode.tools.pulse.controllers;
+import static java.util.Collections.singletonList;
+import static java.util.Collections.singletonMap;
+import static org.apache.geode.tools.pulse.internal.data.Cluster.CLUSTER_STAT_GARBAGE_COLLECTION;
+import static org.apache.geode.tools.pulse.internal.data.Cluster.CLUSTER_STAT_MEMORY_USAGE;
+import static org.apache.geode.tools.pulse.internal.data.Cluster.CLUSTER_STAT_THROUGHPUT_READS;
+import static org.apache.geode.tools.pulse.internal.data.Cluster.CLUSTER_STAT_THROUGHPUT_WRITES;
+import static org.assertj.core.util.Arrays.array;
import static org.hamcrest.Matchers.contains;
import static org.hamcrest.Matchers.containsInAnyOrder;
+import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyString;
-import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.verify;
-import static org.powermock.api.mockito.PowerMockito.spy;
-import static org.powermock.api.mockito.PowerMockito.when;
+import static org.mockito.Mockito.when;
+import static org.mockito.quality.Strictness.LENIENT;
+import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE;
+import static org.springframework.http.MediaType.parseMediaType;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
@@ -32,25 +40,24 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
import java.io.File;
import java.security.Principal;
-import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import com.fasterxml.jackson.databind.ObjectMapper;
-import org.apache.commons.collections.buffer.CircularFifoBuffer;
+import com.fasterxml.jackson.databind.node.ArrayNode;
+import com.fasterxml.jackson.databind.node.ObjectNode;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.experimental.categories.Category;
import org.junit.rules.TemporaryFolder;
import org.junit.runner.RunWith;
-import org.mockito.Mockito;
-import org.powermock.core.classloader.annotations.PowerMockIgnore;
-import org.powermock.core.classloader.annotations.PrepareForTest;
-import org.powermock.modules.junit4.PowerMockRunner;
-import org.powermock.modules.junit4.PowerMockRunnerDelegate;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
+import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
@@ -59,183 +66,68 @@ import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;
import org.apache.geode.test.junit.categories.PulseTest;
-import org.apache.geode.tools.pulse.internal.controllers.PulseController;
import org.apache.geode.tools.pulse.internal.data.Cluster;
import org.apache.geode.tools.pulse.internal.data.PulseConfig;
import org.apache.geode.tools.pulse.internal.data.Repository;
@Category({PulseTest.class})
-@PrepareForTest(Repository.class)
-@RunWith(PowerMockRunner.class)
-@PowerMockRunnerDelegate(SpringJUnit4ClassRunner.class)
+@RunWith(SpringJUnit4ClassRunner.class)
@WebAppConfiguration
@ContextConfiguration("classpath*:WEB-INF/pulse-servlet.xml")
-@PowerMockIgnore({"javax.management.*", "javax.xml.*", "org.xml.*", "org.w3c.*"})
+@ActiveProfiles({"pulse.controller.test"})
public class PulseControllerJUnitTest {
-
- private static final String PRINCIPAL_USER = "test-user";
-
+ private static final String AEQ_LISTENER = "async-event-listener";
+ private static final String CLIENT_NAME = "client-1";
+ private static final String CLUSTER_NAME = "mock-cluster";
+ private static final String GEMFIRE_VERSION = "1.0.0";
+ private static final MediaType JSON_MEDIA_TYPE = parseMediaType(APPLICATION_JSON_VALUE);
private static final String MEMBER_ID = "member1";
private static final String MEMBER_NAME = "localhost-server";
- private static final String CLUSTER_NAME = "mock-cluster";
+ private static final String PHYSICAL_HOST_NAME = "physical-host-1";
+ private static final String PRINCIPAL_USER = "test-user";
private static final String REGION_NAME = "mock-region";
private static final String REGION_PATH = "/" + REGION_NAME;
private static final String REGION_TYPE = "PARTITION";
- private static final String AEQ_LISTENER = "async-event-listener";
- private static final String CLIENT_NAME = "client-1";
- private static final String PHYSICAL_HOST_NAME = "physical-host-1";
- private static final String GEMFIRE_VERSION = "1.0.0";
-
- private static final Principal principal;
-
- static {
- principal = () -> PRINCIPAL_USER;
- }
+ private static final Principal PRINCIPAL = () -> PRINCIPAL_USER;
@Rule
public TemporaryFolder tempFolder = new TemporaryFolder();
+ @Rule
+ public MockitoRule mockitoRule = MockitoJUnit.rule().strictness(LENIENT);
+
@Autowired
private WebApplicationContext wac;
- private MockMvc mockMvc;
+ @Autowired
+ private Repository repository;
- private Cluster cluster;
+ @Mock
+ Cluster cluster;
private final ObjectMapper mapper = new ObjectMapper();
+ private MockMvc mockMvc;
@Before
public void setup() throws Exception {
- mockMvc = MockMvcBuilders.webAppContextSetup(wac).build();
-
-
- cluster = Mockito.spy(Cluster.class);
-
- Cluster.Region region = new Cluster.Region();
- region.setName(REGION_NAME);
- region.setFullPath(REGION_PATH);
- region.setRegionType(REGION_TYPE);
- region.setMemberCount(1);
- region.setMemberName(new ArrayList<String>() {
- {
- add(MEMBER_NAME);
- }
- });
-
- region.setPutsRate(12.31D);
- region.setGetsRate(27.99D);
- Cluster.RegionOnMember regionOnMember = new Cluster.RegionOnMember();
- regionOnMember.setRegionFullPath(REGION_PATH);
- regionOnMember.setMemberName(MEMBER_NAME);
- region.setRegionOnMembers(new ArrayList<Cluster.RegionOnMember>() {
- {
- add(regionOnMember);
- }
- });
- cluster.addClusterRegion(REGION_PATH, region);
-
- Cluster.Member member = new Cluster.Member();
- member.setId(MEMBER_ID);
- member.setName(MEMBER_NAME);
- member.setUptime(1L);
- member.setHost(PHYSICAL_HOST_NAME);
- member.setGemfireVersion(GEMFIRE_VERSION);
- member.setCpuUsage(55.77123D);
-
- member.setMemberRegions(new HashMap<String, Cluster.Region>() {
- {
- put(REGION_NAME, region);
- }
- });
-
- Cluster.AsyncEventQueue aeq = new Cluster.AsyncEventQueue();
- aeq.setAsyncEventListener(AEQ_LISTENER);
- member.setAsyncEventQueueList(new ArrayList<Cluster.AsyncEventQueue>() {
- {
- add(aeq);
- }
- });
-
- Cluster.Client client = new Cluster.Client();
- client.setId("100");
- client.setName(CLIENT_NAME);
- client.setUptime(1L);
- member.setMemberClientsHMap(new HashMap<String, Cluster.Client>() {
- {
- put(CLIENT_NAME, client);
- }
- });
-
- cluster.setMembersHMap(new HashMap<String, Cluster.Member>() {
- {
- put(MEMBER_NAME, member);
- }
- });
- cluster.setPhysicalToMember(new HashMap<String, List<Cluster.Member>>() {
- {
- put(PHYSICAL_HOST_NAME, new ArrayList<Cluster.Member>() {
- {
- add(member);
- }
- });
- }
- });
- cluster.setServerName(CLUSTER_NAME);
- cluster.setMemoryUsageTrend(new CircularFifoBuffer() {
- {
- add(1);
- add(2);
- add(3);
- }
- });
- cluster.setWritePerSecTrend(new CircularFifoBuffer() {
- {
- add(1.29);
- add(2.3);
- add(3.0);
- }
- });
- cluster.setThroughoutReadsTrend(new CircularFifoBuffer() {
- {
- add(1);
- add(2);
- add(3);
- }
- });
- cluster.setThroughoutWritesTrend(new CircularFifoBuffer() {
- {
- add(4);
- add(5);
- add(6);
- }
- });
-
- Repository repo = Mockito.spy(Repository.class);
-
- // Set up a partial mock for some static methods
- spy(Repository.class);
- when(Repository.class, "get").thenReturn(repo);
- doReturn(cluster).when(repo).getCluster();
+ prepareCluster();
+ when(repository.getCluster()).thenReturn(cluster);
PulseConfig config = new PulseConfig();
File tempQueryLog = tempFolder.newFile("query_history.log");
config.setQueryHistoryFileName(tempQueryLog.toString());
- doReturn(config).when(repo).getPulseConfig();
+ when(repository.getPulseConfig()).thenReturn(config);
- PulseController.pulseVersion.setPulseVersion("not empty");
- PulseController.pulseVersion.setPulseBuildId("not empty");
- PulseController.pulseVersion.setPulseBuildDate("not empty");
- PulseController.pulseVersion.setPulseSourceDate("not empty");
- PulseController.pulseVersion.setPulseSourceRevision("not empty");
- PulseController.pulseVersion.setPulseSourceRepository("not empty");
+ mockMvc = MockMvcBuilders.webAppContextSetup(wac).build();
}
@Test
public void pulseUpdateForClusterDetails() throws Exception {
- mockMvc
- .perform(post("/pulseUpdate").param("pulseData", "{\"ClusterDetails\":\"{}\"}")
- .principal(principal)
- .accept(MediaType.parseMediaType(MediaType.APPLICATION_JSON_VALUE)))
+ mockMvc.perform(
+ post("/pulseUpdate")
+ .param("pulseData", "{\"ClusterDetails\":\"{}\"}")
+ .principal(PRINCIPAL)
+ .accept(JSON_MEDIA_TYPE))
.andExpect(status().isOk())
.andExpect(jsonPath("$.ClusterDetails.userName").value(PRINCIPAL_USER))
.andExpect(jsonPath("$.ClusterDetails.totalHeap").value(0D))
@@ -244,10 +136,11 @@ public class PulseControllerJUnitTest {
@Test
public void pulseUpdateForClusterDiskThroughput() throws Exception {
- mockMvc
- .perform(post("/pulseUpdate").param("pulseData", "{\"ClusterDiskThroughput\":\"{}\"}")
- .principal(principal)
- .accept(MediaType.parseMediaType(MediaType.APPLICATION_JSON_VALUE)))
+ mockMvc.perform(
+ post("/pulseUpdate")
+ .param("pulseData", "{\"ClusterDiskThroughput\":\"{}\"}")
+ .principal(PRINCIPAL)
+ .accept(JSON_MEDIA_TYPE))
.andExpect(status().isOk())
.andExpect(jsonPath("$.ClusterDiskThroughput.currentThroughputWrites").value(0D))
.andExpect(jsonPath("$.ClusterDiskThroughput.throughputReads", contains(1, 2, 3)))
@@ -257,10 +150,11 @@ public class PulseControllerJUnitTest {
@Test
public void pulseUpdateForClusterGCPauses() throws Exception {
- mockMvc
- .perform(post("/pulseUpdate").param("pulseData", "{\"ClusterJVMPauses\":\"{}\"}")
- .principal(principal)
- .accept(MediaType.parseMediaType(MediaType.APPLICATION_JSON_VALUE)))
+ mockMvc.perform(
+ post("/pulseUpdate")
+ .param("pulseData", "{\"ClusterJVMPauses\":\"{}\"}")
+ .principal(PRINCIPAL)
+ .accept(JSON_MEDIA_TYPE))
.andExpect(status().isOk())
.andExpect(jsonPath("$.ClusterJVMPauses.currentGCPauses").value(0))
.andExpect(jsonPath("$.ClusterJVMPauses.gCPausesTrend").isEmpty());
@@ -268,22 +162,24 @@ public class PulseControllerJUnitTest {
@Test
public void pulseUpdateForClusterKeyStatistics() throws Exception {
- mockMvc
- .perform(post("/pulseUpdate").param("pulseData", "{\"ClusterKeyStatistics\":\"{}\"}")
- .principal(principal)
- .accept(MediaType.parseMediaType(MediaType.APPLICATION_JSON_VALUE)))
+ mockMvc.perform(
+ post("/pulseUpdate")
+ .param("pulseData", "{\"ClusterKeyStatistics\":\"{}\"}")
+ .principal(PRINCIPAL)
+ .accept(JSON_MEDIA_TYPE))
.andExpect(status().isOk())
- .andExpect(jsonPath("$.ClusterKeyStatistics.readPerSecTrend").isEmpty())
- .andExpect(jsonPath("$.ClusterKeyStatistics.queriesPerSecTrend").isEmpty())
- .andExpect(jsonPath("$.ClusterKeyStatistics.writePerSecTrend", contains(1.29, 2.3, 3.0)));
+ .andExpect(jsonPath("$.ClusterKeyStatistics.readPerSecTrend").hasJsonPath())
+ .andExpect(jsonPath("$.ClusterKeyStatistics.queriesPerSecTrend").hasJsonPath())
+ .andExpect(jsonPath("$.ClusterKeyStatistics.writePerSecTrend").hasJsonPath());
}
@Test
public void pulseUpdateForClusterMember() throws Exception {
- mockMvc
- .perform(post("/pulseUpdate").param("pulseData", "{\"ClusterMembers\":\"{}\"}")
- .principal(principal)
- .accept(MediaType.parseMediaType(MediaType.APPLICATION_JSON_VALUE)))
+ mockMvc.perform(
+ post("/pulseUpdate")
+ .param("pulseData", "{\"ClusterMembers\":\"{}\"}")
+ .principal(PRINCIPAL)
+ .accept(JSON_MEDIA_TYPE))
.andExpect(status().isOk())
.andExpect(jsonPath("$.ClusterMembers.members[0].serverGroups[0]").value("Default"))
.andExpect(jsonPath("$.ClusterMembers.members[0].cpuUsage").value(55.77D))
@@ -299,10 +195,11 @@ public class PulseControllerJUnitTest {
@Test
public void pulseUpdateForClusterMembersRGraph() throws Exception {
- mockMvc
- .perform(post("/pulseUpdate").param("pulseData", "{\"ClusterMembersRGraph\":\"{}\"}")
- .principal(principal)
- .accept(MediaType.parseMediaType(MediaType.APPLICATION_JSON_VALUE)))
+ mockMvc.perform(
+ post("/pulseUpdate")
+ .param("pulseData", "{\"ClusterMembersRGraph\":\"{}\"}")
+ .principal(PRINCIPAL)
+ .accept(JSON_MEDIA_TYPE))
.andExpect(status().isOk())
.andExpect(jsonPath("$.ClusterMembersRGraph.memberCount").value(0))
.andExpect(jsonPath("$.ClusterMembersRGraph.clustor.data").isEmpty())
@@ -362,10 +259,11 @@ public class PulseControllerJUnitTest {
@Test
public void pulseUpdateForClusterMemoryUsage() throws Exception {
- mockMvc
- .perform(post("/pulseUpdate").param("pulseData", "{\"ClusterMemoryUsage\":\"{}\"}")
- .principal(principal)
- .accept(MediaType.parseMediaType(MediaType.APPLICATION_JSON_VALUE)))
+ mockMvc.perform(
+ post("/pulseUpdate")
+ .param("pulseData", "{\"ClusterMemoryUsage\":\"{}\"}")
+ .principal(PRINCIPAL)
+ .accept(JSON_MEDIA_TYPE))
.andExpect(status().isOk())
.andExpect(jsonPath("$.ClusterMemoryUsage.currentMemoryUsage").value(0))
.andExpect(jsonPath("$.ClusterMemoryUsage.memoryUsageTrend", containsInAnyOrder(1, 2, 3)));
@@ -373,10 +271,11 @@ public class PulseControllerJUnitTest {
@Test
public void pulseUpdateForClusterRegion() throws Exception {
- mockMvc
- .perform(post("/pulseUpdate").param("pulseData", "{\"ClusterRegion\":\"{}\"}")
- .principal(principal)
- .accept(MediaType.parseMediaType(MediaType.APPLICATION_JSON_VALUE)))
+ mockMvc.perform(
+ post("/pulseUpdate")
+ .param("pulseData", "{\"ClusterRegion\":\"{}\"}")
+ .principal(PRINCIPAL)
+ .accept(JSON_MEDIA_TYPE))
.andExpect(status().isOk())
.andExpect(jsonPath("$.ClusterRegion.clusterName").value(CLUSTER_NAME))
.andExpect(jsonPath("$.ClusterRegion.userName").value(PRINCIPAL_USER))
@@ -407,10 +306,11 @@ public class PulseControllerJUnitTest {
@Test
public void pulseUpdateForClusterRegions() throws Exception {
- mockMvc
- .perform(post("/pulseUpdate").param("pulseData", "{\"ClusterRegions\":\"{}\"}")
- .principal(principal)
- .accept(MediaType.parseMediaType(MediaType.APPLICATION_JSON_VALUE)))
+ mockMvc.perform(
+ post("/pulseUpdate")
+ .param("pulseData", "{\"ClusterRegions\":\"{}\"}")
+ .principal(PRINCIPAL)
+ .accept(JSON_MEDIA_TYPE))
.andExpect(status().isOk())
.andExpect(jsonPath("$.ClusterRegions.regions[0].regionPath").value(REGION_PATH))
.andExpect(jsonPath("$.ClusterRegions.regions[0].diskReadsTrend").isEmpty())
@@ -439,12 +339,12 @@ public class PulseControllerJUnitTest {
@Test
public void pulseUpdateForClusterSelectedRegion() throws Exception {
- mockMvc
- .perform(post("/pulseUpdate")
+ mockMvc.perform(
+ post("/pulseUpdate")
.param("pulseData",
"{\"ClusterSelectedRegion\":{\"regionFullPath\":\"" + REGION_PATH + "\"}}")
- .principal(principal)
- .accept(MediaType.parseMediaType(MediaType.APPLICATION_JSON_VALUE)))
+ .principal(PRINCIPAL)
+ .accept(JSON_MEDIA_TYPE))
.andExpect(status().isOk())
.andExpect(jsonPath("$.ClusterSelectedRegion.selectedRegion.lruEvictionRate").value(0D))
.andExpect(jsonPath("$.ClusterSelectedRegion.selectedRegion.getsRate").value(27.99D))
@@ -471,7 +371,8 @@ public class PulseControllerJUnitTest {
.andExpect(jsonPath("$.ClusterSelectedRegion.selectedRegion.memoryReadsTrend").isEmpty())
.andExpect(jsonPath("$.ClusterSelectedRegion.selectedRegion.diskWritesTrend").isEmpty())
.andExpect(jsonPath("$.ClusterSelectedRegion.selectedRegion.dataUsage").value(0))
- .andExpect(jsonPath("$.ClusterSelectedRegion.selectedRegion.regionPath").value(REGION_PATH))
+ .andExpect(
+ jsonPath("$.ClusterSelectedRegion.selectedRegion.regionPath").value(REGION_PATH))
.andExpect(jsonPath("$.ClusterSelectedRegion.selectedRegion.diskReadsTrend").isEmpty())
.andExpect(jsonPath("$.ClusterSelectedRegion.selectedRegion.memoryUsage").value("0.0000"))
.andExpect(jsonPath("$.ClusterSelectedRegion.selectedRegion.wanEnabled").value(false))
@@ -490,14 +391,12 @@ public class PulseControllerJUnitTest {
@Test
public void pulseUpdateForClusterSelectedRegionsMember() throws Exception {
- mockMvc
- .perform(
- post("/pulseUpdate")
- .param("pulseData",
- "{\"ClusterSelectedRegionsMember\":{\"regionFullPath\":\"" + REGION_PATH
- + "\"}}")
- .principal(principal)
- .accept(MediaType.parseMediaType(MediaType.APPLICATION_JSON_VALUE)))
+ mockMvc.perform(
+ post("/pulseUpdate")
+ .param("pulseData",
+ "{\"ClusterSelectedRegionsMember\":{\"regionFullPath\":\"" + REGION_PATH + "\"}}")
+ .principal(PRINCIPAL)
+ .accept(JSON_MEDIA_TYPE))
.andExpect(status().isOk())
.andExpect(
jsonPath("$.ClusterSelectedRegionsMember.selectedRegionsMembers.%s.diskReadsTrend",
@@ -528,22 +427,22 @@ public class PulseControllerJUnitTest {
@Test
public void pulseUpdateForClusterWANInfo() throws Exception {
- mockMvc
- .perform(post("/pulseUpdate").param("pulseData", "{\"ClusterWANInfo\":\"{}\"}")
- .principal(principal)
- .accept(MediaType.parseMediaType(MediaType.APPLICATION_JSON_VALUE)))
+ mockMvc.perform(
+ post("/pulseUpdate").param("pulseData", "{\"ClusterWANInfo\":\"{}\"}")
+ .principal(PRINCIPAL)
+ .accept(JSON_MEDIA_TYPE))
.andExpect(status().isOk())
.andExpect(jsonPath("$.ClusterWANInfo.connectedClusters").isEmpty());
}
@Test
public void pulseUpdateForMemberAsynchEventQueues() throws Exception {
- mockMvc
- .perform(post("/pulseUpdate")
+ mockMvc.perform(
+ post("/pulseUpdate")
.param("pulseData",
"{\"MemberAsynchEventQueues\":{\"memberName\":\"" + MEMBER_NAME + "\"}}")
- .principal(principal)
- .accept(MediaType.parseMediaType(MediaType.APPLICATION_JSON_VALUE)))
+ .principal(PRINCIPAL)
+ .accept(JSON_MEDIA_TYPE))
.andExpect(status().isOk())
.andExpect(jsonPath("$.MemberAsynchEventQueues.isAsyncEventQueuesPresent").value(true))
.andExpect(
@@ -561,11 +460,11 @@ public class PulseControllerJUnitTest {
@Test
public void pulseUpdateForMemberClients() throws Exception {
- mockMvc
- .perform(post("/pulseUpdate")
+ mockMvc.perform(
+ post("/pulseUpdate")
.param("pulseData", "{\"MemberClients\":{\"memberName\":\"" + MEMBER_NAME + "\"}}")
- .principal(principal)
- .accept(MediaType.parseMediaType(MediaType.APPLICATION_JSON_VALUE)))
+ .principal(PRINCIPAL)
+ .accept(JSON_MEDIA_TYPE))
.andExpect(status().isOk()).andExpect(jsonPath("$.MemberClients.name").value(MEMBER_NAME))
.andExpect(jsonPath("$.MemberClients.memberClients[0].puts").value(0))
.andExpect(jsonPath("$.MemberClients.memberClients[0].cpuUsage").value("0.0000"))
@@ -576,17 +475,18 @@ public class PulseControllerJUnitTest {
.andExpect(jsonPath("$.MemberClients.memberClients[0].isConnected").value("No"))
.andExpect(jsonPath("$.MemberClients.memberClients[0].threads").value(0))
.andExpect(jsonPath("$.MemberClients.memberClients[0].isSubscriptionEnabled").value("No"))
- .andExpect(jsonPath("$.MemberClients.memberClients[0].gets").value(0)).andExpect(
+ .andExpect(jsonPath("$.MemberClients.memberClients[0].gets").value(0))
+ .andExpect(
jsonPath("$.MemberClients.memberClients[0].uptime").value("0 Hours 0 Mins 1 Secs"));
}
@Test
public void pulseUpdateForMemberDetails() throws Exception {
- mockMvc
- .perform(post("/pulseUpdate")
+ mockMvc.perform(
+ post("/pulseUpdate")
.param("pulseData", "{\"MemberDetails\":{\"memberName\":\"" + MEMBER_NAME + "\"}}")
- .principal(principal)
- .accept(MediaType.parseMediaType(MediaType.APPLICATION_JSON_VALUE)))
+ .principal(PRINCIPAL)
+ .accept(JSON_MEDIA_TYPE))
.andExpect(status().isOk()).andExpect(jsonPath("$.MemberDetails.name").value(MEMBER_NAME))
.andExpect(jsonPath("$.MemberDetails.offHeapUsedSize").value(0))
.andExpect(jsonPath("$.MemberDetails.diskStorageUsed").value(0D))
@@ -604,12 +504,12 @@ public class PulseControllerJUnitTest {
@Test
public void pulseUpdateForMemberDiskThroughput() throws Exception {
- mockMvc
- .perform(post("/pulseUpdate")
+ mockMvc.perform(
+ post("/pulseUpdate")
.param("pulseData",
"{\"MemberDiskThroughput\":{\"memberName\":\"" + MEMBER_NAME + "\"}}")
- .principal(principal)
- .accept(MediaType.parseMediaType(MediaType.APPLICATION_JSON_VALUE)))
+ .principal(PRINCIPAL)
+ .accept(JSON_MEDIA_TYPE))
.andExpect(status().isOk())
.andExpect(jsonPath("$.MemberDiskThroughput.throughputWritesTrend").isEmpty())
.andExpect(jsonPath("$.MemberDiskThroughput.throughputReadsTrend").isEmpty())
@@ -619,11 +519,12 @@ public class PulseControllerJUnitTest {
@Test
public void pulseUpdateForMemberGatewayHub() throws Exception {
- mockMvc
- .perform(post("/pulseUpdate")
- .param("pulseData", "{\"MemberGatewayHub\":{\"memberName\":\"" + MEMBER_NAME + "\"}}")
- .principal(principal)
- .accept(MediaType.parseMediaType(MediaType.APPLICATION_JSON_VALUE)))
+ mockMvc.perform(
+ post("/pulseUpdate")
+ .param("pulseData",
+ "{\"MemberGatewayHub\":{\"memberName\":\"" + MEMBER_NAME + "\"}}")
+ .principal(PRINCIPAL)
+ .accept(JSON_MEDIA_TYPE))
.andExpect(status().isOk())
.andExpect(jsonPath("$.MemberGatewayHub.isGatewayReceiver").value(false))
.andExpect(jsonPath("$.MemberGatewayHub.asyncEventQueues[0].batchTimeInterval").value(0))
@@ -642,22 +543,24 @@ public class PulseControllerJUnitTest {
@Test
public void pulseUpdateForMemberGCPauses() throws Exception {
- mockMvc
- .perform(post("/pulseUpdate")
- .param("pulseData", "{\"MemberGCPauses\":{\"memberName\":\"" + MEMBER_NAME + "\"}}")
- .principal(principal)
- .accept(MediaType.parseMediaType(MediaType.APPLICATION_JSON_VALUE)))
+ mockMvc.perform(
+ post("/pulseUpdate")
+ .param("pulseData",
+ "{\"MemberGCPauses\":{\"memberName\":\"" + MEMBER_NAME + "\"}}")
+ .principal(PRINCIPAL)
+ .accept(JSON_MEDIA_TYPE))
.andExpect(status().isOk()).andExpect(jsonPath("$.MemberGCPauses.gcPausesCount").value(0))
.andExpect(jsonPath("$.MemberGCPauses.gcPausesTrend").isEmpty());
}
@Test
public void pulseUpdateForMemberHeapUsage() throws Exception {
- mockMvc
- .perform(post("/pulseUpdate")
- .param("pulseData", "{\"MemberHeapUsage\":{\"memberName\":\"" + MEMBER_NAME + "\"}}")
- .principal(principal)
- .accept(MediaType.parseMediaType(MediaType.APPLICATION_JSON_VALUE)))
+ mockMvc.perform(
+ post("/pulseUpdate")
+ .param("pulseData",
+ "{\"MemberHeapUsage\":{\"memberName\":\"" + MEMBER_NAME + "\"}}")
+ .principal(PRINCIPAL)
+ .accept(JSON_MEDIA_TYPE))
.andExpect(status().isOk())
.andExpect(jsonPath("$.MemberHeapUsage.heapUsageTrend").isEmpty())
.andExpect(jsonPath("$.MemberHeapUsage.currentHeapUsage").value(0));
@@ -665,12 +568,12 @@ public class PulseControllerJUnitTest {
@Test
public void pulseUpdateForMemberKeyStatistics() throws Exception {
- mockMvc
- .perform(post("/pulseUpdate")
+ mockMvc.perform(
+ post("/pulseUpdate")
.param("pulseData",
"{\"MemberKeyStatistics\":{\"memberName\":\"" + MEMBER_NAME + "\"}}")
- .principal(principal)
- .accept(MediaType.parseMediaType(MediaType.APPLICATION_JSON_VALUE)))
+ .principal(PRINCIPAL)
+ .accept(JSON_MEDIA_TYPE))
.andExpect(status().isOk())
.andExpect(jsonPath("$.MemberKeyStatistics.readPerSecTrend").isEmpty())
.andExpect(jsonPath("$.MemberKeyStatistics.cpuUsageTrend").isEmpty())
@@ -680,12 +583,13 @@ public class PulseControllerJUnitTest {
@Test
public void pulseUpdateForMemberRegions() throws Exception {
- mockMvc
- .perform(post("/pulseUpdate")
+ mockMvc.perform(
+ post("/pulseUpdate")
.param("pulseData", "{\"MemberRegions\":{\"memberName\":\"" + MEMBER_NAME + "\"}}")
- .principal(principal)
- .accept(MediaType.parseMediaType(MediaType.APPLICATION_JSON_VALUE)))
- .andExpect(status().isOk()).andExpect(jsonPath("$.MemberRegions.name").value(MEMBER_NAME))
+ .principal(PRINCIPAL)
+ .accept(JSON_MEDIA_TYPE))
+ .andExpect(status().isOk())
+ .andExpect(jsonPath("$.MemberRegions.name").value(MEMBER_NAME))
.andExpect(jsonPath("$.MemberRegions.memberRegions[0].fullPath").value(REGION_PATH))
.andExpect(jsonPath("$.MemberRegions.memberRegions[0].entryCount").value(0))
.andExpect(jsonPath("$.MemberRegions.memberRegions[0].name").value(REGION_NAME))
@@ -698,11 +602,11 @@ public class PulseControllerJUnitTest {
@Test
public void pulseUpdateForMembersList() throws Exception {
- mockMvc
- .perform(post("/pulseUpdate")
+ mockMvc.perform(
+ post("/pulseUpdate")
.param("pulseData", "{\"MembersList\":{\"memberName\":\"" + MEMBER_NAME + "\"}}")
- .principal(principal)
- .accept(MediaType.parseMediaType(MediaType.APPLICATION_JSON_VALUE)))
+ .principal(PRINCIPAL)
+ .accept(JSON_MEDIA_TYPE))
.andExpect(status().isOk())
.andExpect(jsonPath("$.MembersList.clusterMembers[0].name").value(MEMBER_NAME))
.andExpect(jsonPath("$.MembersList.clusterMembers[0].memberId").value(MEMBER_ID))
@@ -711,10 +615,10 @@ public class PulseControllerJUnitTest {
@Test
public void pulseUpdateForPulseVersion() throws Exception {
- mockMvc
- .perform(post("/pulseUpdate").param("pulseData", "{\"PulseVersion\":\"{}\"}")
- .principal(principal)
- .accept(MediaType.parseMediaType(MediaType.APPLICATION_JSON_VALUE)))
+ mockMvc.perform(
+ post("/pulseUpdate").param("pulseData", "{\"PulseVersion\":\"{}\"}")
+ .principal(PRINCIPAL)
+ .accept(JSON_MEDIA_TYPE))
.andExpect(status().isOk())
.andExpect(jsonPath("$.PulseVersion.sourceDate").value("not empty"))
.andExpect(jsonPath("$.PulseVersion.sourceRepository").value("not empty"))
@@ -726,22 +630,24 @@ public class PulseControllerJUnitTest {
@Test
public void pulseUpdateForQueryStatistics() throws Exception {
- mockMvc
- .perform(post("/pulseUpdate").param("pulseData", "{\"QueryStatistics\":\"{}\"}")
- .principal(principal)
- .accept(MediaType.parseMediaType(MediaType.APPLICATION_JSON_VALUE)))
- .andExpect(status().isOk()).andExpect(jsonPath("$.QueryStatistics.queriesList").isEmpty())
+ mockMvc.perform(
+ post("/pulseUpdate").param("pulseData", "{\"QueryStatistics\":\"{}\"}")
+ .principal(PRINCIPAL)
+ .accept(JSON_MEDIA_TYPE))
+ .andExpect(status().isOk())
+ .andExpect(jsonPath("$.QueryStatistics.queriesList").isEmpty())
.andExpect(jsonPath("$.QueryStatistics.connectedFlag").value(false))
.andExpect(jsonPath("$.QueryStatistics.connectedErrorMsg").value(""));
}
@Test
public void pulseUpdateForSystemAlerts() throws Exception {
- mockMvc
- .perform(post("/pulseUpdate")
- .param("pulseData", "{\"SystemAlerts\":{\"pageNumber\":\"1\"}}").principal(principal)
- .accept(MediaType.parseMediaType(MediaType.APPLICATION_JSON_VALUE)))
- .andExpect(status().isOk()).andExpect(jsonPath("$.SystemAlerts.pageNumber").value(1))
+ mockMvc.perform(
+ post("/pulseUpdate")
+ .param("pulseData", "{\"SystemAlerts\":{\"pageNumber\":\"1\"}}").principal(PRINCIPAL)
+ .accept(JSON_MEDIA_TYPE))
+ .andExpect(status().isOk())
+ .andExpect(jsonPath("$.SystemAlerts.pageNumber").value(1))
.andExpect(jsonPath("$.SystemAlerts.connectedFlag").value(false))
.andExpect(jsonPath("$.SystemAlerts.connectedErrorMsg").value(""))
.andExpect(jsonPath("$.SystemAlerts.systemAlerts").isEmpty());
@@ -749,26 +655,29 @@ public class PulseControllerJUnitTest {
@Test
public void authenticateUserNotLoggedIn() throws Exception {
- mockMvc
- .perform(get("/authenticateUser")
- .accept(MediaType.parseMediaType(MediaType.APPLICATION_JSON_VALUE)))
- .andExpect(status().isOk()).andExpect(jsonPath("$.isUserLoggedIn").value(false));
+ mockMvc.perform(
+ get("/authenticateUser")
+ .accept(JSON_MEDIA_TYPE))
+ .andExpect(status().isOk())
+ .andExpect(jsonPath("$.isUserLoggedIn").value(false));
}
@Test
public void authenticateUserLoggedIn() throws Exception {
- mockMvc
- .perform(get("/authenticateUser").principal(principal)
- .accept(MediaType.parseMediaType(MediaType.APPLICATION_JSON_VALUE)))
+ mockMvc.perform(
+ get("/authenticateUser")
+ .principal(PRINCIPAL)
+ .accept(JSON_MEDIA_TYPE))
.andExpect(status().isOk()).andExpect(jsonPath("$.isUserLoggedIn").value(true));
}
@Test
public void pulseVersion() throws Exception {
- mockMvc
- .perform(get("/pulseVersion")
- .accept(MediaType.parseMediaType(MediaType.APPLICATION_JSON_VALUE)))
- .andExpect(status().isOk()).andExpect(jsonPath("$.pulseVersion").isNotEmpty())
+ mockMvc.perform(
+ get("/pulseVersion")
+ .accept(JSON_MEDIA_TYPE))
+ .andExpect(status().isOk())
+ .andExpect(jsonPath("$.pulseVersion").isNotEmpty())
.andExpect(jsonPath("$.buildId").isNotEmpty())
.andExpect(jsonPath("$.buildDate").isNotEmpty())
.andExpect(jsonPath("$.sourceDate").isNotEmpty())
@@ -778,9 +687,12 @@ public class PulseControllerJUnitTest {
@Test
public void clearAlerts() throws Exception {
- mockMvc
- .perform(get("/clearAlerts").param("alertType", "1")
- .accept(MediaType.parseMediaType(MediaType.APPLICATION_JSON_VALUE)))
+ when(cluster.getNotificationPageNumber()).thenReturn(1);
+
+ mockMvc.perform(
+ get("/clearAlerts")
+ .param("alertType", "1")
+ .accept(JSON_MEDIA_TYPE))
.andExpect(status().isOk())
.andExpect(jsonPath("$.pageNumber").value(1))
.andExpect(jsonPath("$.systemAlerts").isEmpty())
@@ -790,17 +702,19 @@ public class PulseControllerJUnitTest {
@Test
public void acknowledgeAlert() throws Exception {
- mockMvc
- .perform(get("/acknowledgeAlert").param("alertId", "1")
- .accept(MediaType.parseMediaType(MediaType.APPLICATION_JSON_VALUE)))
- .andExpect(status().isOk()).andExpect(jsonPath("$.status").value("deleted"));
+ mockMvc.perform(
+ get("/acknowledgeAlert")
+ .param("alertId", "1")
+ .accept(JSON_MEDIA_TYPE))
+ .andExpect(status().isOk())
+ .andExpect(jsonPath("$.status").value("deleted"));
}
@Test
public void dataBrowserRegions() throws Exception {
- mockMvc
- .perform(get("/dataBrowserRegions")
- .accept(MediaType.parseMediaType(MediaType.APPLICATION_JSON_VALUE)))
+ mockMvc.perform(
+ get("/dataBrowserRegions")
+ .accept(JSON_MEDIA_TYPE))
.andExpect(status().isOk()).andExpect(jsonPath("$.clusterName").value(CLUSTER_NAME))
.andExpect(jsonPath("$.connectedFlag").value(false))
.andExpect(jsonPath("$.clusterRegions[0].fullPath").value(REGION_PATH))
@@ -809,126 +723,138 @@ public class PulseControllerJUnitTest {
@Test
public void dataBrowserQuery() throws Exception {
- doReturn(mapper.createObjectNode().put("foo", "bar")).when(cluster).executeQuery(anyString(),
- anyString(), anyInt());
+ ObjectNode queryResult = mapper.createObjectNode().put("foo", "bar");
+ when(cluster.executeQuery(any(), any(), anyInt())).thenReturn(queryResult);
String query = "SELECT * FROM " + REGION_PATH;
- mockMvc
- .perform(get("/dataBrowserQuery").param("query", query)
- .param("members", MEMBER_NAME).principal(principal)
- .accept(MediaType.parseMediaType(MediaType.APPLICATION_JSON_VALUE)))
- .andExpect(status().isOk()).andExpect(jsonPath("$.foo").value("bar"));
+ mockMvc.perform(
+ get("/dataBrowserQuery")
+ .param("query", query)
+ .param("members", MEMBER_NAME)
+ .principal(PRINCIPAL)
+ .accept(JSON_MEDIA_TYPE))
+ .andExpect(status().isOk())
+ .andExpect(jsonPath("$.foo").value("bar"));
- // Verify cluster addQueryInHistory is invoked
- verify(cluster).addQueryInHistory(query, principal.getName());
+ verify(cluster).addQueryInHistory(query, PRINCIPAL.getName());
}
@Test
public void dataBrowserQueryWithMessageResult() throws Exception {
String message = "Query is invalid due to error : Region mentioned in query probably missing /";
- doReturn(mapper.createObjectNode().put("message", message)).when(cluster).executeQuery(
- anyString(),
- anyString(), anyInt());
+ ObjectNode queryResult = mapper.createObjectNode().put("message", message);
+ when(cluster.executeQuery(any(), any(), anyInt())).thenReturn(queryResult);
String query = "SELECT * FROM " + REGION_PATH;
- mockMvc
- .perform(get("/dataBrowserQuery").param("query", query)
- .param("members", MEMBER_NAME).principal(principal)
- .accept(MediaType.parseMediaType(MediaType.APPLICATION_JSON_VALUE)))
- .andExpect(status().isOk()).andExpect(jsonPath("$.message").value(message));
+ mockMvc.perform(
+ get("/dataBrowserQuery")
+ .param("query", query)
+ .param("members", MEMBER_NAME)
+ .principal(PRINCIPAL)
+ .accept(JSON_MEDIA_TYPE))
+ .andExpect(status().isOk())
+ .andExpect(jsonPath("$.message").value(message));
- // Verify cluster addQueryInHistory is invoked
- verify(cluster).addQueryInHistory(query, principal.getName());
+ verify(cluster).addQueryInHistory(query, PRINCIPAL.getName());
}
@Test
public void dataBrowserQueryWithExceptionResult() throws Exception {
- doThrow(new IllegalStateException()).when(cluster).executeQuery(anyString(),
- anyString(), anyInt());
+ when(cluster.executeQuery(any(), any(), anyInt())).thenThrow(IllegalStateException.class);
String query = "SELECT * FROM " + REGION_PATH;
- mockMvc
- .perform(get("/dataBrowserQuery").param("query", query)
- .param("members", MEMBER_NAME).principal(principal)
- .accept(MediaType.parseMediaType(MediaType.APPLICATION_JSON_VALUE)))
- .andExpect(status().isOk()).andExpect(content().string("{}"));
+ mockMvc.perform(
+ get("/dataBrowserQuery")
+ .param("query", query)
+ .param("members", MEMBER_NAME)
+ .principal(PRINCIPAL)
+ .accept(JSON_MEDIA_TYPE))
+ .andExpect(status().isOk())
+ .andExpect(content().string("{}"));
- // Verify cluster addQueryInHistory is invoked
- verify(cluster).addQueryInHistory(query, principal.getName());
+ verify(cluster).addQueryInHistory(query, PRINCIPAL.getName());
}
@Test
public void dataBrowserExport() throws Exception {
- doReturn(mapper.createObjectNode().put("foo", "bar")).when(cluster).executeQuery(anyString(),
- anyString(), anyInt());
+ ObjectNode queryResult = mapper.createObjectNode().put("foo", "bar");
+ when(cluster.executeQuery(any(), any(), anyInt())).thenReturn(queryResult);
String query = "SELECT * FROM " + REGION_PATH;
- mockMvc
- .perform(get("/dataBrowserExport").param("query", query)
- .param("members", MEMBER_NAME).principal(principal)
- .accept(MediaType.parseMediaType(MediaType.APPLICATION_JSON_VALUE)))
+ mockMvc.perform(
+ get("/dataBrowserExport")
+ .param("query", query)
+ .param("members", MEMBER_NAME)
+ .principal(PRINCIPAL)
+ .accept(JSON_MEDIA_TYPE))
.andExpect(status().isOk())
.andExpect(header().string("Content-Disposition", "attachment; filename=results.json"))
.andExpect(jsonPath("$.foo").value("bar"));
- // Verify cluster addQueryInHistory is invoked
- verify(cluster).addQueryInHistory(query, principal.getName());
+ verify(cluster).addQueryInHistory(query, PRINCIPAL.getName());
}
@Test
public void dataBrowserExportWithMessageResult() throws Exception {
String message = "Query is invalid due to error : Region mentioned in query probably missing /";
- doReturn(mapper.createObjectNode().put("message", message)).when(cluster).executeQuery(
- anyString(),
- anyString(), anyInt());
+ ObjectNode queryResult = mapper.createObjectNode().put("message", message);
+ when(cluster.executeQuery(any(), any(), anyInt())).thenReturn(queryResult);
String query = "SELECT * FROM " + REGION_PATH;
- mockMvc
- .perform(get("/dataBrowserExport").param("query", query)
- .param("members", MEMBER_NAME).principal(principal)
- .accept(MediaType.parseMediaType(MediaType.APPLICATION_JSON_VALUE)))
+ mockMvc.perform(
+ get("/dataBrowserExport")
+ .param("query", query)
+ .param("members", MEMBER_NAME)
+ .principal(PRINCIPAL)
+ .accept(JSON_MEDIA_TYPE))
.andExpect(status().isOk())
.andExpect(header().string("Content-Disposition", "attachment; filename=results.json"))
.andExpect(jsonPath("$.message").value(message));
- // Verify cluster addQueryInHistory is invoked
- verify(cluster).addQueryInHistory(query, principal.getName());
+ verify(cluster).addQueryInHistory(query, PRINCIPAL.getName());
}
@Test
public void dataBrowserExportWithExceptionResult() throws Exception {
- doThrow(new IllegalStateException()).when(cluster).executeQuery(anyString(),
- anyString(), anyInt());
+ when(cluster.executeQuery(any(), any(), anyInt())).thenThrow(IllegalStateException.class);
String query = "SELECT * FROM " + REGION_PATH;
- mockMvc
- .perform(get("/dataBrowserExport").param("query", query)
- .param("members", MEMBER_NAME).principal(principal)
- .accept(MediaType.parseMediaType(MediaType.APPLICATION_JSON_VALUE)))
+ mockMvc.perform(
+ get("/dataBrowserExport")
+ .param("query", query)
+ .param("members", MEMBER_NAME)
+ .principal(PRINCIPAL)
+ .accept(JSON_MEDIA_TYPE))
.andExpect(status().isOk())
.andExpect(header().string("Content-Disposition", "attachment; filename=results.json"))
.andExpect(content().string("{}"));
- // Verify cluster addQueryInHistory is invoked
- verify(cluster).addQueryInHistory(query, principal.getName());
+ verify(cluster).addQueryInHistory(query, PRINCIPAL.getName());
}
@Test
public void dataBrowserQueryHistory() throws Exception {
- dataBrowserQuery();
+ String query = "\"SELECT * FROM " + REGION_PATH + "\"";
+ ArrayNode queryHistory = mapper.createArrayNode();
+ queryHistory.addObject().put("queryText", query);
+
+ when(cluster.getQueryHistoryByUserId(PRINCIPAL_USER)).thenReturn(queryHistory);
- mockMvc
- .perform(get("/dataBrowserQueryHistory").param("action", "view").principal(principal)
- .accept(MediaType.parseMediaType(MediaType.APPLICATION_JSON_VALUE)))
- .andExpect(status().isOk()).andExpect(
- jsonPath("$.queryHistory[0].queryText").value("\"SELECT * FROM " + REGION_PATH + "\""));
+ mockMvc.perform(
+ get("/dataBrowserQueryHistory")
+ .param("action", "view")
+ .principal(PRINCIPAL)
+ .accept(JSON_MEDIA_TYPE))
+ .andExpect(status().isOk())
+ .andExpect(jsonPath("$.queryHistory[0].queryText").value(query));
}
@Test
public void getQueryStatisticsGridModel() throws Exception {
- mockMvc
- .perform(get("/getQueryStatisticsGridModel").principal(principal)
- .accept(MediaType.parseMediaType(MediaType.APPLICATION_JSON_VALUE)))
+ mockMvc.perform(
+ get("/getQueryStatisticsGridModel")
+ .principal(PRINCIPAL)
+ .accept(JSON_MEDIA_TYPE))
.andExpect(status().isOk())
.andExpect(jsonPath("$.columnNames",
containsInAnyOrder("Query", "NumExecution", "TotalExecutionTime(ns)",
@@ -938,4 +864,71 @@ public class PulseControllerJUnitTest {
"ExecutionTime(ns)", "ProjectionTime(ns)", "RowsModificationTime(ns)",
"QNNumRowsSeen", "QNMsgSendTime(ns)", "QNMsgSerTime(ns)", "QNRespDeSerTime(ns)")));
}
+
+ private void prepareCluster() {
+ when(cluster.getAlertsList()).thenReturn(array());
+ when(cluster.getStatements()).thenReturn(array());
+ when(cluster.getConnectionErrorMsg()).thenReturn("");
+ when(cluster.getServerName()).thenReturn(CLUSTER_NAME);
+
+ when(cluster.getStatisticTrend(CLUSTER_STAT_MEMORY_USAGE)).thenReturn(array(1, 2, 3));
+ when(cluster.getStatisticTrend(CLUSTER_STAT_THROUGHPUT_READS)).thenReturn(array(1, 2, 3));
+ when(cluster.getStatisticTrend(CLUSTER_STAT_THROUGHPUT_WRITES)).thenReturn(array(4, 5, 6));
+ when(cluster.getStatisticTrend(CLUSTER_STAT_GARBAGE_COLLECTION)).thenReturn(array());
+ when(cluster.getGarbageCollectionCount()).thenReturn(0L);
+ when(cluster.getNotificationPageNumber()).thenReturn(1);
+
+ Cluster.RegionOnMember regionOnMember = new Cluster.RegionOnMember();
+ regionOnMember.setRegionFullPath(REGION_PATH);
+ regionOnMember.setMemberName(MEMBER_NAME);
+
+ Cluster.Region clusterRegion = new Cluster.Region();
+ clusterRegion.setName(REGION_NAME);
+ clusterRegion.setFullPath(REGION_PATH);
+ clusterRegion.setRegionType(REGION_TYPE);
+ clusterRegion.setMemberCount(1);
+ clusterRegion.setMemberName(singletonList(MEMBER_NAME));
+ clusterRegion.setPutsRate(12.31D);
+ clusterRegion.setGetsRate(27.99D);
+ clusterRegion.setRegionOnMembers(singletonList(regionOnMember));
+
+ when(cluster.getClusterRegion(REGION_PATH)).thenReturn(clusterRegion);
+
+ HashMap<String, Cluster.Region> clusterRegions = new HashMap<>();
+ clusterRegions.put(REGION_NAME, clusterRegion);
+ when(cluster.getClusterRegions()).thenReturn(clusterRegions);
+
+ Cluster.Member member = new Cluster.Member();
+ member.setId(MEMBER_ID);
+ member.setName(MEMBER_NAME);
+ member.setUptime(1L);
+ member.setHost(PHYSICAL_HOST_NAME);
+ member.setGemfireVersion(GEMFIRE_VERSION);
+ member.setCpuUsage(55.77123D);
+
+ member.setMemberRegions(clusterRegions);
+
+ Cluster.AsyncEventQueue aeq = new Cluster.AsyncEventQueue();
+ aeq.setAsyncEventListener(AEQ_LISTENER);
+ member.setAsyncEventQueueList(singletonList(aeq));
+
+ Cluster.Client client = new Cluster.Client();
+ client.setId("100");
+ client.setName(CLIENT_NAME);
+ client.setUptime(1L);
+
+ HashMap<String, Cluster.Client> memberClientsHMap = new HashMap<>();
+ memberClientsHMap.put(CLIENT_NAME, client);
+ member.setMemberClientsHMap(memberClientsHMap);
+
+ HashMap<String, Cluster.Member> membersHMap = new HashMap<>();
+ membersHMap.put(MEMBER_NAME, member);
+ when(cluster.getMembersHMap()).thenReturn(membersHMap);
+ when(cluster.getMembers()).thenReturn(array(member));
+ when(cluster.getMemberCount()).thenReturn(0);
+ when(cluster.getMember(anyString())).thenReturn(member);
+
+ List<Cluster.Member> members = singletonList(member);
+ when(cluster.getPhysicalToMember()).thenReturn(singletonMap(PHYSICAL_HOST_NAME, members));
+ }
}
diff --git a/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/security/GemfireSecurityConfig.java b/geode-pulse/src/integrationTest/java/org/apache/geode/tools/pulse/internal/context/OAuthSecurityTokenHandoffTestConfig.java
similarity index 50%
copy from geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/security/GemfireSecurityConfig.java
copy to geode-pulse/src/integrationTest/java/org/apache/geode/tools/pulse/internal/context/OAuthSecurityTokenHandoffTestConfig.java
index 917a698..7ce8da3 100644
--- a/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/security/GemfireSecurityConfig.java
+++ b/geode-pulse/src/integrationTest/java/org/apache/geode/tools/pulse/internal/context/OAuthSecurityTokenHandoffTestConfig.java
@@ -13,31 +13,31 @@
* the License.
*/
-package org.apache.geode.tools.pulse.internal.security;
+package org.apache.geode.tools.pulse.internal.context;
+
+import static org.mockito.Mockito.mock;
-import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Primary;
import org.springframework.context.annotation.Profile;
-import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
-import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
-import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
+import org.springframework.security.oauth2.client.OAuth2AuthorizedClientService;
+
+import org.apache.geode.tools.pulse.internal.data.ClusterFactory;
+import org.apache.geode.tools.pulse.internal.data.Repository;
@Configuration
-@EnableWebSecurity
-@EnableGlobalMethodSecurity(prePostEnabled = true)
-@Profile("pulse.authentication.gemfire")
-public class GemfireSecurityConfig extends DefaultSecurityConfig {
+@Primary
+@Profile("pulse.oauth.security.token.test")
+public class OAuthSecurityTokenHandoffTestConfig {
@Bean
- public GemFireAuthenticationProvider gemAuthenticationProvider() {
- return new GemFireAuthenticationProvider();
+ public ClusterFactory clusterFactory() {
+ return mock(ClusterFactory.class);
}
- @Autowired
- GemFireAuthenticationProvider gemAuthenticationProvider;
-
- @Override
- protected void configure(AuthenticationManagerBuilder authenticationManagerBuilder) {
- authenticationManagerBuilder.authenticationProvider(gemAuthenticationProvider);
+ @Bean
+ public Repository repository(OAuth2AuthorizedClientService authorizedClientService,
+ ClusterFactory clusterFactory) {
+ return new Repository(authorizedClientService, clusterFactory);
}
}
diff --git a/geode-pulse/src/integrationTest/java/org/apache/geode/tools/pulse/internal/context/PulseControllerTestContext.java b/geode-pulse/src/integrationTest/java/org/apache/geode/tools/pulse/internal/context/PulseControllerTestContext.java
new file mode 100644
index 0000000..f61e041
--- /dev/null
+++ b/geode-pulse/src/integrationTest/java/org/apache/geode/tools/pulse/internal/context/PulseControllerTestContext.java
@@ -0,0 +1,90 @@
+/*
+ * 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.tools.pulse.internal.context;
+
+import static java.util.Collections.enumeration;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Properties;
+import java.util.ResourceBundle;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Profile;
+
+import org.apache.geode.tools.pulse.internal.PropertiesFileLoader;
+import org.apache.geode.tools.pulse.internal.data.PulseConstants;
+import org.apache.geode.tools.pulse.internal.data.Repository;
+
+@Configuration
+@Profile("pulse.controller.test")
+public class PulseControllerTestContext {
+
+ @Bean
+ public Repository repository() {
+ Repository repository = mock(Repository.class);
+ ResourceBundle resourceBundle = getResourceBundle();
+ when(repository.getResourceBundle()).thenReturn(resourceBundle);
+ return repository;
+ }
+
+ @Bean(name = "logoutTargetURL")
+ public String defaultLogoutTargetURL() {
+ return "/login.html";
+ }
+
+ @Bean
+ public PropertiesFileLoader propertiesLoader() {
+ PropertiesFileLoader propertiesFileLoader = mock(PropertiesFileLoader.class);
+ Properties properties = new Properties();
+ properties.setProperty(PulseConstants.PROPERTY_BUILD_DATE, "not empty");
+ properties.setProperty(PulseConstants.PROPERTY_BUILD_ID, "not empty");
+ properties.setProperty(PulseConstants.PROPERTY_PULSE_VERSION, "not empty");
+ properties.setProperty(PulseConstants.PROPERTY_SOURCE_DATE, "not empty");
+ properties.setProperty(PulseConstants.PROPERTY_SOURCE_REPOSITORY, "not empty");
+ properties.setProperty(PulseConstants.PROPERTY_SOURCE_REVISION, "not empty");
+
+ when(propertiesFileLoader.loadProperties(any(), any())).thenReturn(properties);
+
+ return propertiesFileLoader;
+ }
+
+ private ResourceBundle getResourceBundle() {
+ return new ResourceBundle() {
+ Map<String, Object> objects = new HashMap<>();
+
+ @Override
+ protected Object handleGetObject(String key) {
+ objects.put(key, key);
+ return key;
+ }
+
+ @Override
+ public Enumeration<String> getKeys() {
+ return enumeration(objects.keySet());
+ }
+ };
+ }
+}
diff --git a/geode-pulse/src/integrationTest/java/org/apache/geode/tools/pulse/security/CustomSecurityConfigTest.java b/geode-pulse/src/integrationTest/java/org/apache/geode/tools/pulse/security/CustomSecurityConfigTest.java
index 8c54ea3..e772c7b 100644
--- a/geode-pulse/src/integrationTest/java/org/apache/geode/tools/pulse/security/CustomSecurityConfigTest.java
+++ b/geode-pulse/src/integrationTest/java/org/apache/geode/tools/pulse/security/CustomSecurityConfigTest.java
@@ -28,15 +28,13 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringRunner;
-import org.springframework.test.context.web.GenericXmlWebContextLoader;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;
@RunWith(SpringRunner.class)
-@ContextConfiguration(locations = {"classpath*:WEB-INF/pulse-servlet.xml"},
- loader = GenericXmlWebContextLoader.class)
+@ContextConfiguration(locations = {"classpath*:WEB-INF/pulse-servlet.xml"})
@WebAppConfiguration
@ActiveProfiles({"pulse.authentication.custom"})
public class CustomSecurityConfigTest {
diff --git a/geode-pulse/src/integrationTest/java/org/apache/geode/tools/pulse/security/DefaultSecurityConfigTest.java b/geode-pulse/src/integrationTest/java/org/apache/geode/tools/pulse/security/DefaultSecurityConfigTest.java
index 2304c2c..9b0e0eb 100644
--- a/geode-pulse/src/integrationTest/java/org/apache/geode/tools/pulse/security/DefaultSecurityConfigTest.java
+++ b/geode-pulse/src/integrationTest/java/org/apache/geode/tools/pulse/security/DefaultSecurityConfigTest.java
@@ -28,15 +28,13 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringRunner;
-import org.springframework.test.context.web.GenericXmlWebContextLoader;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;
@RunWith(SpringRunner.class)
-@ContextConfiguration(locations = {"classpath*:WEB-INF/pulse-servlet.xml"},
- loader = GenericXmlWebContextLoader.class)
+@ContextConfiguration(locations = {"classpath*:WEB-INF/pulse-servlet.xml"})
@WebAppConfiguration
@ActiveProfiles({"pulse.authentication.default"})
public class DefaultSecurityConfigTest {
diff --git a/geode-pulse/src/integrationTest/java/org/apache/geode/tools/pulse/security/OAuthSecurityConfigTest.java b/geode-pulse/src/integrationTest/java/org/apache/geode/tools/pulse/security/OAuthSecurityConfigTest.java
index e5b5be4..608391d 100644
--- a/geode-pulse/src/integrationTest/java/org/apache/geode/tools/pulse/security/OAuthSecurityConfigTest.java
+++ b/geode-pulse/src/integrationTest/java/org/apache/geode/tools/pulse/security/OAuthSecurityConfigTest.java
@@ -15,11 +15,19 @@
package org.apache.geode.tools.pulse.security;
+import static java.lang.String.format;
+import static org.assertj.core.api.Assertions.assertThat;
import static org.springframework.security.test.web.servlet.setup.SecurityMockMvcConfigurers.springSecurity;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.redirectedUrl;
-import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.redirectedUrlPattern;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
+import static org.springframework.web.util.UriComponentsBuilder.fromUriString;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Properties;
import org.junit.Before;
import org.junit.Test;
@@ -28,18 +36,29 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringRunner;
-import org.springframework.test.context.web.GenericXmlWebContextLoader;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.test.web.servlet.MockMvc;
+import org.springframework.test.web.servlet.ResultMatcher;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;
@RunWith(SpringRunner.class)
-@ContextConfiguration(locations = {"classpath*:WEB-INF/pulse-servlet.xml"},
- loader = GenericXmlWebContextLoader.class)
@WebAppConfiguration
+@ContextConfiguration("classpath*:WEB-INF/pulse-servlet.xml")
@ActiveProfiles({"pulse.authentication.oauth"})
public class OAuthSecurityConfigTest {
+ // When Spring needs to authorize the user via OAuth, it redirects to this URL, which Spring
+ // defined based on the OAuth provider we configured. This URL then redirects to the authorization
+ // URI we configured for that provider.
+ private static final String SPRING_AUTHORIZATION_URL_FOR_OAUTH_PROVIDER =
+ "http://localhost/oauth2/authorization/%s";
+
+ // The URL to which the OAuth provider will redirect with the authorization code.
+ private static final String PULSE_REDIRECT_URL_FOR_OAUTH_PROVIDER =
+ "http://localhost/login/oauth2/code/%s";
+
+ private final Properties pulseProperties = new Properties();
+
@Autowired
private WebApplicationContext context;
@@ -51,15 +70,76 @@ public class OAuthSecurityConfigTest {
.webAppContextSetup(context)
.apply(springSecurity())
.build();
+
+ try (InputStream propertiesStream = getClass().getClassLoader()
+ .getResourceAsStream("pulse.properties")) {
+ pulseProperties.load(propertiesStream);
+ } catch (IOException cause) {
+ throw new RuntimeException("Unable to load pulse.properties for test");
+ }
}
@Test
- public void redirectToOauth() throws Exception {
- mvc.perform(get("/login.html")).andExpect(status().is3xxRedirection())
- .andExpect(redirectedUrl(("http://localhost/oauth2/authorization/uaa")));
+ public void visitingProtectedUrlRedirectsUnauthenticatedUserToOAuthClientURL() throws Exception {
+ String pulseOAuthProvider = property("pulse.oauth.providerId");
+ String aProtectedUrl = "/login.html";
+
+ mvc.perform(get(aProtectedUrl))
+ .andExpect(status().is3xxRedirection())
+ .andExpect(redirectedUrl(springAuthorizationUrlFor(pulseOAuthProvider)));
+ }
+
+ @Test
+ public void oauthClientURLRedirectsToOPulseOAuthAuthorizationURL() throws Exception {
+ String pulseOAuthProvider = property("pulse.oauth.providerId");
+ String pulseOAuthClientId = property("pulse.oauth.clientId");
+ String pulseOAuthAuthorizationUri = property("pulse.oauth.authorizationUri");
+
+ Map<String, String> expectedRedirectParams = new HashMap<>();
+ expectedRedirectParams.put("response_type", "code");
+ expectedRedirectParams.put("client_id", pulseOAuthClientId);
+ expectedRedirectParams.put("redirect_uri", pulseRedirectUrlFor(pulseOAuthProvider));
- mvc.perform(get("http://localhost/oauth2/authorization/uaa"))
+ mvc.perform(get(springAuthorizationUrlFor(pulseOAuthProvider)))
.andExpect(status().is3xxRedirection())
- .andExpect(redirectedUrlPattern("http://example.com/uaa/oauth/**"));
+ .andExpect(redirectedUrlPath(pulseOAuthAuthorizationUri))
+ .andExpect(redirectedUrlParams(expectedRedirectParams));
+ }
+
+ private static ResultMatcher redirectedUrlPath(String expectedPath) {
+ return result -> {
+ String redirectedUrlString = result.getResponse().getRedirectedUrl();
+ assertThat(redirectedUrlString).isNotNull();
+ String actualPath = redirectedUrlString.split("[?#]")[0];
+ assertThat(actualPath)
+ .as("redirect URL path")
+ .startsWith(expectedPath);
+ };
+ }
+
+ private static ResultMatcher redirectedUrlParams(Map<String, String> expectedParams) {
+ return result -> {
+ String redirectedUrlString = result.getResponse().getRedirectedUrl();
+ assertThat(redirectedUrlString).isNotNull();
+ Map<String, String> actualParams = fromUriString(redirectedUrlString)
+ .build()
+ .getQueryParams()
+ .toSingleValueMap();
+ assertThat(actualParams)
+ .as("redirected URL params")
+ .containsAllEntriesOf(expectedParams);
+ };
+ }
+
+ private String property(String name) {
+ return pulseProperties.getProperty(name);
+ }
+
+ private static String pulseRedirectUrlFor(String provider) {
+ return format(PULSE_REDIRECT_URL_FOR_OAUTH_PROVIDER, provider);
+ }
+
+ private static String springAuthorizationUrlFor(String pulseOAuthProvider) {
+ return format(SPRING_AUTHORIZATION_URL_FOR_OAUTH_PROVIDER, pulseOAuthProvider);
}
}
diff --git a/geode-pulse/src/integrationTest/java/org/apache/geode/tools/pulse/security/OAuthSecurityTokenHandoffTest.java b/geode-pulse/src/integrationTest/java/org/apache/geode/tools/pulse/security/OAuthSecurityTokenHandoffTest.java
new file mode 100644
index 0000000..bf10319
--- /dev/null
+++ b/geode-pulse/src/integrationTest/java/org/apache/geode/tools/pulse/security/OAuthSecurityTokenHandoffTest.java
@@ -0,0 +1,154 @@
+/*
+ * 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.tools.pulse.security;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+import static org.springframework.security.oauth2.core.AuthorizationGrantType.AUTHORIZATION_CODE;
+import static org.springframework.security.oauth2.core.OAuth2AccessToken.TokenType.BEARER;
+import static org.springframework.security.test.web.servlet.setup.SecurityMockMvcConfigurers.springSecurity;
+import static org.springframework.security.web.context.HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY;
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
+
+import java.time.Duration;
+import java.time.Instant;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.mock.web.MockHttpSession;
+import org.springframework.security.core.GrantedAuthority;
+import org.springframework.security.core.context.SecurityContextImpl;
+import org.springframework.security.oauth2.client.OAuth2AuthorizedClient;
+import org.springframework.security.oauth2.client.OAuth2AuthorizedClientService;
+import org.springframework.security.oauth2.client.authentication.OAuth2AuthenticationToken;
+import org.springframework.security.oauth2.client.registration.ClientRegistration;
+import org.springframework.security.oauth2.core.OAuth2AccessToken;
+import org.springframework.security.oauth2.core.user.DefaultOAuth2User;
+import org.springframework.security.oauth2.core.user.OAuth2User;
+import org.springframework.security.oauth2.core.user.OAuth2UserAuthority;
+import org.springframework.test.context.ActiveProfiles;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringRunner;
+import org.springframework.test.context.web.WebAppConfiguration;
+import org.springframework.test.web.servlet.MockMvc;
+import org.springframework.test.web.servlet.setup.MockMvcBuilders;
+import org.springframework.web.context.WebApplicationContext;
+
+import org.apache.geode.tools.pulse.internal.data.Cluster;
+import org.apache.geode.tools.pulse.internal.data.ClusterFactory;
+
+@RunWith(SpringRunner.class)
+@WebAppConfiguration
+@ContextConfiguration("classpath*:WEB-INF/pulse-servlet.xml")
+@ActiveProfiles({"pulse.oauth.security.token.test", "pulse.authentication.oauth"})
+public class OAuthSecurityTokenHandoffTest {
+ private static final String AUTHENTICATION_PROVIDER_ID = "uaa";
+ private MockMvc mvc;
+
+ @Autowired
+ private ClusterFactory clusterFactory;
+
+ @Autowired
+ private OAuth2AuthorizedClientService authorizedClientService;
+
+ @Autowired
+ private WebApplicationContext context;
+
+ @Before
+ public void setup() {
+ mvc = MockMvcBuilders
+ .webAppContextSetup(context)
+ .apply(springSecurity())
+ .build();
+ }
+
+ @Test
+ public void usesCurrentSessionAccessTokenAsCredentialToConnectToGemFire() throws Exception {
+ String userName = "some-user-name";
+ String accessTokenValue = "the-access-token-value";
+ String urlThatTriggersPulseToConnectToGemFire = "/dataBrowserRegions";
+
+ Cluster clusterForUser = mock(Cluster.class);
+ when(clusterFactory.create(any(), any(), eq(userName), any(), any()))
+ .thenReturn(clusterForUser);
+
+ MockHttpSession session = sessionWithAuthenticatedUser(userName, accessTokenValue);
+
+ mvc.perform(get(urlThatTriggersPulseToConnectToGemFire).session(session));
+
+ verify(clusterForUser).connectToGemFire(accessTokenValue);
+ }
+
+ private void authorizeClient(
+ OAuth2AuthenticationToken authenticationToken, OAuth2AccessToken accessToken) {
+ OAuth2AuthorizedClient authorizedClient =
+ new OAuth2AuthorizedClient(clientRegistration(),
+ authenticationToken.getPrincipal().getName(), accessToken);
+ authorizedClientService.saveAuthorizedClient(authorizedClient, authenticationToken);
+ }
+
+ private MockHttpSession sessionWithAuthenticatedUser(String username, String tokenValue) {
+ OAuth2AuthenticationToken authenticationToken = authenticationToken(username);
+ authorizeClient(authenticationToken, accessToken(tokenValue));
+ return sessionWithAuthenticationToken(authenticationToken);
+ }
+
+ private static OAuth2AccessToken accessToken(String tokenValue) {
+ return new OAuth2AccessToken(BEARER, tokenValue, Instant.now(),
+ Instant.now().plus(Duration.ofHours(1)));
+ }
+
+ private static OAuth2AuthenticationToken authenticationToken(String userName) {
+ Map<String, Object> attributes = new HashMap<>();
+ attributes.put("sub", userName);
+
+ List<GrantedAuthority> authorities = Arrays.asList(
+ new OAuth2UserAuthority("ROLE_USER", attributes),
+ new OAuth2UserAuthority("SCOPE_CLUSTER:READ", attributes),
+ new OAuth2UserAuthority("SCOPE_CLUSTER:WRITE", attributes),
+ new OAuth2UserAuthority("SCOPE_DATA:READ", attributes),
+ new OAuth2UserAuthority("SCOPE_DATA:WRITE", attributes));
+ OAuth2User user = new DefaultOAuth2User(authorities, attributes, "sub");
+ return new OAuth2AuthenticationToken(user, authorities, AUTHENTICATION_PROVIDER_ID);
+ }
+
+ private static ClientRegistration clientRegistration() {
+ return ClientRegistration
+ .withRegistrationId(AUTHENTICATION_PROVIDER_ID)
+ .authorizationGrantType(AUTHORIZATION_CODE)
+ .redirectUriTemplate("{baseUrl}/oauth2/code/{registrationId}")
+ .clientId("client-id")
+ .authorizationUri("authorization-uri")
+ .tokenUri("token-uri")
+ .build();
+ }
+
+ private static MockHttpSession sessionWithAuthenticationToken(
+ OAuth2AuthenticationToken authenticationToken) {
+ MockHttpSession session = new MockHttpSession();
+ session.setAttribute(SPRING_SECURITY_CONTEXT_KEY, new SecurityContextImpl(authenticationToken));
+ return session;
+ }
+}
diff --git a/geode-pulse/src/integrationTest/resources/pulse.properties b/geode-pulse/src/integrationTest/resources/pulse.properties
index e06fd2d..b7607ae 100644
--- a/geode-pulse/src/integrationTest/resources/pulse.properties
+++ b/geode-pulse/src/integrationTest/resources/pulse.properties
@@ -13,11 +13,12 @@
# the License.
#
-pulse.oauth.provider=uaa
+pulse.oauth.providerId=uaa
+pulse.oauth.providerName=UAA
pulse.oauth.clientId=pulse
pulse.oauth.clientSecret=secret
pulse.oauth.authorizationUri=http://example.com/uaa/oauth/authorize
pulse.oauth.tokenUri=http://example.com/uaa/oauth/token
pulse.oauth.userInfoUri=http://example.com/uaa/userinfo
pulse.oauth.jwkSetUri=http://example.com/uaa/token_keys
-pulse.oauth.userNameAttributeName=user_name
\ No newline at end of file
+pulse.oauth.userNameAttributeName=sub
diff --git a/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/ClassPathPropertiesFileLoader.java b/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/ClassPathPropertiesFileLoader.java
new file mode 100644
index 0000000..8a1c118
--- /dev/null
+++ b/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/ClassPathPropertiesFileLoader.java
@@ -0,0 +1,44 @@
+/*
+ * 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.tools.pulse.internal;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Properties;
+import java.util.ResourceBundle;
+
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+import org.springframework.stereotype.Component;
+
+@Component
+public class ClassPathPropertiesFileLoader implements PropertiesFileLoader {
+ private static final Logger logger = LogManager.getLogger();
+
+ @Override
+ public Properties loadProperties(String propertyFile, ResourceBundle resourceBundle) {
+ final Properties properties = new Properties();
+ try (final InputStream stream =
+ Thread.currentThread().getContextClassLoader().getResourceAsStream(propertyFile)) {
+ logger.info(propertyFile + " " + resourceBundle.getString("LOG_MSG_FILE_FOUND"));
+ properties.load(stream);
+ } catch (IOException e) {
+ logger.error(resourceBundle.getString("LOG_MSG_EXCEPTION_LOADING_PROPERTIES_FILE"), e);
+ }
+
+ return properties;
+ }
+}
diff --git a/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/data/IClusterUpdater.java b/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/PropertiesFileLoader.java
similarity index 60%
copy from geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/data/IClusterUpdater.java
copy to geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/PropertiesFileLoader.java
index 942384a..98fd885 100644
--- a/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/data/IClusterUpdater.java
+++ b/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/PropertiesFileLoader.java
@@ -1,5 +1,4 @@
/*
- *
* 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
@@ -12,27 +11,13 @@
* 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.tools.pulse.internal.data;
-
-import javax.management.remote.JMXConnector;
-
-import com.fasterxml.jackson.databind.node.ObjectNode;
-
-/**
- * Interface having updateData() function which is implemented by JMXDataUpdater
- *
- * @since GemFire version 7.0.Beta 2012-09-23
- *
- */
-public interface IClusterUpdater {
- boolean updateData();
+package org.apache.geode.tools.pulse.internal;
- ObjectNode executeQuery(String queryText, String members, int limit);
+import java.util.Properties;
+import java.util.ResourceBundle;
- default JMXConnector connect(String username, String password) {
- return null;
- }
+public interface PropertiesFileLoader {
+ Properties loadProperties(String propertyFile, ResourceBundle resourceBundle);
}
diff --git a/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/PulseAppListener.java b/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/PulseAppListener.java
index b7d526a..9862068 100644
--- a/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/PulseAppListener.java
+++ b/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/PulseAppListener.java
@@ -17,19 +17,22 @@
package org.apache.geode.tools.pulse.internal;
-import java.io.IOException;
-import java.io.InputStream;
import java.util.Map.Entry;
import java.util.Properties;
import java.util.ResourceBundle;
import java.util.Set;
-import java.util.function.BiFunction;
-import javax.servlet.ServletContextEvent;
-import javax.servlet.ServletContextListener;
+import javax.servlet.ServletContext;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.ApplicationEvent;
+import org.springframework.context.ApplicationListener;
+import org.springframework.context.event.ContextClosedEvent;
+import org.springframework.context.event.ContextRefreshedEvent;
+import org.springframework.stereotype.Component;
+import org.springframework.web.context.WebApplicationContext;
import org.apache.geode.tools.pulse.internal.controllers.PulseController;
import org.apache.geode.tools.pulse.internal.data.PulseConstants;
@@ -39,47 +42,46 @@ import org.apache.geode.tools.pulse.internal.data.Repository;
* This class is used for checking the application running mode i.e. Embedded or not
*
* @since GemFire version 7.0.Beta 2012-09-23
- *
*/
-// @WebListener
-public class PulseAppListener implements ServletContextListener {
+@Component
+public class PulseAppListener implements ApplicationListener<ApplicationEvent> {
private static final Logger logger = LogManager.getLogger();
private static final String GEODE_SSLCONFIG_SERVLET_CONTEXT_PARAM = "org.apache.geode.sslConfig";
private final boolean isEmbedded;
private final Repository repository;
private final ResourceBundle resourceBundle;
- private final BiFunction<String, ResourceBundle, Properties> propertiesFileLoader;
-
- public PulseAppListener() {
- this(Boolean.getBoolean(PulseConstants.SYSTEM_PROPERTY_PULSE_EMBEDDED), Repository.get(),
- PulseAppListener::loadPropertiesFromFile);
+ private final PropertiesFileLoader propertiesFileLoader;
+ private final PulseController pulseController;
+
+ @Autowired
+ public PulseAppListener(PulseController pulseController, Repository repository,
+ PropertiesFileLoader propertiesLoader) {
+ this(Boolean.getBoolean(PulseConstants.SYSTEM_PROPERTY_PULSE_EMBEDDED),
+ propertiesLoader, pulseController, repository);
}
- public PulseAppListener(boolean isEmbedded, Repository repository,
- BiFunction<String, ResourceBundle, Properties> propertiesFileLoader) {
+ public PulseAppListener(boolean isEmbedded, PropertiesFileLoader propertiesFileLoader,
+ PulseController pulseController, Repository repository) {
this.isEmbedded = isEmbedded;
- this.repository = repository;
- this.resourceBundle = repository.getResourceBundle();
this.propertiesFileLoader = propertiesFileLoader;
+ this.pulseController = pulseController;
+ this.repository = repository;
+ resourceBundle = repository.getResourceBundle();
}
@Override
- public void contextDestroyed(ServletContextEvent event) {
-
- // Stop all running threads those are created in Pulse
- // Stop cluster threads
- repository.removeAllClusters();
-
- logger.info("{}{}", resourceBundle.getString("LOG_MSG_CONTEXT_DESTROYED"),
- event.getServletContext().getContextPath());
+ public void onApplicationEvent(ApplicationEvent event) {
+ if (event instanceof ContextRefreshedEvent) {
+ contextInitialized((ContextRefreshedEvent) event);
+ } else if (event instanceof ContextClosedEvent) {
+ contextDestroyed((ContextClosedEvent) event);
+ }
}
- @Override
- public void contextInitialized(ServletContextEvent event) {
+ public void contextInitialized(ContextRefreshedEvent event) {
logger.info(resourceBundle.getString("LOG_MSG_CONTEXT_INITIALIZED"));
- // Load Pulse version details
loadPulseVersionDetails();
logger.info(resourceBundle.getString("LOG_MSG_CHECK_APP_RUNNING_MODE"));
@@ -94,12 +96,18 @@ public class PulseAppListener implements ServletContextListener {
PulseConstants.GEMFIRE_DEFAULT_PORT));
repository.setUseSSLManager(
- Boolean.valueOf(System.getProperty(PulseConstants.SYSTEM_PROPERTY_PULSE_USESSL_MANAGER)));
+ Boolean.parseBoolean(
+ System.getProperty(PulseConstants.SYSTEM_PROPERTY_PULSE_USESSL_MANAGER)));
repository.setUseSSLLocator(
- Boolean.valueOf(System.getProperty(PulseConstants.SYSTEM_PROPERTY_PULSE_USESSL_LOCATOR)));
+ Boolean.parseBoolean(
+ System.getProperty(PulseConstants.SYSTEM_PROPERTY_PULSE_USESSL_LOCATOR)));
+
+ WebApplicationContext applicationContext =
+ (WebApplicationContext) event.getApplicationContext();
+ ServletContext servletContext = applicationContext.getServletContext();
Object sslProperties =
- event.getServletContext().getAttribute(GEODE_SSLCONFIG_SERVLET_CONTEXT_PARAM);
+ servletContext.getAttribute(GEODE_SSLCONFIG_SERVLET_CONTEXT_PARAM);
if (sslProperties instanceof Properties) {
repository.setJavaSslProperties((Properties) sslProperties);
}
@@ -109,7 +117,7 @@ public class PulseAppListener implements ServletContextListener {
// Load Pulse Properties
Properties pulseProperties =
- propertiesFileLoader.apply(PulseConstants.PULSE_PROPERTIES_FILE, resourceBundle);
+ propertiesFileLoader.loadProperties(PulseConstants.PULSE_PROPERTIES_FILE, resourceBundle);
repository.setJmxUseLocator(Boolean.valueOf(
pulseProperties.getProperty(PulseConstants.APPLICATION_PROPERTY_PULSE_USELOCATOR)));
@@ -119,14 +127,15 @@ public class PulseAppListener implements ServletContextListener {
PulseConstants.GEMFIRE_DEFAULT_PORT));
// SSL
- repository.setUseSSLManager(Boolean.valueOf(pulseProperties
+ repository.setUseSSLManager(Boolean.parseBoolean(pulseProperties
.getProperty(PulseConstants.SYSTEM_PROPERTY_PULSE_USESSL_MANAGER, "false")));
- repository.setUseSSLLocator(Boolean.valueOf(pulseProperties
+ repository.setUseSSLLocator(Boolean.parseBoolean(pulseProperties
.getProperty(PulseConstants.SYSTEM_PROPERTY_PULSE_USESSL_LOCATOR, "false")));
// load pulse security properties
Properties pulseSecurityProperties =
- propertiesFileLoader.apply(PulseConstants.PULSE_SECURITY_PROPERTIES_FILE, resourceBundle);
+ propertiesFileLoader
+ .loadProperties(PulseConstants.PULSE_SECURITY_PROPERTIES_FILE, resourceBundle);
// set the ssl related properties found in pulsesecurity.properties
if (!pulseSecurityProperties.isEmpty()) {
@@ -144,38 +153,36 @@ public class PulseAppListener implements ServletContextListener {
}
}
- // Function to load pulse version details from properties file
+ public void contextDestroyed(ContextClosedEvent event) {
+
+ // Stop all running threads those are created in Pulse
+ // Stop cluster threads
+ repository.removeAllClusters();
+
+ WebApplicationContext applicationContext =
+ (WebApplicationContext) event.getApplicationContext();
+ ServletContext servletContext = applicationContext.getServletContext();
+
+ logger.info("{}{}", resourceBundle.getString("LOG_MSG_CONTEXT_DESTROYED"),
+ servletContext.getContextPath());
+ }
+
private void loadPulseVersionDetails() {
Properties properties =
- propertiesFileLoader.apply(PulseConstants.PULSE_VERSION_PROPERTIES_FILE, resourceBundle);
- // Set pulse version details in common object
- PulseController.pulseVersion
+ propertiesFileLoader
+ .loadProperties(PulseConstants.PULSE_VERSION_PROPERTIES_FILE, resourceBundle);
+ pulseController.getPulseVersion()
.setPulseVersion(properties.getProperty(PulseConstants.PROPERTY_PULSE_VERSION, ""));
- PulseController.pulseVersion
+ pulseController.getPulseVersion()
.setPulseBuildId(properties.getProperty(PulseConstants.PROPERTY_BUILD_ID, ""));
- PulseController.pulseVersion
+ pulseController.getPulseVersion()
.setPulseBuildDate(properties.getProperty(PulseConstants.PROPERTY_BUILD_DATE, ""));
- PulseController.pulseVersion
+ pulseController.getPulseVersion()
.setPulseSourceDate(properties.getProperty(PulseConstants.PROPERTY_SOURCE_DATE, ""));
- PulseController.pulseVersion.setPulseSourceRevision(
+ pulseController.getPulseVersion().setPulseSourceRevision(
properties.getProperty(PulseConstants.PROPERTY_SOURCE_REVISION, ""));
- PulseController.pulseVersion.setPulseSourceRepository(
+ pulseController.getPulseVersion().setPulseSourceRepository(
properties.getProperty(PulseConstants.PROPERTY_SOURCE_REPOSITORY, ""));
- logger.info(PulseController.pulseVersion.getPulseVersionLogMessage());
- }
-
- // Function to load pulse properties from pulse.properties file
- private static Properties loadPropertiesFromFile(String propertyFile,
- ResourceBundle resourceBundle) {
- final Properties properties = new Properties();
- try (final InputStream stream =
- Thread.currentThread().getContextClassLoader().getResourceAsStream(propertyFile)) {
- logger.info(propertyFile + " " + resourceBundle.getString("LOG_MSG_FILE_FOUND"));
- properties.load(stream);
- } catch (IOException e) {
- logger.error(resourceBundle.getString("LOG_MSG_EXCEPTION_LOADING_PROPERTIES_FILE"), e);
- }
-
- return properties;
+ logger.info(pulseController.getPulseVersion().getPulseVersionLogMessage());
}
}
diff --git a/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/controllers/PulseController.java b/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/controllers/PulseController.java
index 1852e94..709ac08 100644
--- a/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/controllers/PulseController.java
+++ b/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/controllers/PulseController.java
@@ -71,12 +71,23 @@ public class PulseController {
private static final String EMPTY_JSON = "{}";
// Shared object to hold pulse version details
- public static PulseVersion pulseVersion = new PulseVersion();
+ private final PulseVersion pulseVersion;
private final ObjectMapper mapper = new ObjectMapper();
+ private final PulseServiceFactory pulseServiceFactory;
+ private final Repository repository;
@Autowired
- PulseServiceFactory pulseServiceFactory;
+ public PulseController(PulseServiceFactory pulseServiceFactory, Repository repository,
+ PulseVersion pulseVersion) {
+ this.pulseServiceFactory = pulseServiceFactory;
+ this.repository = repository;
+ this.pulseVersion = pulseVersion;
+ }
+
+ public PulseVersion getPulseVersion() {
+ return pulseVersion;
+ }
@RequestMapping(value = "/pulseUpdate", method = RequestMethod.POST)
public void getPulseUpdate(HttpServletRequest request, HttpServletResponse response)
@@ -141,12 +152,12 @@ public class PulseController {
try {
// Response
- responseJSON.put("pulseVersion", PulseController.pulseVersion.getPulseVersion());
- responseJSON.put("buildId", PulseController.pulseVersion.getPulseBuildId());
- responseJSON.put("buildDate", PulseController.pulseVersion.getPulseBuildDate());
- responseJSON.put("sourceDate", PulseController.pulseVersion.getPulseSourceDate());
- responseJSON.put("sourceRevision", PulseController.pulseVersion.getPulseSourceRevision());
- responseJSON.put("sourceRepository", PulseController.pulseVersion.getPulseSourceRepository());
+ responseJSON.put("pulseVersion", pulseVersion.getPulseVersion());
+ responseJSON.put("buildId", pulseVersion.getPulseBuildId());
+ responseJSON.put("buildDate", pulseVersion.getPulseBuildDate());
+ responseJSON.put("sourceDate", pulseVersion.getPulseSourceDate());
+ responseJSON.put("sourceRevision", pulseVersion.getPulseSourceRevision());
+ responseJSON.put("sourceRepository", pulseVersion.getPulseSourceRepository());
} catch (Exception e) {
logger.debug("Exception Occurred : ", e);
@@ -174,7 +185,7 @@ public class PulseController {
try {
boolean isClearAll = Boolean.parseBoolean(request.getParameter("clearAll"));
// get cluster object
- Cluster cluster = Repository.get().getCluster();
+ Cluster cluster = repository.getCluster();
cluster.clearAlerts(alertType, isClearAll);
responseJSON.put("status", "deleted");
responseJSON.set("systemAlerts",
@@ -213,7 +224,7 @@ public class PulseController {
try {
// get cluster object
- Cluster cluster = Repository.get().getCluster();
+ Cluster cluster = repository.getCluster();
// set alert is acknowledged
cluster.acknowledgeAlert(alertId);
@@ -231,7 +242,7 @@ public class PulseController {
HttpServletResponse response)
throws IOException {
// get cluster object
- Cluster cluster = Repository.get().getCluster();
+ Cluster cluster = repository.getCluster();
// json object to be sent as response
ObjectNode responseJSON = mapper.createObjectNode();
@@ -322,7 +333,7 @@ public class PulseController {
try {
// get cluster object
- Cluster cluster = Repository.get().getCluster();
+ Cluster cluster = repository.getCluster();
String userName = request.getUserPrincipal().getName();
// get query string
@@ -388,7 +399,7 @@ public class PulseController {
ObjectNode responseJSON = mapper.createObjectNode();
// get cluster object
- Cluster cluster = Repository.get().getCluster();
+ Cluster cluster = repository.getCluster();
String userName = request.getUserPrincipal().getName();
try {
@@ -431,7 +442,7 @@ public class PulseController {
if (StringUtils.isNotBlank(query)) {
// get cluster object
- Cluster cluster = Repository.get().getCluster();
+ Cluster cluster = repository.getCluster();
String userName = request.getUserPrincipal().getName();
// Add html escaped query to history
diff --git a/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/data/Cluster.java b/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/data/Cluster.java
index 5c252af..dbc3b56 100644
--- a/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/data/Cluster.java
+++ b/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/data/Cluster.java
@@ -54,7 +54,8 @@ public class Cluster extends Thread {
public static final int PAGE_ALERTS_MAX_SIZE = 100;
private static final Logger logger = LogManager.getLogger();
- private final ResourceBundle resourceBundle = Repository.get().getResourceBundle();
+ private Repository repository;
+ private ResourceBundle resourceBundle;
private String jmxUserName;
private String serverName;
@@ -2241,12 +2242,15 @@ public class Cluster extends Thread {
* @param port port
* @param userName pulse user name
*/
- public Cluster(String host, String port, String userName) {
+ public Cluster(String host, String port, String userName, ResourceBundle resourceBundle,
+ Repository repository) {
serverName = host;
this.port = port;
jmxUserName = userName;
+ this.resourceBundle = resourceBundle;
+ this.repository = repository;
- updater = new JMXDataUpdater(serverName, port, this);
+ updater = new JMXDataUpdater(serverName, port, this, resourceBundle, repository);
clusterHasBeenInitialized = new CountDownLatch(1);
if (Boolean.getBoolean(PulseConstants.SYSTEM_PROPERTY_PULSE_EMBEDDED)) {
setDaemon(true);
@@ -2733,15 +2737,11 @@ public class Cluster extends Thread {
public DataBrowser getDataBrowser() {
// Initialize dataBrowser if null
if (dataBrowser == null) {
- dataBrowser = new DataBrowser();
+ dataBrowser = new DataBrowser(resourceBundle, repository);
}
return dataBrowser;
}
- public void setDataBrowser(DataBrowser dataBrowser) {
- this.dataBrowser = dataBrowser;
- }
-
public ObjectNode executeQuery(String queryText, String members, int limit) {
// Execute data browser query
return updater.executeQuery(queryText, members, limit);
@@ -2759,10 +2759,9 @@ public class Cluster extends Thread {
return getDataBrowser().deleteQueryById(userId, queryId);
}
- public void connectToGemFire(String password) {
- jmxConnector = updater.connect(getJmxUserName(), password);
+ public void connectToGemFire(Object credentials) {
+ jmxConnector = updater.connect(credentials);
- // if connected
if (jmxConnector != null) {
// Start Thread
start();
diff --git a/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/data/IClusterUpdater.java b/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/data/ClusterFactory.java
similarity index 64%
copy from geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/data/IClusterUpdater.java
copy to geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/data/ClusterFactory.java
index 942384a..6b0eff4 100644
--- a/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/data/IClusterUpdater.java
+++ b/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/data/ClusterFactory.java
@@ -1,5 +1,4 @@
/*
- *
* 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
@@ -12,27 +11,13 @@
* 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.tools.pulse.internal.data;
-import javax.management.remote.JMXConnector;
-
-import com.fasterxml.jackson.databind.node.ObjectNode;
-
-/**
- * Interface having updateData() function which is implemented by JMXDataUpdater
- *
- * @since GemFire version 7.0.Beta 2012-09-23
- *
- */
-public interface IClusterUpdater {
- boolean updateData();
-
- ObjectNode executeQuery(String queryText, String members, int limit);
+import java.util.ResourceBundle;
- default JMXConnector connect(String username, String password) {
- return null;
- }
+public interface ClusterFactory {
+ Cluster create(String host, String port, String userName, ResourceBundle resourceBundle,
+ Repository repository);
}
diff --git a/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/data/DataBrowser.java b/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/data/DataBrowser.java
index 35f4c6c..6e79161 100644
--- a/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/data/DataBrowser.java
+++ b/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/data/DataBrowser.java
@@ -45,13 +45,19 @@ import org.apache.logging.log4j.Logger;
public class DataBrowser {
private static final Logger logger = LogManager.getLogger();
- private final ResourceBundle resourceBundle = Repository.get().getResourceBundle();
+ private final ResourceBundle resourceBundle;
+ private final Repository repository;
private SimpleDateFormat simpleDateFormat =
new SimpleDateFormat(PulseConstants.PULSE_QUERY_HISTORY_DATE_PATTERN);
private final ObjectMapper mapper = new ObjectMapper();
+ public DataBrowser(ResourceBundle resourceBundle, Repository repository) {
+ this.resourceBundle = resourceBundle;
+ this.repository = repository;
+ }
+
/**
* addQueryInHistory method adds user's query into query history file
*
@@ -156,7 +162,7 @@ public class DataBrowser {
try {
inputStream =
- new FileInputStream(Repository.get().getPulseConfig().getQueryHistoryFileName());
+ new FileInputStream(repository.getPulseConfig().getQueryHistoryFileName());
String inputStreamString = new Scanner(inputStream, "UTF-8").useDelimiter("\\A").next();
queriesJSON = mapper.readTree(inputStreamString);
} catch (FileNotFoundException e) {
@@ -187,7 +193,7 @@ public class DataBrowser {
boolean operationStatus = false;
FileOutputStream fileOut = null;
- File file = new File(Repository.get().getPulseConfig().getQueryHistoryFileName());
+ File file = new File(repository.getPulseConfig().getQueryHistoryFileName());
try {
fileOut = new FileOutputStream(file);
diff --git a/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/data/IClusterUpdater.java b/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/data/IClusterUpdater.java
index 942384a..8bcd666 100644
--- a/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/data/IClusterUpdater.java
+++ b/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/data/IClusterUpdater.java
@@ -32,7 +32,7 @@ public interface IClusterUpdater {
ObjectNode executeQuery(String queryText, String members, int limit);
- default JMXConnector connect(String username, String password) {
+ default JMXConnector connect(Object credentials) {
return null;
}
}
diff --git a/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/data/JMXDataUpdater.java b/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/data/JMXDataUpdater.java
index a9a4b94..c73daab 100644
--- a/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/data/JMXDataUpdater.java
+++ b/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/data/JMXDataUpdater.java
@@ -74,7 +74,8 @@ import org.apache.geode.tools.pulse.internal.data.JmxManagerFinder.JmxManagerInf
public class JMXDataUpdater implements IClusterUpdater, NotificationListener {
private static final Logger logger = LogManager.getLogger();
- private final ResourceBundle resourceBundle = Repository.get().getResourceBundle();
+ private final ResourceBundle resourceBundle;
+ private final Repository repository;
private JMXConnector conn = null;
private MBeanServerConnection mbs = null;
@@ -99,10 +100,13 @@ public class JMXDataUpdater implements IClusterUpdater, NotificationListener {
/**
* constructor used for creating JMX connection
*/
- public JMXDataUpdater(String server, String port, Cluster cluster) {
+ public JMXDataUpdater(String server, String port, Cluster cluster, ResourceBundle resourceBundle,
+ Repository repository) {
serverName = server;
this.port = port;
this.cluster = cluster;
+ this.resourceBundle = resourceBundle;
+ this.repository = repository;
try {
// Initialize MBean object names
@@ -164,14 +168,11 @@ public class JMXDataUpdater implements IClusterUpdater, NotificationListener {
return null;
}
-
/**
* Get the jmx connection
*/
@Override
- public JMXConnector connect(String username, String password) {
- // Reference to repository
- Repository repository = Repository.get();
+ public JMXConnector connect(Object credentials) {
try {
String jmxSerURL = "";
@@ -203,9 +204,8 @@ public class JMXDataUpdater implements IClusterUpdater, NotificationListener {
if (StringUtils.isNotBlank(jmxSerURL)) {
JMXServiceURL url = new JMXServiceURL(jmxSerURL);
- String[] creds = {username, password};
Map<String, Object> env = new HashMap<>();
- env.put(JMXConnector.CREDENTIALS, creds);
+ env.put(JMXConnector.CREDENTIALS, credentials);
Properties originalProperties = System.getProperties();
try {
diff --git a/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/data/PulseVersion.java b/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/data/PulseVersion.java
index 79e9604..c0c1646 100644
--- a/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/data/PulseVersion.java
+++ b/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/data/PulseVersion.java
@@ -19,6 +19,9 @@ package org.apache.geode.tools.pulse.internal.data;
import java.util.ResourceBundle;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
/**
* Class PulseVersion
*
@@ -27,11 +30,17 @@ import java.util.ResourceBundle;
*
* @since GemFire version Helios
*/
-
+@Component
public class PulseVersion {
+ private final Repository repository;
private String pulseVersion;
+ @Autowired
+ public PulseVersion(Repository repository) {
+ this.repository = repository;
+ }
+
public String getPulseVersion() {
return pulseVersion;
}
@@ -91,10 +100,9 @@ public class PulseVersion {
}
public String getPulseVersionLogMessage() {
- ResourceBundle resourceBundle = Repository.get().getResourceBundle();
- String logMessage = resourceBundle.getString("LOG_MSG_PULSE_VERSION") + " "
+ ResourceBundle resourceBundle = repository.getResourceBundle();
+ return resourceBundle.getString("LOG_MSG_PULSE_VERSION") + " "
+ this.getPulseVersion() + " " + this.getPulseBuildId() + " " + this.getPulseBuildDate();
- return logMessage;
}
}
diff --git a/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/data/Repository.java b/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/data/Repository.java
index 0f9f818..9f500f5 100644
--- a/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/data/Repository.java
+++ b/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/data/Repository.java
@@ -21,24 +21,34 @@ import java.util.HashMap;
import java.util.Iterator;
import java.util.Locale;
import java.util.Map;
+import java.util.Objects;
import java.util.Properties;
import java.util.ResourceBundle;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
+import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.security.oauth2.client.OAuth2AuthorizedClient;
+import org.springframework.security.oauth2.client.OAuth2AuthorizedClientService;
+import org.springframework.security.oauth2.client.authentication.OAuth2AuthenticationToken;
+import org.springframework.security.oauth2.core.OAuth2AccessToken;
+import org.springframework.security.oauth2.core.user.OAuth2User;
+import org.springframework.stereotype.Component;
/**
* A Singleton instance of the memory cache for clusters.
*
* @since GemFire version 7.0.Beta 2012-09-23
*/
+@Component
public class Repository {
private static final Logger logger = LogManager.getLogger();
- private static Repository instance = new Repository();
- private HashMap<String, Cluster> clusterMap = new HashMap<>();
+ private final OAuth2AuthorizedClientService authorizedClientService;
+ private final ClusterFactory clusterFactory;
+ private final HashMap<String, Cluster> clusterMap = new HashMap<>();
private Boolean jmxUseLocator;
private String host;
private String port;
@@ -54,12 +64,21 @@ public class Repository {
private PulseConfig pulseConfig = new PulseConfig();
- private Repository() {
+ public Repository() {
+ this(null);
+ }
+ // The authorizedClientService is required only when using OAuth2 security.
+ @Autowired
+ public Repository(
+ @Autowired(required = false) OAuth2AuthorizedClientService authorizedClientService) {
+ this(authorizedClientService, Cluster::new);
}
- public static Repository get() {
- return instance;
+ public Repository(OAuth2AuthorizedClientService authorizedClientService,
+ ClusterFactory clusterFactory) {
+ this.authorizedClientService = authorizedClientService;
+ this.clusterFactory = clusterFactory;
}
public Boolean getJmxUseLocator() {
@@ -67,6 +86,7 @@ public class Repository {
}
public void setJmxUseLocator(Boolean jmxUseLocator) {
+ Objects.requireNonNull(jmxUseLocator, "jmxUseLocat == null");
this.jmxUseLocator = jmxUseLocator;
}
@@ -119,24 +139,43 @@ public class Repository {
* request
*
* But for multi-user connections to gemfireJMX, i.e pulse that uses gemfire integrated security,
- * we will need to get the username form the context
+ * we will need to get the username from the context
*/
public Cluster getCluster() {
- Authentication auth = SecurityContextHolder.getContext().getAuthentication();
- if (auth == null)
+ Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
+ if (authentication == null) {
return null;
- return getCluster(auth.getName(), null);
+ }
+
+ if (authentication instanceof OAuth2AuthenticationToken) {
+ OAuth2AuthenticationToken authenticationToken = (OAuth2AuthenticationToken) authentication;
+ OAuth2AuthorizedClient authorizedClient = authorizedClientService.loadAuthorizedClient(
+ authenticationToken.getAuthorizedClientRegistrationId(),
+ authenticationToken.getName());
+
+ OAuth2User authenticatedPrincipal = authenticationToken.getPrincipal();
+ String authenticatedPrincipalName = authenticatedPrincipal.getName();
+ OAuth2AccessToken accessToken = authorizedClient.getAccessToken();
+ String accessTokenValue = accessToken.getTokenValue();
+ return getClusterWithCredentials(authenticatedPrincipalName, accessTokenValue);
+ }
+
+ return getClusterWithUserNameAndPassword(authentication.getName(), null);
+ }
+
+ public Cluster getClusterWithUserNameAndPassword(String userName, String password) {
+ return getClusterWithCredentials(userName, new String[] {userName, password});
}
- public Cluster getCluster(String username, String password) {
+ public Cluster getClusterWithCredentials(String username, Object credentials) {
synchronized (this.clusterMap) {
Cluster data = clusterMap.get(username);
if (data == null) {
logger.info(resourceBundle.getString("LOG_MSG_CREATE_NEW_THREAD") + " : " + username);
- data = new Cluster(this.host, this.port, username);
+ data = clusterFactory.create(host, port, username, resourceBundle, this);
// Assign name to thread created
- data.setName(PulseConstants.APP_NAME + "-" + this.host + ":" + this.port + ":" + username);
- data.connectToGemFire(password);
+ data.setName(PulseConstants.APP_NAME + "-" + host + ":" + port + ":" + username);
+ data.connectToGemFire(credentials);
if (data.isConnectedFlag()) {
this.clusterMap.put(username, data);
}
diff --git a/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/security/CustomSecurityConfig.java b/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/security/CustomSecurityConfig.java
index 6bb69e3..4b52033 100644
--- a/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/security/CustomSecurityConfig.java
+++ b/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/security/CustomSecurityConfig.java
@@ -24,6 +24,7 @@ import org.springframework.security.config.annotation.authentication.builders.Au
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
+
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
diff --git a/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/security/DefaultSecurityConfig.java b/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/security/DefaultSecurityConfig.java
index fbbe716..a005b94 100644
--- a/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/security/DefaultSecurityConfig.java
+++ b/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/security/DefaultSecurityConfig.java
@@ -18,7 +18,6 @@ package org.apache.geode.tools.pulse.internal.security;
import java.util.HashMap;
import java.util.Map;
-import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
@@ -32,20 +31,18 @@ import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.password.PasswordEncoder;
+import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.security.web.authentication.ExceptionMappingAuthenticationFailureHandler;
+import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
@Profile("pulse.authentication.default")
public class DefaultSecurityConfig extends WebSecurityConfigurerAdapter {
- @Bean
- public LogoutHandler logoutHandler() {
- return new LogoutHandler("/login.html");
- }
@Bean
- public ExceptionMappingAuthenticationFailureHandler failureHandler() {
+ public AuthenticationFailureHandler failureHandler() {
ExceptionMappingAuthenticationFailureHandler exceptionMappingAuthenticationFailureHandler =
new ExceptionMappingAuthenticationFailureHandler();
Map<String, String> exceptionMappings = new HashMap<>();
@@ -58,11 +55,10 @@ public class DefaultSecurityConfig extends WebSecurityConfigurerAdapter {
return exceptionMappingAuthenticationFailureHandler;
}
- @Autowired
- private LogoutHandler logoutHandler;
-
- @Autowired
- private ExceptionMappingAuthenticationFailureHandler failureHandler;
+ @Bean
+ public LogoutSuccessHandler logoutHandler() {
+ return new LogoutHandler("/login.html");
+ }
@Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
@@ -78,11 +74,11 @@ public class DefaultSecurityConfig extends WebSecurityConfigurerAdapter {
.formLogin(form -> form
.loginPage("/login.html")
.loginProcessingUrl("/login")
- .failureHandler(failureHandler)
+ .failureHandler(failureHandler())
.defaultSuccessUrl("/clusterDetail.html", true))
.logout(logout -> logout
.logoutUrl("/clusterLogout")
- .logoutSuccessHandler(logoutHandler))
+ .logoutSuccessHandler(logoutHandler()))
.exceptionHandling(exception -> exception
.accessDeniedPage("/accessDenied.html"))
.headers(header -> header
diff --git a/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/security/GemFireAuthenticationProvider.java b/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/security/GemFireAuthenticationProvider.java
index 6bd77d4..7bbb4dc 100644
--- a/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/security/GemFireAuthenticationProvider.java
+++ b/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/security/GemFireAuthenticationProvider.java
@@ -39,8 +39,11 @@ import org.apache.geode.tools.pulse.internal.data.Repository;
public class GemFireAuthenticationProvider implements AuthenticationProvider {
private static final Logger logger = LogManager.getLogger();
+ private final Repository repository;
- public GemFireAuthenticationProvider() {}
+ public GemFireAuthenticationProvider(Repository repository) {
+ this.repository = repository;
+ }
@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
@@ -54,7 +57,8 @@ public class GemFireAuthenticationProvider implements AuthenticationProvider {
String password = authentication.getCredentials().toString();
logger.debug("Connecting to GemFire with user=" + name);
- JMXConnector jmxc = Repository.get().getCluster(name, password).getJMXConnector();
+ JMXConnector jmxc =
+ repository.getClusterWithUserNameAndPassword(name, password).getJMXConnector();
if (jmxc == null) {
throw new BadCredentialsException("Error connecting to GemFire JMX Server");
}
@@ -70,5 +74,4 @@ public class GemFireAuthenticationProvider implements AuthenticationProvider {
public boolean supports(Class<?> authentication) {
return authentication.equals(UsernamePasswordAuthenticationToken.class);
}
-
}
diff --git a/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/security/GemfireSecurityConfig.java b/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/security/GemfireSecurityConfig.java
index 917a698..11defd9 100644
--- a/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/security/GemfireSecurityConfig.java
+++ b/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/security/GemfireSecurityConfig.java
@@ -16,28 +16,30 @@
package org.apache.geode.tools.pulse.internal.security;
import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
+import org.apache.geode.tools.pulse.internal.data.Repository;
+
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
@Profile("pulse.authentication.gemfire")
public class GemfireSecurityConfig extends DefaultSecurityConfig {
- @Bean
- public GemFireAuthenticationProvider gemAuthenticationProvider() {
- return new GemFireAuthenticationProvider();
- }
+
+ private final Repository repository;
@Autowired
- GemFireAuthenticationProvider gemAuthenticationProvider;
+ public GemfireSecurityConfig(Repository repository) {
+ this.repository = repository;
+ }
@Override
protected void configure(AuthenticationManagerBuilder authenticationManagerBuilder) {
- authenticationManagerBuilder.authenticationProvider(gemAuthenticationProvider);
+ authenticationManagerBuilder
+ .authenticationProvider(new GemFireAuthenticationProvider(repository));
}
}
diff --git a/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/security/LogoutHandler.java b/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/security/LogoutHandler.java
index 1abfa43..4ad4c08 100644
--- a/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/security/LogoutHandler.java
+++ b/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/security/LogoutHandler.java
@@ -22,21 +22,24 @@ import javax.servlet.http.HttpServletResponse;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
+import org.springframework.beans.BeansException;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.ApplicationContextAware;
import org.springframework.security.core.Authentication;
-import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;
import org.springframework.security.web.authentication.logout.SimpleUrlLogoutSuccessHandler;
import org.apache.geode.tools.pulse.internal.data.Repository;
/**
* Handler is used to close jmx connection maintained at user-level
- *
*/
-public class LogoutHandler extends SimpleUrlLogoutSuccessHandler implements LogoutSuccessHandler {
+public class LogoutHandler extends SimpleUrlLogoutSuccessHandler implements
+ ApplicationContextAware {
private static final Logger logger = LogManager.getLogger();
+ private ApplicationContext applicationContext;
- public LogoutHandler(String defaultTargetURL) {
- this.setDefaultTargetUrl(defaultTargetURL);
+ public LogoutHandler(String logoutTargetURL) {
+ setDefaultTargetUrl(logoutTargetURL);
}
@Override
@@ -44,10 +47,16 @@ public class LogoutHandler extends SimpleUrlLogoutSuccessHandler implements Logo
Authentication authentication) throws IOException, ServletException {
if (authentication != null) {
- Repository.get().logoutUser(authentication.getName());
+ Repository repository = applicationContext.getBean("repository", Repository.class);
+ repository.logoutUser(authentication.getName());
logger.info("#LogoutHandler: GemFireAuthentication JMX Connection Closed.");
}
super.onLogoutSuccess(request, response, authentication);
}
+
+ @Override
+ public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
+ this.applicationContext = applicationContext;
+ }
}
diff --git a/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/security/OAuthSecurityConfig.java b/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/security/OAuthSecurityConfig.java
index 3f0e0e9..470c932 100644
--- a/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/security/OAuthSecurityConfig.java
+++ b/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/security/OAuthSecurityConfig.java
@@ -15,8 +15,6 @@
package org.apache.geode.tools.pulse.internal.security;
-import static org.springframework.security.config.Customizer.withDefaults;
-
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@@ -34,6 +32,7 @@ import org.springframework.security.oauth2.client.registration.InMemoryClientReg
import org.springframework.security.oauth2.client.web.AuthenticatedPrincipalOAuth2AuthorizedClientRepository;
import org.springframework.security.oauth2.client.web.OAuth2AuthorizedClientRepository;
import org.springframework.security.oauth2.core.AuthorizationGrantType;
+import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;
@Configuration
@EnableWebSecurity
@@ -41,8 +40,10 @@ import org.springframework.security.oauth2.core.AuthorizationGrantType;
@Profile("pulse.authentication.oauth")
@PropertySource("classpath:pulse.properties")
public class OAuthSecurityConfig extends WebSecurityConfigurerAdapter {
- @Value("${pulse.oauth.provider}")
+ @Value("${pulse.oauth.providerId}")
private String providerId;
+ @Value("${pulse.oauth.providerName}")
+ private String providerName;
@Value("${pulse.oauth.clientId}")
private String clientId;
@Value("${pulse.oauth.clientSecret}")
@@ -58,16 +59,38 @@ public class OAuthSecurityConfig extends WebSecurityConfigurerAdapter {
@Value("${pulse.oauth.userNameAttributeName}")
private String userNameAttributeName;
+ @Bean
+ public LogoutSuccessHandler logoutHandler() {
+ return new LogoutHandler("/login");
+ }
+
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests(authorize -> authorize
+ .mvcMatchers("/pulseVersion", "/scripts/**", "/images/**", "/css/**", "/properties/**")
+ .permitAll()
+ .mvcMatchers("/dataBrowser*", "/getQueryStatisticsGridModel*")
+ .access("hasAuthority('SCOPE_CLUSTER:READ') and hasAuthority('SCOPE_DATA:READ')")
+ .mvcMatchers("/*")
+ .hasAuthority("SCOPE_CLUSTER:READ")
.anyRequest().authenticated())
- .oauth2Login(withDefaults());
+ .oauth2Login(oauth -> oauth.defaultSuccessUrl("/clusterDetail.html", true))
+ .exceptionHandling(exception -> exception.accessDeniedPage("/accessDenied.html"))
+ .logout(logout -> logout
+ .logoutUrl("/clusterLogout")
+ .logoutSuccessHandler(logoutHandler()))
+ .headers(header -> header
+ .frameOptions().deny()
+ .xssProtection(xss -> xss
+ .xssProtectionEnabled(true)
+ .block(true))
+ .contentTypeOptions())
+ .csrf().disable();
}
@Bean
public ClientRegistrationRepository clientRegistrationRepository() {
- return new InMemoryClientRegistrationRepository(this.clientRegistration());
+ return new InMemoryClientRegistrationRepository(clientRegistration());
}
@Bean
@@ -84,16 +107,19 @@ public class OAuthSecurityConfig extends WebSecurityConfigurerAdapter {
private ClientRegistration clientRegistration() {
return ClientRegistration.withRegistrationId(providerId)
- .clientId(clientId)
- .clientSecret(clientSecret)
.authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE)
.redirectUriTemplate("{baseUrl}/login/oauth2/code/{registrationId}")
- .scope("openid", "CLUSTER:READ", "CLUSTER:WRITE", "DATA:READ", "DATA:WRITE")
+ .clientId(clientId)
+ .clientSecret(clientSecret)
.authorizationUri(authorizationUri)
.tokenUri(tokenUri)
.userInfoUri(userInfoUri)
.jwkSetUri(jwkSetUri)
- .clientName("Pulse")
+ // When Spring shows the login page, it displays a link to the OAuth provider's
+ // authorization URI. Spring uses the value passed to clientName() as the text for that
+ // link. We pass the providerName property here, to let the user know which OAuth provider
+ // they will be redirected to.
+ .clientName(providerName)
.userNameAttributeName(userNameAttributeName)
.build();
}
diff --git a/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/service/ClusterDetailsService.java b/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/service/ClusterDetailsService.java
index f043bb4..f200143 100644
--- a/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/service/ClusterDetailsService.java
+++ b/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/service/ClusterDetailsService.java
@@ -23,6 +23,7 @@ import javax.servlet.http.HttpServletRequest;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
+import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
@@ -44,6 +45,12 @@ import org.apache.geode.tools.pulse.internal.data.Repository;
public class ClusterDetailsService implements PulseService {
private final ObjectMapper mapper = new ObjectMapper();
+ private final Repository repository;
+
+ @Autowired
+ public ClusterDetailsService(Repository repository) {
+ this.repository = repository;
+ }
@Override
public ObjectNode execute(final HttpServletRequest request) throws Exception {
@@ -51,7 +58,7 @@ public class ClusterDetailsService implements PulseService {
String userName = request.getUserPrincipal().getName();
// get cluster object
- Cluster cluster = Repository.get().getCluster();
+ Cluster cluster = repository.getCluster();
// json object to be sent as response
ObjectNode responseJSON = mapper.createObjectNode();
diff --git a/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/service/ClusterDiskThroughputService.java b/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/service/ClusterDiskThroughputService.java
index 7e8529f..25c0720 100644
--- a/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/service/ClusterDiskThroughputService.java
+++ b/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/service/ClusterDiskThroughputService.java
@@ -21,6 +21,7 @@ import javax.servlet.http.HttpServletRequest;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
+import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
@@ -41,12 +42,18 @@ import org.apache.geode.tools.pulse.internal.data.Repository;
public class ClusterDiskThroughputService implements PulseService {
private final ObjectMapper mapper = new ObjectMapper();
+ private final Repository repository;
+
+ @Autowired
+ public ClusterDiskThroughputService(Repository repository) {
+ this.repository = repository;
+ }
@Override
public ObjectNode execute(final HttpServletRequest request) throws Exception {
// get cluster object
- Cluster cluster = Repository.get().getCluster();
+ Cluster cluster = repository.getCluster();
// json object to be sent as response
ObjectNode responseJSON = mapper.createObjectNode();
diff --git a/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/service/ClusterGCPausesService.java b/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/service/ClusterGCPausesService.java
index 826f666..b367d27 100644
--- a/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/service/ClusterGCPausesService.java
+++ b/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/service/ClusterGCPausesService.java
@@ -22,6 +22,7 @@ import javax.servlet.http.HttpServletRequest;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
+import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
@@ -44,12 +45,18 @@ import org.apache.geode.tools.pulse.internal.data.Repository;
public class ClusterGCPausesService implements PulseService {
private final ObjectMapper mapper = new ObjectMapper();
+ private final Repository repository;
+
+ @Autowired
+ public ClusterGCPausesService(Repository repository) {
+ this.repository = repository;
+ }
@Override
public ObjectNode execute(final HttpServletRequest request) throws Exception {
// get cluster object
- Cluster cluster = Repository.get().getCluster();
+ Cluster cluster = repository.getCluster();
// json object to be sent as response
ObjectNode responseJSON = mapper.createObjectNode();
diff --git a/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/service/ClusterKeyStatisticsService.java b/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/service/ClusterKeyStatisticsService.java
index ae75bd8..f39d75e 100644
--- a/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/service/ClusterKeyStatisticsService.java
+++ b/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/service/ClusterKeyStatisticsService.java
@@ -21,6 +21,7 @@ import javax.servlet.http.HttpServletRequest;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
+import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
@@ -43,12 +44,18 @@ import org.apache.geode.tools.pulse.internal.data.Repository;
public class ClusterKeyStatisticsService implements PulseService {
private final ObjectMapper mapper = new ObjectMapper();
+ private final Repository repository;
+
+ @Autowired
+ public ClusterKeyStatisticsService(Repository repository) {
+ this.repository = repository;
+ }
@Override
public ObjectNode execute(final HttpServletRequest request) throws Exception {
// get cluster object
- Cluster cluster = Repository.get().getCluster();
+ Cluster cluster = repository.getCluster();
// json object to be sent as response
ObjectNode responseJSON = mapper.createObjectNode();
diff --git a/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/service/ClusterMemberService.java b/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/service/ClusterMemberService.java
index 32d9af3..f3181ce 100644
--- a/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/service/ClusterMemberService.java
+++ b/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/service/ClusterMemberService.java
@@ -27,6 +27,7 @@ import javax.servlet.http.HttpServletRequest;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
+import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
@@ -52,12 +53,18 @@ public class ClusterMemberService implements PulseService {
private final ObjectMapper mapper = new ObjectMapper();
private static final String HEAP_USAGE = "heapUsage";
+ private final Repository repository;
+
+ @Autowired
+ public ClusterMemberService(Repository repository) {
+ this.repository = repository;
+ }
@Override
public ObjectNode execute(final HttpServletRequest request) throws Exception {
// get cluster object
- Cluster cluster = Repository.get().getCluster();
+ Cluster cluster = repository.getCluster();
// json object to be sent as response
ObjectNode responseJSON = mapper.createObjectNode();
diff --git a/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/service/ClusterMembersRGraphService.java b/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/service/ClusterMembersRGraphService.java
index e0c9ac8..8fcbfb0 100644
--- a/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/service/ClusterMembersRGraphService.java
+++ b/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/service/ClusterMembersRGraphService.java
@@ -28,6 +28,7 @@ import javax.servlet.http.HttpServletRequest;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
+import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
@@ -74,6 +75,7 @@ public class ClusterMembersRGraphService implements PulseService {
private static final String MEMBER_NODE_TYPE_ERROR = "Error";
private static final String MEMBER_NODE_TYPE_SEVERE = "Severe";
private static final String CHILDREN = "children";
+ private final Repository repository;
// traversing the alert array list and members which have severe, error or
// warnings
@@ -82,12 +84,14 @@ public class ClusterMembersRGraphService implements PulseService {
private List<String> errorAlertsList;
private List<String> warningAlertsList;
+ @Autowired
+ public ClusterMembersRGraphService(Repository repository) {
+ this.repository = repository;
+ }
+
@Override
public ObjectNode execute(final HttpServletRequest request) throws Exception {
- // Reference to repository
- Repository repository = Repository.get();
-
// get cluster object
Cluster cluster = repository.getCluster();
@@ -95,8 +99,7 @@ public class ClusterMembersRGraphService implements PulseService {
ObjectNode responseJSON = mapper.createObjectNode();
// cluster's Members
- responseJSON.set(CLUSTER,
- getPhysicalServerJson(cluster));
+ responseJSON.set(CLUSTER, getPhysicalServerJson(cluster));
responseJSON.put(MEMBER_COUNT, cluster.getMemberCount());
// Send json response
diff --git a/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/service/ClusterMemoryUsageService.java b/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/service/ClusterMemoryUsageService.java
index 37fe6b6..67a5c45 100644
--- a/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/service/ClusterMemoryUsageService.java
+++ b/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/service/ClusterMemoryUsageService.java
@@ -21,6 +21,7 @@ import javax.servlet.http.HttpServletRequest;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
+import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
@@ -43,12 +44,18 @@ import org.apache.geode.tools.pulse.internal.data.Repository;
public class ClusterMemoryUsageService implements PulseService {
private final ObjectMapper mapper = new ObjectMapper();
+ private final Repository repository;
+
+ @Autowired
+ public ClusterMemoryUsageService(Repository repository) {
+ this.repository = repository;
+ }
@Override
public ObjectNode execute(final HttpServletRequest request) throws Exception {
// get cluster object
- Cluster cluster = Repository.get().getCluster();
+ Cluster cluster = repository.getCluster();
// json object to be sent as response
ObjectNode responseJSON = mapper.createObjectNode();
diff --git a/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/service/ClusterRegionService.java b/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/service/ClusterRegionService.java
index ee98438..66ee91b 100644
--- a/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/service/ClusterRegionService.java
+++ b/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/service/ClusterRegionService.java
@@ -30,6 +30,7 @@ import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
@@ -54,6 +55,12 @@ public class ClusterRegionService implements PulseService {
// String constants used for forming a json response
private static final String ENTRY_SIZE = "entrySize";
+ private final Repository repository;
+
+ @Autowired
+ public ClusterRegionService(Repository repository) {
+ this.repository = repository;
+ }
// Comparator based upon regions entry count
private static Comparator<Cluster.Region> regionEntryCountComparator = (r1, r2) -> {
@@ -68,7 +75,7 @@ public class ClusterRegionService implements PulseService {
String userName = request.getUserPrincipal().getName();
// get cluster object
- Cluster cluster = Repository.get().getCluster();
+ Cluster cluster = repository.getCluster();
// json object to be sent as response
ObjectNode responseJSON = mapper.createObjectNode();
diff --git a/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/service/ClusterRegionsService.java b/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/service/ClusterRegionsService.java
index ff551af..3641ca2 100644
--- a/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/service/ClusterRegionsService.java
+++ b/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/service/ClusterRegionsService.java
@@ -30,6 +30,7 @@ import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
@@ -54,6 +55,12 @@ public class ClusterRegionsService implements PulseService {
// String constants used for forming a json response
private static final String ENTRY_SIZE = "entrySize";
+ private final Repository repository;
+
+ @Autowired
+ public ClusterRegionsService(Repository repository) {
+ this.repository = repository;
+ }
// Comparator based upon regions entry count
private static Comparator<Cluster.Region> regionEntryCountComparator = (r1, r2) -> {
@@ -65,7 +72,7 @@ public class ClusterRegionsService implements PulseService {
@Override
public ObjectNode execute(final HttpServletRequest request) throws Exception {
// get cluster object
- Cluster cluster = Repository.get().getCluster();
+ Cluster cluster = repository.getCluster();
// json object to be sent as response
ObjectNode responseJSON = mapper.createObjectNode();
diff --git a/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/service/ClusterSelectedRegionService.java b/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/service/ClusterSelectedRegionService.java
index e8a8b22..d8c0dd9 100644
--- a/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/service/ClusterSelectedRegionService.java
+++ b/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/service/ClusterSelectedRegionService.java
@@ -33,6 +33,7 @@ import com.fasterxml.jackson.databind.node.ObjectNode;
import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
+import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
@@ -59,6 +60,12 @@ public class ClusterSelectedRegionService implements PulseService {
// String constants used for forming a json response
private static final String ENTRY_SIZE = "entrySize";
+ private final Repository repository;
+
+ @Autowired
+ public ClusterSelectedRegionService(Repository repository) {
+ this.repository = repository;
+ }
// Comparator based upon regions entry count
private static Comparator<Cluster.Member> memberCurrentHeapUsageComparator = (m1, m2) -> {
@@ -77,7 +84,7 @@ public class ClusterSelectedRegionService implements PulseService {
parameterMap.get("ClusterSelectedRegion").get("regionFullPath").textValue();
// get cluster object
- Cluster cluster = Repository.get().getCluster();
+ Cluster cluster = repository.getCluster();
// json object to be sent as response
ObjectNode responseJSON = mapper.createObjectNode();
diff --git a/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/service/ClusterSelectedRegionsMemberService.java b/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/service/ClusterSelectedRegionsMemberService.java
index 55b5a93..648b703 100644
--- a/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/service/ClusterSelectedRegionsMemberService.java
+++ b/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/service/ClusterSelectedRegionsMemberService.java
@@ -28,6 +28,7 @@ import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
+import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
@@ -52,6 +53,12 @@ public class ClusterSelectedRegionsMemberService implements PulseService {
private final ObjectMapper mapper = new ObjectMapper();
private static final Logger logger = LogManager.getLogger();
+ private final Repository repository;
+
+ @Autowired
+ public ClusterSelectedRegionsMemberService(Repository repository) {
+ this.repository = repository;
+ }
// Comparator based upon regions entry count
private static Comparator<Cluster.RegionOnMember> romEntryCountComparator = (m1, m2) -> {
@@ -71,7 +78,7 @@ public class ClusterSelectedRegionsMemberService implements PulseService {
selectedRegionFullPath);
// get cluster object
- Cluster cluster = Repository.get().getCluster();
+ Cluster cluster = repository.getCluster();
// json object to be sent as response
ObjectNode responseJSON = mapper.createObjectNode();
diff --git a/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/service/ClusterWANInfoService.java b/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/service/ClusterWANInfoService.java
index 47a085a..499b049 100644
--- a/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/service/ClusterWANInfoService.java
+++ b/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/service/ClusterWANInfoService.java
@@ -24,6 +24,7 @@ import javax.servlet.http.HttpServletRequest;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
+import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
@@ -44,12 +45,18 @@ import org.apache.geode.tools.pulse.internal.data.Repository;
public class ClusterWANInfoService implements PulseService {
private final ObjectMapper mapper = new ObjectMapper();
+ private final Repository repository;
+
+ @Autowired
+ public ClusterWANInfoService(Repository repository) {
+ this.repository = repository;
+ }
@Override
public ObjectNode execute(final HttpServletRequest request) throws Exception {
// get cluster object
- Cluster cluster = Repository.get().getCluster();
+ Cluster cluster = repository.getCluster();
// json object to be sent as response
ObjectNode responseJSON = mapper.createObjectNode();
diff --git a/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/service/MemberAsynchEventQueuesService.java b/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/service/MemberAsynchEventQueuesService.java
index 25be0e9..abcb3d0 100644
--- a/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/service/MemberAsynchEventQueuesService.java
+++ b/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/service/MemberAsynchEventQueuesService.java
@@ -25,6 +25,7 @@ import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
+import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
@@ -46,12 +47,18 @@ import org.apache.geode.tools.pulse.internal.data.Repository;
public class MemberAsynchEventQueuesService implements PulseService {
private final ObjectMapper mapper = new ObjectMapper();
+ private final Repository repository;
+
+ @Autowired
+ public MemberAsynchEventQueuesService(Repository repository) {
+ this.repository = repository;
+ }
@Override
public ObjectNode execute(final HttpServletRequest request) throws Exception {
// get cluster object
- Cluster cluster = Repository.get().getCluster();
+ Cluster cluster = repository.getCluster();
// json object to be sent as response
ObjectNode responseJSON = mapper.createObjectNode();
diff --git a/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/service/MemberClientsService.java b/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/service/MemberClientsService.java
index 8a64596..19441cc 100644
--- a/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/service/MemberClientsService.java
+++ b/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/service/MemberClientsService.java
@@ -25,6 +25,7 @@ import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
+import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
@@ -50,12 +51,18 @@ public class MemberClientsService implements PulseService {
// String constants used for forming a json response
private static final String NAME = "name";
private static final String HOST = "host";
+ private final Repository repository;
+
+ @Autowired
+ public MemberClientsService(Repository repository) {
+ this.repository = repository;
+ }
@Override
public ObjectNode execute(final HttpServletRequest request) throws Exception {
// get cluster object
- Cluster cluster = Repository.get().getCluster();
+ Cluster cluster = repository.getCluster();
// json object to be sent as response
ObjectNode responseJSON = mapper.createObjectNode();
diff --git a/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/service/MemberDetailsService.java b/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/service/MemberDetailsService.java
index 4290d93..633f376 100644
--- a/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/service/MemberDetailsService.java
+++ b/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/service/MemberDetailsService.java
@@ -25,6 +25,7 @@ import javax.servlet.http.HttpServletRequest;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
+import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
@@ -45,6 +46,12 @@ import org.apache.geode.tools.pulse.internal.data.Repository;
public class MemberDetailsService implements PulseService {
private final ObjectMapper mapper = new ObjectMapper();
+ private final Repository repository;
+
+ @Autowired
+ public MemberDetailsService(Repository repository) {
+ this.repository = repository;
+ }
@Override
public ObjectNode execute(final HttpServletRequest request) throws Exception {
@@ -52,7 +59,7 @@ public class MemberDetailsService implements PulseService {
String userName = request.getUserPrincipal().getName();
// get cluster object
- Cluster cluster = Repository.get().getCluster();
+ Cluster cluster = repository.getCluster();
// json object to be sent as response
ObjectNode responseJSON = mapper.createObjectNode();
diff --git a/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/service/MemberDiskThroughputService.java b/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/service/MemberDiskThroughputService.java
index 51d3c48..9f292bf 100644
--- a/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/service/MemberDiskThroughputService.java
+++ b/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/service/MemberDiskThroughputService.java
@@ -24,6 +24,7 @@ import javax.servlet.http.HttpServletRequest;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
+import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
@@ -45,12 +46,18 @@ import org.apache.geode.tools.pulse.internal.data.Repository;
public class MemberDiskThroughputService implements PulseService {
private final ObjectMapper mapper = new ObjectMapper();
+ private final Repository repository;
+
+ @Autowired
+ public MemberDiskThroughputService(Repository repository) {
+ this.repository = repository;
+ }
@Override
public ObjectNode execute(final HttpServletRequest request) throws Exception {
// get cluster object
- Cluster cluster = Repository.get().getCluster();
+ Cluster cluster = repository.getCluster();
// json object to be sent as response
ObjectNode responseJSON = mapper.createObjectNode();
diff --git a/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/service/MemberGCPausesService.java b/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/service/MemberGCPausesService.java
index 5a8a3db..5680a65 100644
--- a/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/service/MemberGCPausesService.java
+++ b/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/service/MemberGCPausesService.java
@@ -24,6 +24,7 @@ import javax.servlet.http.HttpServletRequest;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
+import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
@@ -46,12 +47,18 @@ import org.apache.geode.tools.pulse.internal.data.Repository;
public class MemberGCPausesService implements PulseService {
private final ObjectMapper mapper = new ObjectMapper();
+ private final Repository repository;
+
+ @Autowired
+ public MemberGCPausesService(Repository repository) {
+ this.repository = repository;
+ }
@Override
public ObjectNode execute(final HttpServletRequest request) throws Exception {
// get cluster object
- Cluster cluster = Repository.get().getCluster();
+ Cluster cluster = repository.getCluster();
// json object to be sent as response
ObjectNode responseJSON = mapper.createObjectNode();
diff --git a/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/service/MemberGatewayHubService.java b/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/service/MemberGatewayHubService.java
index b458569..93205e4 100644
--- a/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/service/MemberGatewayHubService.java
+++ b/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/service/MemberGatewayHubService.java
@@ -29,6 +29,7 @@ import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
+import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
@@ -50,12 +51,18 @@ import org.apache.geode.tools.pulse.internal.data.Repository;
public class MemberGatewayHubService implements PulseService {
private final ObjectMapper mapper = new ObjectMapper();
+ private final Repository repository;
+
+ @Autowired
+ public MemberGatewayHubService(Repository repository) {
+ this.repository = repository;
+ }
@Override
public ObjectNode execute(final HttpServletRequest request) throws Exception {
// get cluster object
- Cluster cluster = Repository.get().getCluster();
+ Cluster cluster = repository.getCluster();
// json object to be sent as response
ObjectNode responseJSON = mapper.createObjectNode();
diff --git a/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/service/MemberHeapUsageService.java b/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/service/MemberHeapUsageService.java
index a87041f..52801ed 100644
--- a/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/service/MemberHeapUsageService.java
+++ b/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/service/MemberHeapUsageService.java
@@ -24,6 +24,7 @@ import javax.servlet.http.HttpServletRequest;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
+import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
@@ -45,12 +46,18 @@ import org.apache.geode.tools.pulse.internal.data.Repository;
public class MemberHeapUsageService implements PulseService {
private final ObjectMapper mapper = new ObjectMapper();
+ private final Repository repository;
+
+ @Autowired
+ public MemberHeapUsageService(Repository repository) {
+ this.repository = repository;
+ }
@Override
public ObjectNode execute(final HttpServletRequest request) throws Exception {
// get cluster object
- Cluster cluster = Repository.get().getCluster();
+ Cluster cluster = repository.getCluster();
// json object to be sent as response
ObjectNode responseJSON = mapper.createObjectNode();
diff --git a/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/service/MemberKeyStatisticsService.java b/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/service/MemberKeyStatisticsService.java
index 0dec34e..8ceac47 100644
--- a/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/service/MemberKeyStatisticsService.java
+++ b/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/service/MemberKeyStatisticsService.java
@@ -24,6 +24,7 @@ import javax.servlet.http.HttpServletRequest;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
+import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
@@ -44,12 +45,18 @@ import org.apache.geode.tools.pulse.internal.data.Repository;
public class MemberKeyStatisticsService implements PulseService {
private final ObjectMapper mapper = new ObjectMapper();
+ private final Repository repository;
+
+ @Autowired
+ public MemberKeyStatisticsService(Repository repository) {
+ this.repository = repository;
+ }
@Override
public ObjectNode execute(final HttpServletRequest request) throws Exception {
// get cluster object
- Cluster cluster = Repository.get().getCluster();
+ Cluster cluster = repository.getCluster();
// json object to be sent as response
ObjectNode responseJSON = mapper.createObjectNode();
diff --git a/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/service/MemberRegionsService.java b/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/service/MemberRegionsService.java
index 8ec8e90..10f7213 100644
--- a/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/service/MemberRegionsService.java
+++ b/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/service/MemberRegionsService.java
@@ -27,6 +27,7 @@ import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
@@ -54,12 +55,18 @@ public class MemberRegionsService implements PulseService {
private static final String ENTRY_SIZE = "entrySize";
private static final String DISC_STORE_NAME = "diskStoreName";
private static final String DISC_SYNCHRONOUS = "diskSynchronous";
+ private final Repository repository;
+
+ @Autowired
+ public MemberRegionsService(Repository repository) {
+ this.repository = repository;
+ }
@Override
public ObjectNode execute(final HttpServletRequest request) throws Exception {
// get cluster object
- Cluster cluster = Repository.get().getCluster();
+ Cluster cluster = repository.getCluster();
// json object to be sent as response
ObjectNode responseJSON = mapper.createObjectNode();
diff --git a/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/service/MembersListService.java b/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/service/MembersListService.java
index 9d0ca9e..1f8337e 100644
--- a/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/service/MembersListService.java
+++ b/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/service/MembersListService.java
@@ -22,6 +22,7 @@ import javax.servlet.http.HttpServletRequest;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
+import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
@@ -42,12 +43,18 @@ import org.apache.geode.tools.pulse.internal.data.Repository;
public class MembersListService implements PulseService {
private final ObjectMapper mapper = new ObjectMapper();
+ private final Repository repository;
+
+ @Autowired
+ public MembersListService(Repository repository) {
+ this.repository = repository;
+ }
@Override
public ObjectNode execute(final HttpServletRequest request) throws Exception {
// get cluster object
- Cluster cluster = Repository.get().getCluster();
+ Cluster cluster = repository.getCluster();
// json object to be sent as response
ObjectNode responseJSON = mapper.createObjectNode();
diff --git a/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/service/PulseVersionService.java b/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/service/PulseVersionService.java
index 9cd83b2..a505c79 100644
--- a/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/service/PulseVersionService.java
+++ b/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/service/PulseVersionService.java
@@ -21,6 +21,7 @@ import javax.servlet.http.HttpServletRequest;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
+import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
@@ -42,6 +43,12 @@ import org.apache.geode.tools.pulse.internal.controllers.PulseController;
public class PulseVersionService implements PulseService {
private final ObjectMapper mapper = new ObjectMapper();
+ private final PulseController pulseController;
+
+ @Autowired
+ public PulseVersionService(PulseController pulseController) {
+ this.pulseController = pulseController;
+ }
@Override
public ObjectNode execute(final HttpServletRequest request) throws Exception {
@@ -50,12 +57,13 @@ public class PulseVersionService implements PulseService {
ObjectNode responseJSON = mapper.createObjectNode();
// Response
- responseJSON.put("pulseVersion", PulseController.pulseVersion.getPulseVersion());
- responseJSON.put("buildId", PulseController.pulseVersion.getPulseBuildId());
- responseJSON.put("buildDate", PulseController.pulseVersion.getPulseBuildDate());
- responseJSON.put("sourceDate", PulseController.pulseVersion.getPulseSourceDate());
- responseJSON.put("sourceRevision", PulseController.pulseVersion.getPulseSourceRevision());
- responseJSON.put("sourceRepository", PulseController.pulseVersion.getPulseSourceRepository());
+ responseJSON.put("pulseVersion", pulseController.getPulseVersion().getPulseVersion());
+ responseJSON.put("buildId", pulseController.getPulseVersion().getPulseBuildId());
+ responseJSON.put("buildDate", pulseController.getPulseVersion().getPulseBuildDate());
+ responseJSON.put("sourceDate", pulseController.getPulseVersion().getPulseSourceDate());
+ responseJSON.put("sourceRevision", pulseController.getPulseVersion().getPulseSourceRevision());
+ responseJSON.put("sourceRepository",
+ pulseController.getPulseVersion().getPulseSourceRepository());
// Send json response
return responseJSON;
diff --git a/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/service/QueryStatisticsService.java b/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/service/QueryStatisticsService.java
index 7d42abd..9fa4ee0 100644
--- a/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/service/QueryStatisticsService.java
+++ b/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/service/QueryStatisticsService.java
@@ -22,6 +22,7 @@ import javax.servlet.http.HttpServletRequest;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
+import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
@@ -43,12 +44,18 @@ import org.apache.geode.tools.pulse.internal.data.Repository;
public class QueryStatisticsService implements PulseService {
private final ObjectMapper mapper = new ObjectMapper();
+ private final Repository repository;
+
+ @Autowired
+ public QueryStatisticsService(Repository repository) {
+ this.repository = repository;
+ }
@Override
public ObjectNode execute(final HttpServletRequest request) throws Exception {
// get cluster object
- Cluster cluster = Repository.get().getCluster();
+ Cluster cluster = repository.getCluster();
// json object to be sent as response
ObjectNode responseJSON = mapper.createObjectNode();
diff --git a/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/service/SystemAlertsService.java b/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/service/SystemAlertsService.java
index 8908abf..2216404 100644
--- a/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/service/SystemAlertsService.java
+++ b/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/service/SystemAlertsService.java
@@ -24,6 +24,7 @@ import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
@@ -46,12 +47,18 @@ import org.apache.geode.tools.pulse.internal.data.Repository;
public class SystemAlertsService implements PulseService {
private static final ObjectMapper mapper = new ObjectMapper();
+ private final Repository repository;
+
+ @Autowired
+ public SystemAlertsService(Repository repository) {
+ this.repository = repository;
+ }
@Override
public ObjectNode execute(final HttpServletRequest request) throws Exception {
// get cluster object
- Cluster cluster = Repository.get().getCluster();
+ Cluster cluster = repository.getCluster();
// json object to be sent as response
ObjectNode responseJSON = mapper.createObjectNode();
diff --git a/geode-pulse/src/main/resources/pulse.properties b/geode-pulse/src/main/resources/pulse.properties
index 98aeff3..d909c3f 100644
--- a/geode-pulse/src/main/resources/pulse.properties
+++ b/geode-pulse/src/main/resources/pulse.properties
@@ -29,7 +29,8 @@ pulse.port=10334
#pulse.useSSL.manager=true
###### use pulse.properties to customize oauth behavior ######
-#pulse.oauth.provider=uaa/google/etc.
+#pulse.oauth.providerId=uaa/google/etc.
+#pulse.oauth.providerName=
#pulse.oauth.clientId=
#pulse.oauth.clientSecret=
#pulse.oauth.authorizationUri=
diff --git a/geode-pulse/src/main/webapp/WEB-INF/web.xml b/geode-pulse/src/main/webapp/WEB-INF/web.xml
index 19ad467..5da1928 100644
--- a/geode-pulse/src/main/webapp/WEB-INF/web.xml
+++ b/geode-pulse/src/main/webapp/WEB-INF/web.xml
@@ -39,15 +39,6 @@
<url-pattern>/</url-pattern>
</servlet-mapping>
- <listener>
- <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
- </listener>
- <context-param>
- <param-name>contextConfigLocation</param-name>
- <param-value>
- /WEB-INF/pulse-servlet.xml
- </param-value>
- </context-param>
<context-param>
<param-name>spring.profiles.default</param-name>
<param-value>pulse.authentication.default</param-value>
@@ -60,7 +51,4 @@
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
- <listener>
- <listener-class>org.apache.geode.tools.pulse.internal.PulseAppListener</listener-class>
- </listener>
</web-app>
\ No newline at end of file
diff --git a/geode-pulse/src/test/java/org/apache/geode/tools/pulse/internal/PulseAppListenerTest.java b/geode-pulse/src/test/java/org/apache/geode/tools/pulse/internal/PulseAppListenerTest.java
index 3fc89fb..7ce7896 100644
--- a/geode-pulse/src/test/java/org/apache/geode/tools/pulse/internal/PulseAppListenerTest.java
+++ b/geode-pulse/src/test/java/org/apache/geode/tools/pulse/internal/PulseAppListenerTest.java
@@ -21,7 +21,6 @@ import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import javax.servlet.ServletContext;
-import javax.servlet.ServletContextEvent;
import org.junit.After;
import org.junit.Assert;
@@ -30,8 +29,12 @@ import org.junit.Rule;
import org.junit.Test;
import org.junit.contrib.java.lang.system.RestoreSystemProperties;
import org.junit.rules.TestRule;
+import org.springframework.context.event.ContextRefreshedEvent;
+import org.springframework.web.context.WebApplicationContext;
+import org.apache.geode.tools.pulse.internal.controllers.PulseController;
import org.apache.geode.tools.pulse.internal.data.PulseConstants;
+import org.apache.geode.tools.pulse.internal.data.PulseVersion;
import org.apache.geode.tools.pulse.internal.data.Repository;
public class PulseAppListenerTest {
@@ -41,19 +44,27 @@ public class PulseAppListenerTest {
@Rule
public final TestRule restoreSystemProperties = new RestoreSystemProperties();
- ServletContextEvent contextEvent;
+ ContextRefreshedEvent contextEvent;
@Before
public void setUp() {
System.setProperty(PulseConstants.SYSTEM_PROPERTY_PULSE_EMBEDDED, "true");
- repository = Repository.get();
- appListener = new PulseAppListener();
+ repository = new Repository();
- contextEvent = mock(ServletContextEvent.class);
- ServletContext context = mock(ServletContext.class);
- when(context.getAttribute(anyString())).thenReturn(null);
- when(contextEvent.getServletContext()).thenReturn(context);
+ PulseController pulseController = mock(PulseController.class);
+ appListener =
+ new PulseAppListener(pulseController, repository, new ClassPathPropertiesFileLoader());
+ PulseVersion pulseVersion = new PulseVersion(repository);
+ when(pulseController.getPulseVersion()).thenReturn(pulseVersion);
+
+ contextEvent = mock(ContextRefreshedEvent.class);
+ WebApplicationContext applicationContext = mock(WebApplicationContext.class);
+ when(contextEvent.getApplicationContext()).thenReturn(applicationContext);
+
+ ServletContext servletContext = mock(ServletContext.class);
+ when(servletContext.getAttribute(anyString())).thenReturn(null);
+ when(applicationContext.getServletContext()).thenReturn(servletContext);
}
@Test
diff --git a/geode-pulse/src/test/java/org/apache/geode/tools/pulse/internal/PulseAppListenerUnitTest.java b/geode-pulse/src/test/java/org/apache/geode/tools/pulse/internal/PulseAppListenerUnitTest.java
index 6de7e35..8e58873 100644
--- a/geode-pulse/src/test/java/org/apache/geode/tools/pulse/internal/PulseAppListenerUnitTest.java
+++ b/geode-pulse/src/test/java/org/apache/geode/tools/pulse/internal/PulseAppListenerUnitTest.java
@@ -28,10 +28,8 @@ import static org.mockito.Mockito.when;
import java.util.Enumeration;
import java.util.Properties;
import java.util.ResourceBundle;
-import java.util.function.BiFunction;
import javax.servlet.ServletContext;
-import javax.servlet.ServletContextEvent;
import org.junit.Before;
import org.junit.Rule;
@@ -39,18 +37,19 @@ import org.junit.Test;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnit;
import org.mockito.junit.MockitoRule;
+import org.springframework.context.event.ContextRefreshedEvent;
+import org.springframework.web.context.WebApplicationContext;
+import org.apache.geode.tools.pulse.internal.controllers.PulseController;
+import org.apache.geode.tools.pulse.internal.data.PulseVersion;
import org.apache.geode.tools.pulse.internal.data.Repository;
public class PulseAppListenerUnitTest {
-
@Rule
public MockitoRule rule = MockitoJUnit.rule();
- private PulseAppListener subject;
-
@Mock
- private ServletContextEvent contextEvent;
+ private ContextRefreshedEvent contextEvent;
@Mock
private ServletContext servletContext;
@@ -59,23 +58,36 @@ public class PulseAppListenerUnitTest {
private Repository repository;
@Mock
- private BiFunction<String, ResourceBundle, Properties> loadProperties;
+ private PulseController pulseController;
+
+ @Mock
+ private PropertiesFileLoader loadProperties;
+
+ @Mock
+ private WebApplicationContext applicationContext;
private ResourceBundle resourceBundle;
+ private PulseVersion pulseVersion;
+ private PulseAppListener subject;
+
@Before
public void setUp() {
- when(loadProperties.apply(eq("GemFireVersion.properties"), any())).thenReturn(new Properties());
+ pulseVersion = new PulseVersion(repository);
}
@Test
public void contextInitialized_isEmbeddedModeWithoutSslProperties_doesNotSetSslProperties() {
resourceBundle = new StubResourceBundle();
- when(contextEvent.getServletContext()).thenReturn(servletContext);
+ when(loadProperties.loadProperties(eq("GemFireVersion.properties"), any()))
+ .thenReturn(new Properties());
+ when(contextEvent.getApplicationContext()).thenReturn(applicationContext);
+ when(applicationContext.getServletContext()).thenReturn(servletContext);
when(repository.getResourceBundle()).thenReturn(resourceBundle);
+ when(pulseController.getPulseVersion()).thenReturn(pulseVersion);
- subject = new PulseAppListener(true, repository, loadProperties);
+ subject = new PulseAppListener(true, loadProperties, pulseController, repository);
subject.contextInitialized(contextEvent);
@@ -88,11 +100,15 @@ public class PulseAppListenerUnitTest {
Properties sslProperties = new Properties();
- when(contextEvent.getServletContext()).thenReturn(servletContext);
+ when(contextEvent.getApplicationContext()).thenReturn(applicationContext);
+ when(applicationContext.getServletContext()).thenReturn(servletContext);
+ when(loadProperties.loadProperties(eq("GemFireVersion.properties"), any()))
+ .thenReturn(new Properties());
when(repository.getResourceBundle()).thenReturn(resourceBundle);
when(servletContext.getAttribute("org.apache.geode.sslConfig")).thenReturn(sslProperties);
+ when(pulseController.getPulseVersion()).thenReturn(pulseVersion);
- subject = new PulseAppListener(true, repository, loadProperties);
+ subject = new PulseAppListener(true, loadProperties, pulseController, repository);
subject.contextInitialized(contextEvent);
@@ -104,9 +120,10 @@ public class PulseAppListenerUnitTest {
resourceBundle = new StubResourceBundle();
when(repository.getResourceBundle()).thenReturn(resourceBundle);
- when(loadProperties.apply(anyString(), any())).thenReturn(new Properties());
+ when(loadProperties.loadProperties(anyString(), any())).thenReturn(new Properties());
+ when(pulseController.getPulseVersion()).thenReturn(pulseVersion);
- subject = new PulseAppListener(false, repository, loadProperties);
+ subject = new PulseAppListener(false, loadProperties, pulseController, repository);
subject.contextInitialized(contextEvent);
@@ -121,18 +138,21 @@ public class PulseAppListenerUnitTest {
sslProperties.put("foo", "bar");
when(repository.getResourceBundle()).thenReturn(resourceBundle);
- when(loadProperties.apply(eq("pulse.properties"), any())).thenReturn(new Properties());
- when(loadProperties.apply(eq("pulsesecurity.properties"), any())).thenReturn(sslProperties);
+ when(loadProperties.loadProperties(eq("pulse.properties"), any())).thenReturn(new Properties());
+ when(loadProperties.loadProperties(eq("pulsesecurity.properties"), any()))
+ .thenReturn(sslProperties);
+ when(loadProperties.loadProperties(eq("GemFireVersion.properties"), any()))
+ .thenReturn(new Properties());
+ when(pulseController.getPulseVersion()).thenReturn(pulseVersion);
- subject = new PulseAppListener(false, repository, loadProperties);
+ subject = new PulseAppListener(false, loadProperties, pulseController, repository);
subject.contextInitialized(contextEvent);
verify(repository).setJavaSslProperties(sslProperties);
}
- class StubResourceBundle extends ResourceBundle {
-
+ static class StubResourceBundle extends ResourceBundle {
@Override
protected Object handleGetObject(String key) {
return "the same string";
diff --git a/geode-pulse/src/test/java/org/apache/geode/tools/pulse/internal/data/JMXDataUpdaterGetDoubleAttributeTest.java b/geode-pulse/src/test/java/org/apache/geode/tools/pulse/internal/data/JMXDataUpdaterGetDoubleAttributeTest.java
index f3651fa..c4b0b8b 100644
--- a/geode-pulse/src/test/java/org/apache/geode/tools/pulse/internal/data/JMXDataUpdaterGetDoubleAttributeTest.java
+++ b/geode-pulse/src/test/java/org/apache/geode/tools/pulse/internal/data/JMXDataUpdaterGetDoubleAttributeTest.java
@@ -34,7 +34,7 @@ public class JMXDataUpdaterGetDoubleAttributeTest {
@Before
public void setUp() {
this.cluster = mock(Cluster.class);
- this.jmxDataUpdater = new JMXDataUpdater("server", "cluster", this.cluster);
+ this.jmxDataUpdater = new JMXDataUpdater("server", "cluster", this.cluster, null, null);
this.floatStat = 1.2345f;
this.doubleStat = 1.2345d;
}
diff --git a/geode-pulse/src/test/java/org/apache/geode/tools/pulse/internal/security/LogoutHandlerTest.java b/geode-pulse/src/test/java/org/apache/geode/tools/pulse/internal/security/LogoutHandlerTest.java
index 424fc57..d64e471 100644
--- a/geode-pulse/src/test/java/org/apache/geode/tools/pulse/internal/security/LogoutHandlerTest.java
+++ b/geode-pulse/src/test/java/org/apache/geode/tools/pulse/internal/security/LogoutHandlerTest.java
@@ -14,98 +14,81 @@
*/
package org.apache.geode.tools.pulse.internal.security;
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
-import static org.powermock.api.mockito.PowerMockito.spy;
-import static org.powermock.api.mockito.PowerMockito.when;
+import static org.mockito.Mockito.when;
-import java.util.Arrays;
-import java.util.Collection;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
import org.junit.Before;
+import org.junit.Rule;
import org.junit.Test;
import org.junit.experimental.categories.Category;
-import org.junit.runner.RunWith;
-import org.junit.runners.Parameterized;
-import org.junit.runners.Parameterized.Parameter;
-import org.junit.runners.Parameterized.Parameters;
-import org.junit.runners.Parameterized.UseParametersRunnerFactory;
-import org.mockito.Mockito;
-import org.powermock.core.classloader.annotations.PowerMockIgnore;
-import org.powermock.core.classloader.annotations.PrepareForTest;
-import org.powermock.modules.junit4.PowerMockRunner;
-import org.powermock.modules.junit4.PowerMockRunnerDelegate;
-import org.springframework.mock.web.MockHttpServletRequest;
-import org.springframework.mock.web.MockHttpServletResponse;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
+import org.springframework.context.ApplicationContext;
import org.springframework.security.core.Authentication;
import org.apache.geode.test.junit.categories.LoggingTest;
import org.apache.geode.test.junit.categories.PulseTest;
import org.apache.geode.test.junit.categories.SecurityTest;
-import org.apache.geode.test.junit.runners.CategoryWithParameterizedRunnerFactory;
-import org.apache.geode.tools.pulse.internal.data.Cluster;
import org.apache.geode.tools.pulse.internal.data.Repository;
-@RunWith(PowerMockRunner.class)
-@PrepareForTest(Repository.class)
-@PowerMockRunnerDelegate(Parameterized.class)
-@PowerMockIgnore({"javax.management.*", "javax.security.*", "*.UnitTest"})
-@UseParametersRunnerFactory(CategoryWithParameterizedRunnerFactory.class)
@Category({PulseTest.class, SecurityTest.class, LoggingTest.class})
public class LogoutHandlerTest {
+ private static final String EXPECTED_REDIRECT_URL = "/defaultTargetUrl";
- private static final String mockUser = "admin";
+ @Rule
+ public MockitoRule mockitoRule = MockitoJUnit.rule();
+ @Mock
+ private HttpServletRequest request;
+ @Mock
+ private HttpServletResponse response;
+ @Mock
private Repository repository;
- private LogoutHandler handler;
+ @Mock
+ private ApplicationContext applicationContext;
- @Parameter
- public static Authentication authentication;
-
- @Parameters(name = "{0}")
- public static Collection<Authentication> authentications() throws Exception {
- Authentication defaultAuthentication = mock(Authentication.class, "Default Authentication");
- when(defaultAuthentication.getName()).thenReturn(mockUser);
-
- GemFireAuthentication gemfireAuthentication =
- mock(GemFireAuthentication.class, "GemFire Authentication");
- when(gemfireAuthentication.getName()).thenReturn(mockUser);
-
- return Arrays.asList(defaultAuthentication, gemfireAuthentication);
- }
+ private final LogoutHandler handler = new LogoutHandler(EXPECTED_REDIRECT_URL);
@Before
- public void setup() throws Exception {
- Cluster cluster = Mockito.spy(Cluster.class);
- repository = Mockito.spy(Repository.class);
- spy(Repository.class);
- when(Repository.class, "get").thenReturn(repository);
- doReturn(cluster).when(repository).getCluster();
- handler = new LogoutHandler("/defaultTargetUrl");
+ public void setup() {
+ when(request.getContextPath()).thenReturn("");
+ when(response.encodeRedirectURL(EXPECTED_REDIRECT_URL)).thenReturn(EXPECTED_REDIRECT_URL);
+ handler.setApplicationContext(applicationContext);
}
@Test
- public void testNullAuthentication() throws Exception {
- MockHttpServletRequest request = new MockHttpServletRequest();
- MockHttpServletResponse response = new MockHttpServletResponse();
+ public void onLogoutSuccess_logsOutAuthenticatedUser() throws Exception {
+ String authenticatedUser = "authenticated-user";
- handler.onLogoutSuccess(request, response, null);
+ Authentication authentication = mock(Authentication.class);
+ when(authentication.getName()).thenReturn(authenticatedUser);
+ when(applicationContext.getBean("repository", Repository.class)).thenReturn(repository);
+
+ handler.onLogoutSuccess(request, response, authentication);
- assertThat(response.getStatus()).isEqualTo(302);
- assertThat(response.getHeader("Location")).isEqualTo("/defaultTargetUrl");
+ verify(repository, times(1)).logoutUser(authenticatedUser);
}
@Test
- public void testNotNullAuthentication() throws Exception {
- MockHttpServletRequest request = new MockHttpServletRequest();
- MockHttpServletResponse response = new MockHttpServletResponse();
+ public void onLogoutSuccess_redirectsToSpecifiedUrl() throws Exception {
+ when(applicationContext.getBean("repository", Repository.class)).thenReturn(repository);
+ handler.onLogoutSuccess(request, response, mock(Authentication.class));
- handler.onLogoutSuccess(request, response, authentication);
+ verify(response).sendRedirect(EXPECTED_REDIRECT_URL);
+ }
+
+ @Test
+ public void onLogoutSuccess_redirectsToSpecifiedUrl_evenIfNoAuthenticationGiven()
+ throws Exception {
+ handler.onLogoutSuccess(request, response, null);
- assertThat(response.getStatus()).isEqualTo(302);
- assertThat(response.getHeader("Location")).isEqualTo("/defaultTargetUrl");
- verify(repository, Mockito.times(1)).logoutUser(mockUser);
+ verify(response).sendRedirect(EXPECTED_REDIRECT_URL);
}
+
}