GEODE-1993: postprocess region/key in developer rest api * This closes #276
Project: http://git-wip-us.apache.org/repos/asf/incubator-geode/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-geode/commit/bd229d76 Tree: http://git-wip-us.apache.org/repos/asf/incubator-geode/tree/bd229d76 Diff: http://git-wip-us.apache.org/repos/asf/incubator-geode/diff/bd229d76 Branch: refs/heads/feature/GEODE-1930 Commit: bd229d7681376a11ba2e37747e48844ffe65584c Parents: e584c4e Author: Kevin Duling <kdul...@pivotal.io> Authored: Fri Oct 28 13:27:56 2016 -0700 Committer: Jinmei Liao <jil...@pivotal.io> Committed: Thu Nov 10 14:59:47 2016 -0800 ---------------------------------------------------------------------- .../web/RestSecurityPostProcessorTest.java | 188 +++++++++++++++++++ .../rest/internal/web/controllers/Customer.java | 26 ++- .../web/controllers/RedactingPostProcessor.java | 67 +++++++ .../RestAPIsQueryAndFEJUnitTest.java | 61 +++--- .../cache/query/internal/CompiledValue.java | 9 +- .../cache/query/internal/DefaultQuery.java | 39 +++- .../security/IntegratedSecurityService.java | 4 +- .../apache/geode/security/PostProcessor.java | 2 +- .../PdxLocalQueryVersionedClassDUnitTest.java | 5 +- .../ClientServerFunctionExecutionDUnitTest.java | 19 +- .../internal/cache/functions/TestFunction.java | 1 - .../security/NoShowValue1PostProcessor.java | 4 - .../apache/geode/security/PDXPostProcessor.java | 10 +- .../web/controllers/AbstractBaseController.java | 37 ++-- .../controllers/FunctionAccessController.java | 15 +- .../web/controllers/PdxBasedCrudController.java | 21 +-- .../web/controllers/QueryAccessController.java | 24 ++- .../web/security/RestSecurityService.java | 8 +- .../rest/internal/web/util/JsonWriter.java | 51 ++--- 19 files changed, 442 insertions(+), 149 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/bd229d76/geode-assembly/src/test/java/org/apache/geode/rest/internal/web/RestSecurityPostProcessorTest.java ---------------------------------------------------------------------- diff --git a/geode-assembly/src/test/java/org/apache/geode/rest/internal/web/RestSecurityPostProcessorTest.java b/geode-assembly/src/test/java/org/apache/geode/rest/internal/web/RestSecurityPostProcessorTest.java new file mode 100644 index 0000000..72b589f --- /dev/null +++ b/geode-assembly/src/test/java/org/apache/geode/rest/internal/web/RestSecurityPostProcessorTest.java @@ -0,0 +1,188 @@ +/* + * 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.rest.internal.web; + +import static org.apache.geode.distributed.ConfigurationProperties.HTTP_SERVICE_BIND_ADDRESS; +import static org.apache.geode.distributed.ConfigurationProperties.HTTP_SERVICE_PORT; +import static org.apache.geode.distributed.ConfigurationProperties.SECURITY_MANAGER; +import static org.apache.geode.distributed.ConfigurationProperties.SECURITY_POST_PROCESSOR; +import static org.apache.geode.distributed.ConfigurationProperties.START_DEV_REST_API; +import static org.apache.geode.rest.internal.web.GeodeRestClient.getCode; +import static org.apache.geode.rest.internal.web.GeodeRestClient.getContentType; +import static org.apache.geode.rest.internal.web.GeodeRestClient.getJsonArray; +import static org.apache.geode.rest.internal.web.GeodeRestClient.getJsonObject; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import org.apache.geode.cache.Region; +import org.apache.geode.cache.RegionShortcut; +import org.apache.geode.internal.AvailablePortHelper; +import org.apache.geode.rest.internal.web.controllers.Customer; +import org.apache.geode.rest.internal.web.controllers.RedactingPostProcessor; +import org.apache.geode.security.templates.SampleSecurityManager; +import org.apache.geode.test.dunit.rules.ServerStarterRule; +import org.apache.geode.test.junit.categories.IntegrationTest; +import org.apache.geode.test.junit.categories.SecurityTest; +import org.apache.http.HttpResponse; +import org.json.JSONArray; +import org.json.JSONObject; +import org.junit.BeforeClass; +import org.junit.ClassRule; +import org.junit.Test; +import org.junit.experimental.categories.Category; +import org.springframework.http.MediaType; + +import java.net.URLEncoder; +import java.util.Properties; + + +@Category({IntegrationTest.class, SecurityTest.class}) +public class RestSecurityPostProcessorTest { + + static int restPort = AvailablePortHelper.getRandomAvailableTCPPort(); + static Properties properties = new Properties() { + { + setProperty(SampleSecurityManager.SECURITY_JSON, + "org/apache/geode/management/internal/security/clientServer.json"); + setProperty(SECURITY_MANAGER, SampleSecurityManager.class.getName()); + setProperty(START_DEV_REST_API, "true"); + setProperty(HTTP_SERVICE_BIND_ADDRESS, "localhost"); + setProperty(HTTP_SERVICE_PORT, restPort + ""); + setProperty(SECURITY_POST_PROCESSOR, RedactingPostProcessor.class.getName()); + } + }; + + @ClassRule + public static ServerStarterRule serverStarter = new ServerStarterRule(properties); + private final GeodeRestClient restClient = new GeodeRestClient("localhost", restPort); + + @BeforeClass + public static void before() throws Exception { + Region region = + serverStarter.cache.createRegionFactory(RegionShortcut.REPLICATE).create("customers"); + region.put("1", new Customer(1L, "John", "Doe", "555555555")); + region.put("2", new Customer(2L, "Richard", "Roe", "222533554")); + region.put("3", new Customer(3L, "Jane", "Doe", "555223333")); + region.put("4", new Customer(4L, "Jane", "Roe", "555443333")); + } + + /** + * Test post-processing of a retrieved key from the server. + */ + @Test + public void getRegionKey() throws Exception { + // Test a single key + HttpResponse response = restClient.doGet("/customers/1", "dataReader", "1234567"); + assertEquals(200, getCode(response)); + assertEquals(MediaType.APPLICATION_JSON_UTF8_VALUE, getContentType(response)); + + // Ensure SSN is hidden + JSONObject jsonObject = getJsonObject(response); + assertEquals("*********", jsonObject.getString("socialSecurityNumber")); + assertEquals(1L, jsonObject.getLong("customerId")); + + // Try with super-user + response = restClient.doGet("/customers/1", "super-user", "1234567"); + assertEquals(200, getCode(response)); + assertEquals(MediaType.APPLICATION_JSON_UTF8_VALUE, getContentType(response)); + + // ensure SSN is readable + jsonObject = getJsonObject(response); + assertEquals("555555555", jsonObject.getString("socialSecurityNumber")); + assertEquals(1L, jsonObject.getLong("customerId")); + } + + // Test multiple keys + @Test + public void getMultipleRegionKeys() throws Exception { + HttpResponse response = restClient.doGet("/customers/1,3", "dataReader", "1234567"); + assertEquals(200, getCode(response)); + assertEquals(MediaType.APPLICATION_JSON_UTF8_VALUE, getContentType(response)); + + JSONObject jsonObject = getJsonObject(response); + JSONArray jsonArray = jsonObject.getJSONArray("customers"); + final int length = jsonArray.length(); + assertEquals(2, length); + JSONObject customer = jsonArray.getJSONObject(0); + assertEquals("*********", customer.getString("socialSecurityNumber")); + assertEquals(1, customer.getLong("customerId")); + customer = jsonArray.getJSONObject(1); + assertEquals("*********", customer.getString("socialSecurityNumber")); + assertEquals(3, customer.getLong("customerId")); + } + + @Test + public void getRegion() throws Exception { + HttpResponse response = restClient.doGet("/customers", "dataReader", "1234567"); + assertEquals(200, getCode(response)); + assertEquals(MediaType.APPLICATION_JSON_UTF8_VALUE, getContentType(response)); + + JSONObject jsonObject = getJsonObject(response); + JSONArray jsonArray = jsonObject.getJSONArray("customers"); + final int length = jsonArray.length(); + for (int index = 0; index < length; ++index) { + JSONObject customer = jsonArray.getJSONObject(index); + assertEquals("*********", customer.getString("socialSecurityNumber")); + assertEquals((long) index + 1, customer.getLong("customerId")); + } + } + + @Test + public void adhocQuery() throws Exception { + String query = "/queries/adhoc?q=" + + URLEncoder.encode("SELECT * FROM /customers order by customerId", "UTF-8"); + HttpResponse response = restClient.doGet(query, "dataReader", "1234567"); + assertEquals(200, getCode(response)); + assertEquals(MediaType.APPLICATION_JSON_UTF8_VALUE, getContentType(response)); + + JSONArray jsonArray = getJsonArray(response); + final int length = jsonArray.length(); + for (int index = 0; index < length; ++index) { + JSONObject customer = jsonArray.getJSONObject(index); + assertEquals("*********", customer.getString("socialSecurityNumber")); + assertEquals((long) index + 1, customer.getLong("customerId")); + } + } + + @Test + public void namedQuery() throws Exception { + // Declare the named query + String namedQuery = "SELECT c FROM /customers c WHERE c.customerId = $1"; + + // Install the named query + HttpResponse response = + restClient.doPost("/queries?id=selectCustomer&q=" + URLEncoder.encode(namedQuery, "UTF-8"), + "dataReader", "1234567", ""); + assertEquals(201, getCode(response)); + + // Verify the query has been installed + String query = "/queries"; + response = restClient.doGet(query, "dataReader", "1234567"); + assertEquals(200, getCode(response)); + assertEquals(MediaType.APPLICATION_JSON_UTF8_VALUE, getContentType(response)); + + // Execute the query + response = restClient.doPost("/queries/selectCustomer", "dataReader", "1234567", + "{" + "\"@type\": \"int\"," + "\"@value\": 1" + "}"); + assertEquals(200, getCode(response)); + + // Validate the result + JSONArray jsonArray = getJsonArray(response); + assertTrue(jsonArray.length() == 1); + JSONObject customer = jsonArray.getJSONObject(0); + assertEquals("*********", customer.getString("socialSecurityNumber")); + assertEquals(1L, customer.getLong("customerId")); + } +} http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/bd229d76/geode-assembly/src/test/java/org/apache/geode/rest/internal/web/controllers/Customer.java ---------------------------------------------------------------------- diff --git a/geode-assembly/src/test/java/org/apache/geode/rest/internal/web/controllers/Customer.java b/geode-assembly/src/test/java/org/apache/geode/rest/internal/web/controllers/Customer.java index 263e6c7..9732aa0 100644 --- a/geode-assembly/src/test/java/org/apache/geode/rest/internal/web/controllers/Customer.java +++ b/geode-assembly/src/test/java/org/apache/geode/rest/internal/web/controllers/Customer.java @@ -14,21 +14,28 @@ */ package org.apache.geode.rest.internal.web.controllers; -import java.io.Serializable; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonInclude.Include; +import com.fasterxml.jackson.annotation.JsonProperty; import org.apache.geode.internal.lang.ObjectUtils; +import java.io.Serializable; + /** * The Customer class models a customer entity. * <p/> * * @since GemFire 8.0 */ - +@JsonInclude(Include.NON_NULL) public class Customer implements Serializable { + @JsonProperty("id") private Long customerId; private String firstName; private String lastName; + @JsonProperty("ssn") + private String socialSecurityNumber; public Customer() {} @@ -36,10 +43,11 @@ public class Customer implements Serializable { this.customerId = custId; } - public Customer(final Long custId, final String fname, final String lname) { + public Customer(final Long custId, final String fname, final String lname, final String ssn) { this.customerId = custId; this.firstName = fname; this.lastName = lname; + this.socialSecurityNumber = ssn; } public Long getCustomerId() { @@ -80,7 +88,16 @@ public class Customer implements Serializable { return (ObjectUtils.equals(this.getCustomerId(), that.getCustomerId()) && ObjectUtils.equals(this.getLastName(), that.getLastName()) - && ObjectUtils.equals(this.getFirstName(), that.getFirstName())); + && ObjectUtils.equals(this.getFirstName(), that.getFirstName()) + && ObjectUtils.equals(this.getSocialSecurityNumber(), that.getSocialSecurityNumber())); + } + + public String getSocialSecurityNumber() { + return socialSecurityNumber; + } + + public void setSocialSecurityNumber(final String ssn) { + this.socialSecurityNumber = ssn; } @Override @@ -99,6 +116,7 @@ public class Customer implements Serializable { buffer.append(", customerId = ").append(getCustomerId()); buffer.append(", firstName = ").append(getFirstName()); buffer.append(", lastName = ").append(getLastName()); + buffer.append(", ssn = ").append(getSocialSecurityNumber()); buffer.append(" }"); return buffer.toString(); } http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/bd229d76/geode-assembly/src/test/java/org/apache/geode/rest/internal/web/controllers/RedactingPostProcessor.java ---------------------------------------------------------------------- diff --git a/geode-assembly/src/test/java/org/apache/geode/rest/internal/web/controllers/RedactingPostProcessor.java b/geode-assembly/src/test/java/org/apache/geode/rest/internal/web/controllers/RedactingPostProcessor.java new file mode 100644 index 0000000..7ec14bf --- /dev/null +++ b/geode-assembly/src/test/java/org/apache/geode/rest/internal/web/controllers/RedactingPostProcessor.java @@ -0,0 +1,67 @@ +/* + * 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.rest.internal.web.controllers; + +import org.apache.geode.security.PostProcessor; + +import java.security.Principal; +import java.util.Properties; + +/** + * This is example that implements PostProcessor that will redact Social Security Numbers from + * Customer objects + */ +public class RedactingPostProcessor implements PostProcessor { + + @Override + public void init(final Properties securityProps) {} + + /** + * Protect the Customer's Social Security Number from unauthorized users + * + * @param principal The principal that's accessing the value + * @param regionName The region that's been accessed. This could be null. + * @param id the customer id the lookup was done with. This could be null. + * @param customer a @Customer object, this could be null. + * @return the processed value + */ + @Override + public Object processRegionValue(Object principal, String regionName, Object id, + Object customer) { + if (customer == null) + return null; + if (customer instanceof Customer) { + String username = getUsername(principal); + // Unable to retrieve the role at this point, so for this demo we'll just work with the + // username + if (username.equals("super-user")) + return customer; + Customer cust = (Customer) customer; + return new Customer(cust.getCustomerId(), cust.getFirstName(), cust.getLastName(), + "*********"); + } else + return customer; + } + + private String getUsername(final Object principal) { + String name = null; + if (principal instanceof Principal) { + name = ((Principal) principal).getName(); + } else { + name = principal.toString(); + } + return name; + } +} http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/bd229d76/geode-assembly/src/test/java/org/apache/geode/rest/internal/web/controllers/RestAPIsQueryAndFEJUnitTest.java ---------------------------------------------------------------------- diff --git a/geode-assembly/src/test/java/org/apache/geode/rest/internal/web/controllers/RestAPIsQueryAndFEJUnitTest.java b/geode-assembly/src/test/java/org/apache/geode/rest/internal/web/controllers/RestAPIsQueryAndFEJUnitTest.java index 5397b95..f054110 100644 --- a/geode-assembly/src/test/java/org/apache/geode/rest/internal/web/controllers/RestAPIsQueryAndFEJUnitTest.java +++ b/geode-assembly/src/test/java/org/apache/geode/rest/internal/web/controllers/RestAPIsQueryAndFEJUnitTest.java @@ -14,34 +14,13 @@ */ package org.apache.geode.rest.internal.web.controllers; -import static org.apache.geode.distributed.ConfigurationProperties.*; -import static org.junit.Assert.*; - -import java.net.InetAddress; -import java.net.UnknownHostException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Properties; - -import org.json.JSONArray; -import org.json.JSONException; -import org.json.JSONObject; -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.junit.experimental.categories.Category; -import org.springframework.http.HttpEntity; -import org.springframework.http.HttpHeaders; -import org.springframework.http.HttpMethod; -import org.springframework.http.HttpStatus; -import org.springframework.http.MediaType; -import org.springframework.http.ResponseEntity; -import org.springframework.util.StringUtils; -import org.springframework.web.client.HttpClientErrorException; -import org.springframework.web.client.HttpServerErrorException; +import static org.apache.geode.distributed.ConfigurationProperties.HTTP_SERVICE_BIND_ADDRESS; +import static org.apache.geode.distributed.ConfigurationProperties.HTTP_SERVICE_PORT; +import static org.apache.geode.distributed.ConfigurationProperties.MCAST_PORT; +import static org.apache.geode.distributed.ConfigurationProperties.START_DEV_REST_API; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; import org.apache.geode.cache.AttributesFactory; import org.apache.geode.cache.Cache; @@ -67,6 +46,31 @@ import org.apache.geode.internal.net.SocketCreator; import org.apache.geode.management.internal.AgentUtil; import org.apache.geode.management.internal.ManagementConstants; import org.apache.geode.test.junit.categories.IntegrationTest; +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.experimental.categories.Category; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpMethod; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.util.StringUtils; +import org.springframework.web.client.HttpClientErrorException; +import org.springframework.web.client.HttpServerErrorException; + +import java.net.InetAddress; +import java.net.UnknownHostException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Properties; @Category(IntegrationTest.class) public class RestAPIsQueryAndFEJUnitTest { @@ -761,7 +765,6 @@ public class RestAPIsQueryAndFEJUnitTest { entity = new HttpEntity<>(TEST_DATA[index][REQUEST_BODY_INDEX], headers); ResponseEntity<String> result = RestTestUtils.getRestTemplate().exchange(restRequestUrl, (HttpMethod) TEST_DATA[index][METHOD_INDEX], entity, String.class); - validateGetAllResult(index, result); validateQueryResult(index, result); http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/bd229d76/geode-core/src/main/java/org/apache/geode/cache/query/internal/CompiledValue.java ---------------------------------------------------------------------- diff --git a/geode-core/src/main/java/org/apache/geode/cache/query/internal/CompiledValue.java b/geode-core/src/main/java/org/apache/geode/cache/query/internal/CompiledValue.java index a2844fd..9da575d 100644 --- a/geode-core/src/main/java/org/apache/geode/cache/query/internal/CompiledValue.java +++ b/geode-core/src/main/java/org/apache/geode/cache/query/internal/CompiledValue.java @@ -14,7 +14,12 @@ */ package org.apache.geode.cache.query.internal; -import org.apache.geode.cache.query.*; +import org.apache.geode.cache.query.AmbiguousNameException; +import org.apache.geode.cache.query.FunctionDomainException; +import org.apache.geode.cache.query.NameResolutionException; +import org.apache.geode.cache.query.QueryInvalidException; +import org.apache.geode.cache.query.QueryInvocationTargetException; +import org.apache.geode.cache.query.TypeMismatchException; import org.apache.geode.cache.query.internal.parse.OQLLexerTokenTypes; import org.apache.geode.cache.query.types.ObjectType; import org.apache.geode.distributed.internal.DistributionConfig; @@ -120,7 +125,7 @@ public interface CompiledValue { /** * Populates the Set passed with the name of the Region which, if any , will be the bottommost - * object (CompiledRegion). The default implemenation is provided in the AbstractCompiledValue & + * object (CompiledRegion). The default implementation is provided in the AbstractCompiledValue & * overridden in the CompiledSelect as it can contain multiple iterators */ public void getRegionsInQuery(Set regionNames, Object[] parameters); http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/bd229d76/geode-core/src/main/java/org/apache/geode/cache/query/internal/DefaultQuery.java ---------------------------------------------------------------------- diff --git a/geode-core/src/main/java/org/apache/geode/cache/query/internal/DefaultQuery.java b/geode-core/src/main/java/org/apache/geode/cache/query/internal/DefaultQuery.java index 78054ad..068f1d1 100644 --- a/geode-core/src/main/java/org/apache/geode/cache/query/internal/DefaultQuery.java +++ b/geode-core/src/main/java/org/apache/geode/cache/query/internal/DefaultQuery.java @@ -26,16 +26,39 @@ import org.apache.geode.cache.execute.Function; import org.apache.geode.cache.execute.RegionFunctionContext; import org.apache.geode.cache.partition.PartitionRegionHelper; import org.apache.geode.cache.persistence.PartitionOfflineException; -import org.apache.geode.cache.persistence.PersistentID; -import org.apache.geode.cache.query.*; +import org.apache.geode.cache.query.FunctionDomainException; +import org.apache.geode.cache.query.NameResolutionException; +import org.apache.geode.cache.query.Query; +import org.apache.geode.cache.query.QueryException; +import org.apache.geode.cache.query.QueryInvalidException; +import org.apache.geode.cache.query.QueryInvocationTargetException; +import org.apache.geode.cache.query.QueryService; +import org.apache.geode.cache.query.QueryStatistics; +import org.apache.geode.cache.query.RegionNotFoundException; +import org.apache.geode.cache.query.SelectResults; +import org.apache.geode.cache.query.TypeMismatchException; import org.apache.geode.cache.query.internal.cq.InternalCqQuery; import org.apache.geode.distributed.internal.DistributionConfig; import org.apache.geode.internal.NanoTimer; -import org.apache.geode.internal.cache.*; -import org.apache.geode.internal.cache.partitioned.RegionAdvisor; +import org.apache.geode.internal.cache.BucketRegion; +import org.apache.geode.internal.cache.CachePerfStats; +import org.apache.geode.internal.cache.GemFireCacheImpl; +import org.apache.geode.internal.cache.LocalDataSet; +import org.apache.geode.internal.cache.PRQueryProcessor; +import org.apache.geode.internal.cache.PartitionedRegion; +import org.apache.geode.internal.cache.TXManagerImpl; +import org.apache.geode.internal.cache.TXStateProxy; import org.apache.geode.internal.i18n.LocalizedStrings; -import java.util.*; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Set; import java.util.concurrent.atomic.AtomicLong; @@ -771,9 +794,9 @@ public class DefaultQuery implements Query { /** * Returns an unmodifiable Set containing the Region names which are present in the Query. A - * region which is assosciated with the query as a bind parameter will not be included in the - * list. The Region names returned by the query do not indicate anything about the state of the - * region or whether the region actually exists in the GemfireCache etc. + * region which is associated with the query as a bind parameter will not be included in the list. + * The Region names returned by the query do not indicate anything about the state of the region + * or whether the region actually exists in the GemfireCache etc. * * @param parameters the parameters to be passed in to the query when executed * @return Unmodifiable List containing the region names. http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/bd229d76/geode-core/src/main/java/org/apache/geode/internal/security/IntegratedSecurityService.java ---------------------------------------------------------------------- diff --git a/geode-core/src/main/java/org/apache/geode/internal/security/IntegratedSecurityService.java b/geode-core/src/main/java/org/apache/geode/internal/security/IntegratedSecurityService.java index 57cb2db..73d051f 100644 --- a/geode-core/src/main/java/org/apache/geode/internal/security/IntegratedSecurityService.java +++ b/geode-core/src/main/java/org/apache/geode/internal/security/IntegratedSecurityService.java @@ -440,7 +440,9 @@ public class IntegratedSecurityService implements SecurityService { } /** - * If Shiro's security manager is configured, then return true, otherwise, return false; + * check if Shiro's security manager is configured + * + * @return true if configured, false if not */ public boolean isIntegratedSecurity() { if (isIntegratedSecurity != null) { http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/bd229d76/geode-core/src/main/java/org/apache/geode/security/PostProcessor.java ---------------------------------------------------------------------- diff --git a/geode-core/src/main/java/org/apache/geode/security/PostProcessor.java b/geode-core/src/main/java/org/apache/geode/security/PostProcessor.java index 3cfcace..707e3cf 100644 --- a/geode-core/src/main/java/org/apache/geode/security/PostProcessor.java +++ b/geode-core/src/main/java/org/apache/geode/security/PostProcessor.java @@ -39,7 +39,7 @@ public interface PostProcessor { * depend on how you implemented your SecurityManager * @param regionName The region that's been accessed. This could be null. * @param key the key of the value that's been accessed. This could be null. - * @param value the original value. The orginal value could be null as well. + * @param value the original value. The original value could be null as well. * @return the value that will be returned to the requester */ Object processRegionValue(Object principal, String regionName, Object key, Object value); http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/bd229d76/geode-core/src/test/java/org/apache/geode/cache/query/dunit/PdxLocalQueryVersionedClassDUnitTest.java ---------------------------------------------------------------------- diff --git a/geode-core/src/test/java/org/apache/geode/cache/query/dunit/PdxLocalQueryVersionedClassDUnitTest.java b/geode-core/src/test/java/org/apache/geode/cache/query/dunit/PdxLocalQueryVersionedClassDUnitTest.java index 2a8a64c..fda6cf4 100644 --- a/geode-core/src/test/java/org/apache/geode/cache/query/dunit/PdxLocalQueryVersionedClassDUnitTest.java +++ b/geode-core/src/test/java/org/apache/geode/cache/query/dunit/PdxLocalQueryVersionedClassDUnitTest.java @@ -14,9 +14,6 @@ */ package org.apache.geode.cache.query.dunit; -import org.apache.geode.test.junit.categories.DistributedTest; -import org.junit.Test; - import org.apache.geode.cache.Region; import org.apache.geode.cache.RegionShortcut; import org.apache.geode.cache.client.ClientCache; @@ -36,6 +33,8 @@ import org.apache.geode.test.dunit.NetworkUtils; import org.apache.geode.test.dunit.SerializableCallable; import org.apache.geode.test.dunit.ThreadUtils; import org.apache.geode.test.dunit.VM; +import org.apache.geode.test.junit.categories.DistributedTest; +import org.junit.Test; import org.junit.experimental.categories.Category; @Category(DistributedTest.class) http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/bd229d76/geode-core/src/test/java/org/apache/geode/internal/cache/execute/ClientServerFunctionExecutionDUnitTest.java ---------------------------------------------------------------------- diff --git a/geode-core/src/test/java/org/apache/geode/internal/cache/execute/ClientServerFunctionExecutionDUnitTest.java b/geode-core/src/test/java/org/apache/geode/internal/cache/execute/ClientServerFunctionExecutionDUnitTest.java index 07f6537..ce4df64 100755 --- a/geode-core/src/test/java/org/apache/geode/internal/cache/execute/ClientServerFunctionExecutionDUnitTest.java +++ b/geode-core/src/test/java/org/apache/geode/internal/cache/execute/ClientServerFunctionExecutionDUnitTest.java @@ -14,15 +14,12 @@ */ package org.apache.geode.internal.cache.execute; -import org.junit.experimental.categories.Category; -import org.junit.Test; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; -import static org.junit.Assert.*; - -import org.apache.geode.test.dunit.cache.internal.JUnit4CacheTestCase; -import org.apache.geode.test.dunit.internal.JUnit4DistributedTestCase; -import org.apache.geode.test.junit.categories.DistributedTest; -import org.apache.geode.test.junit.categories.FlakyTest; import org.apache.geode.cache.AttributesFactory; import org.apache.geode.cache.DataPolicy; import org.apache.geode.cache.Region; @@ -41,20 +38,20 @@ import org.apache.geode.distributed.DistributedSystem; import org.apache.geode.internal.cache.functions.TestFunction; import org.apache.geode.internal.cache.tier.sockets.CacheServerTestUtil; import org.apache.geode.test.dunit.Assert; -import org.apache.geode.test.dunit.AsyncInvocation; import org.apache.geode.test.dunit.IgnoredException; import org.apache.geode.test.dunit.LogWriterUtils; import org.apache.geode.test.dunit.NetworkUtils; import org.apache.geode.test.dunit.Wait; import org.apache.geode.test.dunit.WaitCriterion; +import org.apache.geode.test.junit.categories.DistributedTest; +import org.junit.Test; +import org.junit.experimental.categories.Category; import java.io.Serializable; import java.util.ArrayList; import java.util.HashSet; import java.util.Iterator; import java.util.List; -import java.util.Set; -import java.util.concurrent.Callable; @Category(DistributedTest.class) public class ClientServerFunctionExecutionDUnitTest extends PRClientServerTestBase { http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/bd229d76/geode-core/src/test/java/org/apache/geode/internal/cache/functions/TestFunction.java ---------------------------------------------------------------------- diff --git a/geode-core/src/test/java/org/apache/geode/internal/cache/functions/TestFunction.java b/geode-core/src/test/java/org/apache/geode/internal/cache/functions/TestFunction.java index 4182bf9..2a5f51f 100755 --- a/geode-core/src/test/java/org/apache/geode/internal/cache/functions/TestFunction.java +++ b/geode-core/src/test/java/org/apache/geode/internal/cache/functions/TestFunction.java @@ -34,7 +34,6 @@ import org.apache.geode.internal.Assert; import org.apache.geode.internal.cache.CacheServerImpl; import org.apache.geode.internal.cache.GemFireCacheImpl; import org.apache.geode.internal.cache.PartitionedRegion; -import org.apache.geode.internal.cache.PartitionedRegionDataStore; import org.apache.geode.internal.cache.execute.InternalFunctionInvocationTargetException; import org.apache.geode.internal.cache.execute.MyFunctionExecutionException; import org.apache.geode.internal.cache.execute.RegionFunctionContextImpl; http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/bd229d76/geode-core/src/test/java/org/apache/geode/security/NoShowValue1PostProcessor.java ---------------------------------------------------------------------- diff --git a/geode-core/src/test/java/org/apache/geode/security/NoShowValue1PostProcessor.java b/geode-core/src/test/java/org/apache/geode/security/NoShowValue1PostProcessor.java index 8aeecae..078448c 100644 --- a/geode-core/src/test/java/org/apache/geode/security/NoShowValue1PostProcessor.java +++ b/geode-core/src/test/java/org/apache/geode/security/NoShowValue1PostProcessor.java @@ -14,10 +14,6 @@ */ package org.apache.geode.security; -import java.io.Serializable; - -import org.apache.geode.security.PostProcessor; - public class NoShowValue1PostProcessor implements PostProcessor { @Override http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/bd229d76/geode-core/src/test/java/org/apache/geode/security/PDXPostProcessor.java ---------------------------------------------------------------------- diff --git a/geode-core/src/test/java/org/apache/geode/security/PDXPostProcessor.java b/geode-core/src/test/java/org/apache/geode/security/PDXPostProcessor.java index aeebd15..2b84246 100644 --- a/geode-core/src/test/java/org/apache/geode/security/PDXPostProcessor.java +++ b/geode-core/src/test/java/org/apache/geode/security/PDXPostProcessor.java @@ -14,16 +14,14 @@ */ package org.apache.geode.security; -import static org.junit.Assert.*; - -import java.util.Arrays; -import java.util.Properties; - -import org.apache.geode.security.PostProcessor; +import static org.junit.Assert.assertTrue; import org.apache.geode.pdx.SimpleClass; import org.apache.geode.pdx.internal.PdxInstanceImpl; +import java.util.Arrays; +import java.util.Properties; + public class PDXPostProcessor implements PostProcessor { public static byte[] BYTES = {1, 0}; http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/bd229d76/geode-web-api/src/main/java/org/apache/geode/rest/internal/web/controllers/AbstractBaseController.java ---------------------------------------------------------------------- diff --git a/geode-web-api/src/main/java/org/apache/geode/rest/internal/web/controllers/AbstractBaseController.java b/geode-web-api/src/main/java/org/apache/geode/rest/internal/web/controllers/AbstractBaseController.java index 80297b5..b9d2bf4 100644 --- a/geode-web-api/src/main/java/org/apache/geode/rest/internal/web/controllers/AbstractBaseController.java +++ b/geode-web-api/src/main/java/org/apache/geode/rest/internal/web/controllers/AbstractBaseController.java @@ -27,6 +27,7 @@ import org.apache.geode.cache.LowMemoryException; import org.apache.geode.cache.PartitionedRegionStorageException; import org.apache.geode.cache.Region; import org.apache.geode.cache.TimeoutException; +import org.apache.geode.cache.query.Query; import org.apache.geode.cache.query.QueryService; import org.apache.geode.distributed.DistributedMember; import org.apache.geode.distributed.LeaseExpiredException; @@ -44,6 +45,7 @@ import org.apache.geode.rest.internal.web.exception.GemfireRestException; import org.apache.geode.rest.internal.web.exception.MalformedJsonException; import org.apache.geode.rest.internal.web.exception.RegionNotFoundException; import org.apache.geode.rest.internal.web.exception.ResourceNotFoundException; +import org.apache.geode.rest.internal.web.security.RestSecurityService; import org.apache.geode.rest.internal.web.util.ArrayUtils; import org.apache.geode.rest.internal.web.util.IdentifiableUtils; import org.apache.geode.rest.internal.web.util.JSONUtils; @@ -91,18 +93,17 @@ import javax.annotation.PostConstruct; @SuppressWarnings("unused") public abstract class AbstractBaseController { - private static final Logger logger = LogService.getLogger(); - protected static final String NEW_META_DATA_PROPERTY = "@new"; protected static final String OLD_META_DATA_PROPERTY = "@old"; protected static final String TYPE_META_DATA_PROPERTY = "@type"; - protected static final String UTF_8 = "UTF-8"; protected static final String DEFAULT_ENCODING = UTF_8; + private static final Logger logger = LogService.getLogger(); private static final AtomicLong ID_SEQUENCE = new AtomicLong(0l); // private Cache cache = GemFireCacheImpl.getExisting(null); - + @Autowired + protected RestSecurityService securityService; @Autowired private ObjectMapper objectMapper; @@ -190,15 +191,18 @@ public abstract class AbstractBaseController { } } - public ResponseEntity<String> processQueryResponse(Object queryResult, String queryId) + public ResponseEntity<String> processQueryResponse(Query query, Object args[], Object queryResult) throws JSONException { if (queryResult instanceof Collection<?>) { - Collection<Object> result = (Collection<Object>) queryResult; - String queryResultAsJson = JSONUtils.convertCollectionToJson(result); + Collection processedResults = new ArrayList(((Collection) queryResult).size()); + for (Object result : (Collection) queryResult) { + processedResults.add(securityService.postProcess(null, null, result, false)); + } + String queryResultAsJson = JSONUtils.convertCollectionToJson(processedResults); final HttpHeaders headers = new HttpHeaders(); - headers.setLocation(toUri("queries", queryId)); - return new ResponseEntity<String>(queryResultAsJson, headers, HttpStatus.OK); + headers.setLocation(toUri("queries", query.getQueryString())); + return new ResponseEntity<>(queryResultAsJson, headers, HttpStatus.OK); } else { throw new GemfireRestException( "Server has encountered error while generating query result into restful format(JSON)!"); @@ -211,7 +215,6 @@ public abstract class AbstractBaseController { jsonArr = new JSONArray(jsonArray); Collection<PdxInstance> pdxInstances = new ArrayList<PdxInstance>(); - for (int index = 0; index < jsonArr.length(); index++) { // String element = jsonArr.getJSONObject(i).toString(); // String element = jsonArr.getString(i); @@ -639,6 +642,10 @@ public abstract class AbstractBaseController { try { final Region<Object, T> region = getRegion(regionNamePath); final Map<Object, T> entries = region.getAll(Arrays.asList(getKeys(regionNamePath, keys))); + for (Object key : entries.keySet()) { + entries.put(key, + (T) securityService.postProcess(regionNamePath, key, entries.get(key), false)); + } return entries; } catch (SerializationException se) { throw new DataTypeNotSupportedException( @@ -881,12 +888,20 @@ public abstract class AbstractBaseController { @SuppressWarnings("unchecked") protected <T> T getValue(final String regionNamePath, final Object key) { + return getValue(regionNamePath, key, true); + } + + protected <T> T getValue(final String regionNamePath, final Object key, boolean postProcess) { Assert.notNull(key, "The Cache Region key to read the value for cannot be null!"); Region r = getRegion(regionNamePath); try { Object value = r.get(key); - return (T) value; + if (postProcess) { + return (T) securityService.postProcess(regionNamePath, key, value, false); + } else { + return (T) value; + } } catch (SerializationException se) { throw new DataTypeNotSupportedException( "The resource identified could not convert into the supported content characteristics (JSON)!", http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/bd229d76/geode-web-api/src/main/java/org/apache/geode/rest/internal/web/controllers/FunctionAccessController.java ---------------------------------------------------------------------- diff --git a/geode-web-api/src/main/java/org/apache/geode/rest/internal/web/controllers/FunctionAccessController.java b/geode-web-api/src/main/java/org/apache/geode/rest/internal/web/controllers/FunctionAccessController.java index ec05ec7..08ec9a1 100644 --- a/geode-web-api/src/main/java/org/apache/geode/rest/internal/web/controllers/FunctionAccessController.java +++ b/geode-web-api/src/main/java/org/apache/geode/rest/internal/web/controllers/FunctionAccessController.java @@ -63,15 +63,14 @@ import java.util.Set; @RequestMapping(FunctionAccessController.REST_API_VERSION + "/functions") @SuppressWarnings("unused") public class FunctionAccessController extends AbstractBaseController { - private static final Logger logger = LogService.getLogger(); - // Constant String value indicating the version of the REST API. protected static final String REST_API_VERSION = "/v1"; + private static final Logger logger = LogService.getLogger(); /** * Gets the version of the REST API implemented by this @Controller. * <p> - * + * * @return a String indicating the REST API version. */ @Override @@ -81,7 +80,7 @@ public class FunctionAccessController extends AbstractBaseController { /** * list all registered functions in Gemfire data node - * + * * @return result as a JSON document. */ @RequestMapping(method = RequestMethod.GET, produces = {MediaType.APPLICATION_JSON_UTF8_VALUE}) @@ -102,13 +101,13 @@ public class FunctionAccessController extends AbstractBaseController { JSONUtils.formulateJsonForListFunctionsCall(registeredFunctions.keySet()); final HttpHeaders headers = new HttpHeaders(); headers.setLocation(toUri("functions")); - return new ResponseEntity<String>(listFunctionsAsJson, headers, HttpStatus.OK); + return new ResponseEntity<>(listFunctionsAsJson, headers, HttpStatus.OK); } /** * Execute a function on Gemfire data node using REST API call. Arguments to the function are * passed as JSON string in the request body. - * + * * @param functionId represents function to be executed * @param region list of regions on which function to be executed. * @param members list of nodes on which function to be executed. @@ -116,6 +115,7 @@ public class FunctionAccessController extends AbstractBaseController { * @param filter list of keys which the function will use to determine on which node to execute * the function. * @param argsInBody function argument as a JSON document + * * @return result as a JSON document */ @RequestMapping(method = RequestMethod.POST, value = "/{functionId}", @@ -145,7 +145,6 @@ public class FunctionAccessController extends AbstractBaseController { logger.debug("Executing Function ({}) with arguments ({}) on Region ({})...", functionId, ArrayUtils.toString(argsInBody), region); - region = decode(region); try { function = FunctionService.onRegion(getRegion(region)); @@ -236,7 +235,7 @@ public class FunctionAccessController extends AbstractBaseController { @SuppressWarnings("unchecked") String functionResultAsJson = JSONUtils.convertCollectionToJson((ArrayList<Object>) functionResult); - return new ResponseEntity<String>(functionResultAsJson, headers, HttpStatus.OK); + return new ResponseEntity<>(functionResultAsJson, headers, HttpStatus.OK); } catch (JSONException e) { throw new GemfireRestException( "Could not convert function results into Restful (JSON) format!", e); http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/bd229d76/geode-web-api/src/main/java/org/apache/geode/rest/internal/web/controllers/PdxBasedCrudController.java ---------------------------------------------------------------------- diff --git a/geode-web-api/src/main/java/org/apache/geode/rest/internal/web/controllers/PdxBasedCrudController.java b/geode-web-api/src/main/java/org/apache/geode/rest/internal/web/controllers/PdxBasedCrudController.java index 2b44e54..3b08c5f 100644 --- a/geode-web-api/src/main/java/org/apache/geode/rest/internal/web/controllers/PdxBasedCrudController.java +++ b/geode-web-api/src/main/java/org/apache/geode/rest/internal/web/controllers/PdxBasedCrudController.java @@ -113,7 +113,7 @@ public class PdxBasedCrudController extends CommonCrudController { headers.setLocation(toUri(region, key)); if (existingPdxObj != null) { - final RegionEntryData<Object> data = new RegionEntryData<Object>(region); + final RegionEntryData<Object> data = new RegionEntryData<>(region); data.add(existingPdxObj); headers.setContentType(MediaType.APPLICATION_JSON); return new ResponseEntity<RegionEntryData<?>>(data, headers, HttpStatus.CONFLICT); @@ -149,13 +149,13 @@ public class PdxBasedCrudController extends CommonCrudController { region = decode(region); Map<Object, Object> valueObjs = null; - final RegionData<Object> data = new RegionData<Object>(region); + final RegionData<Object> data = new RegionData<>(region); final HttpHeaders headers = new HttpHeaders(); String keyList = null; int regionSize = getRegion(region).size(); - List<Object> keys = new ArrayList<Object>(regionSize); - List<Object> values = new ArrayList<Object>(regionSize); + List<Object> keys = new ArrayList<>(regionSize); + List<Object> values = new ArrayList<>(regionSize); for (Map.Entry<Object, Object> entry : getValues(region).entrySet()) { Object value = entry.getValue(); @@ -174,8 +174,7 @@ public class PdxBasedCrudController extends CommonCrudController { if (maxLimit < 0) { String errorMessage = String.format("Negative limit param (%1$s) is not valid!", maxLimit); - return new ResponseEntity<String>(convertErrorAsJson(errorMessage), - HttpStatus.BAD_REQUEST); + return new ResponseEntity<>(convertErrorAsJson(errorMessage), HttpStatus.BAD_REQUEST); } int mapSize = keys.size(); @@ -190,7 +189,7 @@ public class PdxBasedCrudController extends CommonCrudController { // limit param is not specified in proper format. set the HTTPHeader // for BAD_REQUEST String errorMessage = String.format("limit param (%1$s) is not valid!", limit); - return new ResponseEntity<String>(convertErrorAsJson(errorMessage), HttpStatus.BAD_REQUEST); + return new ResponseEntity<>(convertErrorAsJson(errorMessage), HttpStatus.BAD_REQUEST); } } @@ -233,7 +232,7 @@ public class PdxBasedCrudController extends CommonCrudController { .format("Key (%1$s) does not exist for region (%2$s) in cache!", keys[0], region)); } - final RegionEntryData<Object> data = new RegionEntryData<Object>(region); + final RegionEntryData<Object> data = new RegionEntryData<>(region); headers.set("Content-Location", toUri(region, keys[0]).toASCIIString()); data.add(value); return new ResponseEntity<RegionData<?>>(data, headers, HttpStatus.OK); @@ -245,7 +244,7 @@ public class PdxBasedCrudController extends CommonCrudController { String errorMessage = String.format( "ignoreMissingKey param (%1$s) is not valid. valid usage is ignoreMissingKey=true!", ignoreMissingKey); - return new ResponseEntity<String>(convertErrorAsJson(errorMessage), HttpStatus.BAD_REQUEST); + return new ResponseEntity<>(convertErrorAsJson(errorMessage), HttpStatus.BAD_REQUEST); } if (!("true".equalsIgnoreCase(ignoreMissingKey))) { @@ -254,7 +253,7 @@ public class PdxBasedCrudController extends CommonCrudController { String unknownKeysAsStr = StringUtils.collectionToDelimitedString(unknownKeys, ","); String erroString = String.format("Requested keys (%1$s) not exist in region (%2$s)", StringUtils.collectionToDelimitedString(unknownKeys, ","), region); - return new ResponseEntity<String>(convertErrorAsJson(erroString), headers, + return new ResponseEntity<>(convertErrorAsJson(erroString), headers, HttpStatus.BAD_REQUEST); } } @@ -268,7 +267,7 @@ public class PdxBasedCrudController extends CommonCrudController { // currently we are not removing keys having value null from the result. String keyList = StringUtils.collectionToDelimitedString(valueObjs.keySet(), ","); headers.set("Content-Location", toUri(region, keyList).toASCIIString()); - final RegionData<Object> data = new RegionData<Object>(region); + final RegionData<Object> data = new RegionData<>(region); data.add(valueObjs.values()); return new ResponseEntity<RegionData<?>>(data, headers, HttpStatus.OK); } http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/bd229d76/geode-web-api/src/main/java/org/apache/geode/rest/internal/web/controllers/QueryAccessController.java ---------------------------------------------------------------------- diff --git a/geode-web-api/src/main/java/org/apache/geode/rest/internal/web/controllers/QueryAccessController.java b/geode-web-api/src/main/java/org/apache/geode/rest/internal/web/controllers/QueryAccessController.java index 4a7dfde..b00a7aa 100644 --- a/geode-web-api/src/main/java/org/apache/geode/rest/internal/web/controllers/QueryAccessController.java +++ b/geode-web-api/src/main/java/org/apache/geode/rest/internal/web/controllers/QueryAccessController.java @@ -71,8 +71,7 @@ public class QueryAccessController extends AbstractBaseController { protected static final String PARAMETERIZED_QUERIES_REGION = "__ParameterizedQueries__"; - private final ConcurrentHashMap<String, DefaultQuery> compiledQueries = - new ConcurrentHashMap<String, DefaultQuery>(); + private final ConcurrentHashMap<String, DefaultQuery> compiledQueries = new ConcurrentHashMap<>(); // Constant String value indicating the version of the REST API. protected static final String REST_API_VERSION = "/v1"; @@ -112,7 +111,7 @@ public class QueryAccessController extends AbstractBaseController { String queryListAsJson = JSONUtils.formulateJsonForListQueriesCall(parametrizedQueryRegion); final HttpHeaders headers = new HttpHeaders(); headers.setLocation(toUri("queries")); - return new ResponseEntity<String>(queryListAsJson, headers, HttpStatus.OK); + return new ResponseEntity<>(queryListAsJson, headers, HttpStatus.OK); } /** @@ -142,7 +141,7 @@ public class QueryAccessController extends AbstractBaseController { // store the compiled OQL statement with 'queryId' as the Key into the hidden, - // ParameterizedQueries Region... + // Parametrized Queries Region... final String existingOql = createNamedQuery(PARAMETERIZED_QUERIES_REGION, queryId, oqlStatement); @@ -151,9 +150,8 @@ public class QueryAccessController extends AbstractBaseController { if (existingOql != null) { headers.setContentType(MediaType.APPLICATION_JSON); - return new ResponseEntity<String>( - JSONUtils.formulateJsonForExistingQuery(queryId, existingOql), headers, - HttpStatus.CONFLICT); + return new ResponseEntity<>(JSONUtils.formulateJsonForExistingQuery(queryId, existingOql), + headers, HttpStatus.CONFLICT); } else { return new ResponseEntity<String>(headers, HttpStatus.CREATED); } @@ -188,7 +186,7 @@ public class QueryAccessController extends AbstractBaseController { // and handle the Exceptions appropriately (500 Server Error)! try { Object queryResult = query.execute(); - return processQueryResponse(queryResult, "adhoc?q=" + oql); + return processQueryResponse(query, null, queryResult); } catch (FunctionDomainException fde) { throw new GemfireRestException( "A function was applied to a parameter that is improper for that function!", fde); @@ -253,7 +251,7 @@ public class QueryAccessController extends AbstractBaseController { Query compiledQuery = compiledQueries.get(queryId); if (compiledQuery == null) { // This is first time the query is seen by this server. - final String oql = getValue(PARAMETERIZED_QUERIES_REGION, queryId); + final String oql = getValue(PARAMETERIZED_QUERIES_REGION, queryId, false); ValidationUtils.returnValueThrowOnNull(oql, new ResourceNotFoundException( String.format("No Query with ID (%1$s) was found!", queryId))); @@ -269,7 +267,7 @@ public class QueryAccessController extends AbstractBaseController { // and handle the Exceptions appropriately (500 Server Error)! try { Object queryResult = compiledQuery.execute(args); - return processQueryResponse(queryResult, queryId); + return processQueryResponse(compiledQuery, args, queryResult); } catch (FunctionDomainException fde) { throw new GemfireRestException( "A function was applied to a parameter that is improper for that function!", fde); @@ -327,13 +325,13 @@ public class QueryAccessController extends AbstractBaseController { queryId); - // update the OQL statement with 'queryId' as the Key into the hidden, ParameterizedQueries + // update the OQL statement with 'queryId' as the Key into the hidden, Parametrized Queries // Region... checkForQueryIdExist(PARAMETERIZED_QUERIES_REGION, queryId); updateNamedQuery(PARAMETERIZED_QUERIES_REGION, queryId, oqlStatement); compiledQueries.remove(queryId); - return new ResponseEntity<Object>(HttpStatus.OK); + return new ResponseEntity<>(HttpStatus.OK); } // delete named, parametrized query @@ -358,7 +356,7 @@ public class QueryAccessController extends AbstractBaseController { // ParameterizedQueries Region... deleteNamedQuery(PARAMETERIZED_QUERIES_REGION, queryId); compiledQueries.remove(queryId); - return new ResponseEntity<Object>(HttpStatus.OK); + return new ResponseEntity<>(HttpStatus.OK); } } http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/bd229d76/geode-web-api/src/main/java/org/apache/geode/rest/internal/web/security/RestSecurityService.java ---------------------------------------------------------------------- diff --git a/geode-web-api/src/main/java/org/apache/geode/rest/internal/web/security/RestSecurityService.java b/geode-web-api/src/main/java/org/apache/geode/rest/internal/web/security/RestSecurityService.java index 9004936..80ff719 100644 --- a/geode-web-api/src/main/java/org/apache/geode/rest/internal/web/security/RestSecurityService.java +++ b/geode-web-api/src/main/java/org/apache/geode/rest/internal/web/security/RestSecurityService.java @@ -15,10 +15,9 @@ package org.apache.geode.rest.internal.web.security; -import org.springframework.stereotype.Component; - import org.apache.geode.internal.security.SecurityService; import org.apache.geode.security.GemFireSecurityException; +import org.springframework.stereotype.Component; @Component("securityService") public class RestSecurityService { @@ -50,4 +49,9 @@ public class RestSecurityService { } return true; } + + public Object postProcess(String regionPath, Object key, Object value, + boolean valueIsSerialized) { + return securityService.postProcess(regionPath, key, value, valueIsSerialized); + } } http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/bd229d76/geode-web-api/src/main/java/org/apache/geode/rest/internal/web/util/JsonWriter.java ---------------------------------------------------------------------- diff --git a/geode-web-api/src/main/java/org/apache/geode/rest/internal/web/util/JsonWriter.java b/geode-web-api/src/main/java/org/apache/geode/rest/internal/web/util/JsonWriter.java index cc6a424..68a9c3e 100644 --- a/geode-web-api/src/main/java/org/apache/geode/rest/internal/web/util/JsonWriter.java +++ b/geode-web-api/src/main/java/org/apache/geode/rest/internal/web/util/JsonWriter.java @@ -15,37 +15,34 @@ package org.apache.geode.rest.internal.web.util; +import com.fasterxml.jackson.core.JsonGenerationException; +import com.fasterxml.jackson.core.JsonGenerator; +import org.apache.geode.cache.Region; +import org.apache.geode.cache.query.Struct; +import org.apache.geode.cache.query.internal.StructImpl; +import org.apache.geode.pdx.PdxInstance; +import org.apache.geode.pdx.internal.EnumInfo; +import org.apache.geode.pdx.internal.EnumInfo.PdxInstanceEnumInfo; +import org.springframework.hateoas.Link; +import org.springframework.http.HttpHeaders; +import org.springframework.http.MediaType; +import org.springframework.util.CollectionUtils; + import java.io.IOException; import java.math.BigDecimal; import java.math.BigInteger; import java.nio.charset.Charset; import java.util.ArrayList; import java.util.Collection; -import java.util.Date; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; -import org.springframework.hateoas.Link; -import org.springframework.http.HttpHeaders; -import org.springframework.http.MediaType; -import org.springframework.util.CollectionUtils; - -import com.fasterxml.jackson.core.JsonGenerationException; -import com.fasterxml.jackson.core.JsonGenerator; -import org.apache.geode.cache.Region; -import org.apache.geode.cache.query.Struct; -import org.apache.geode.cache.query.internal.StructImpl; -import org.apache.geode.pdx.PdxInstance; -import org.apache.geode.pdx.internal.EnumInfo; -import org.apache.geode.pdx.internal.EnumInfo.PdxInstanceEnumInfo; -import org.apache.geode.rest.internal.web.exception.GemfireRestException; - /** * The JsonWriter class is an utility to write various java types as a JSON string. * <p/> - * + * * @since GemFire 8.0 */ public class JsonWriter { @@ -490,8 +487,8 @@ public class JsonWriter { writeArrayAsJson(generator, value, pdxField); } else if (value.getClass().equals(Link.class)) { writeLinkAsJson(generator, (Link) value, pdxField); - } else if (value.getClass().equals(Date.class)) { - generator.writeObject((Date) value); + // } else if (value.getClass().equals(Date.class)) { + // generator.writeObject((Date) value); } else if (value.getClass().equals(EnumInfo.class)) { /* * try { generator.writeString(((EnumInfo)value).getEnum().name()); } catch @@ -512,21 +509,7 @@ public class JsonWriter { } else if (value instanceof Map) { writeMapAsJson(generator, (Map) value, pdxField); } else { - // TODO:: can value be a domain object...? As we have configured PdxInstance based storage, - // Throw GemfireRestException for value of type domain objects. - - // TODO:Do we need to convert domain objects into the JSON using ObjectMapper. There is no - // gurantee that domain class is in classpath. - /* - * ObjectMapper mapper = new ObjectMapper(); mapper.setDateFormat(new - * SimpleDateFormat("MM/dd/yyyy")); - * mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); - * mapper.configure(com.fasterxml.jackson.core.JsonParser.Feature. - * ALLOW_UNQUOTED_FIELD_NAMES, true); mapper.writeValueAsString(value) - * - * Object classInstance = mapper.readValue(JSON, Class.forName(className)); - */ - throw new GemfireRestException("Requested data could not convert into REST format[JSON] "); + generator.writeObject(value); } } }