geode-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From jensde...@apache.org
Subject [23/50] [abbrv] incubator-geode git commit: Merge branch 'develop' into feature/GEODE-17
Date Thu, 25 Feb 2016 20:27:11 GMT
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/5c01d5f4/geode-web-api/src/main/java/com/gemstone/gemfire/rest/internal/web/controllers/PdxBasedCrudController.java
----------------------------------------------------------------------
diff --cc geode-web-api/src/main/java/com/gemstone/gemfire/rest/internal/web/controllers/PdxBasedCrudController.java
index 0000000,99e50d6..726d127
mode 000000,100644..100644
--- a/geode-web-api/src/main/java/com/gemstone/gemfire/rest/internal/web/controllers/PdxBasedCrudController.java
+++ b/geode-web-api/src/main/java/com/gemstone/gemfire/rest/internal/web/controllers/PdxBasedCrudController.java
@@@ -1,0 -1,354 +1,444 @@@
+ /*
+  * Licensed to the Apache Software Foundation (ASF) under one or more
+  * contributor license agreements.  See the NOTICE file distributed with
+  * this work for additional information regarding copyright ownership.
+  * The ASF licenses this file to You under the Apache License, Version 2.0
+  * (the "License"); you may not use this file except in compliance with
+  * the License.  You may obtain a copy of the License at
+  *
+  *      http://www.apache.org/licenses/LICENSE-2.0
+  *
+  * Unless required by applicable law or agreed to in writing, software
+  * distributed under the License is distributed on an "AS IS" BASIS,
+  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  * See the License for the specific language governing permissions and
+  * limitations under the License.
+  */
+ package com.gemstone.gemfire.rest.internal.web.controllers;
+ 
+ import java.util.ArrayList;
+ import java.util.List;
+ import java.util.Map;
++import java.util.Set;
+ 
+ import org.apache.logging.log4j.Logger;
+ import org.springframework.http.HttpHeaders;
+ import org.springframework.http.HttpStatus;
+ import org.springframework.http.MediaType;
+ import org.springframework.http.ResponseEntity;
+ import org.springframework.stereotype.Controller;
+ import org.springframework.util.StringUtils;
+ import org.springframework.web.bind.annotation.PathVariable;
+ import org.springframework.web.bind.annotation.RequestBody;
+ import org.springframework.web.bind.annotation.RequestMapping;
+ import org.springframework.web.bind.annotation.RequestMethod;
+ import org.springframework.web.bind.annotation.RequestParam;
+ 
++import com.gemstone.gemfire.cache.operations.PutOperationContext;
+ import com.gemstone.gemfire.internal.logging.LogService;
++import com.gemstone.gemfire.internal.security.AuthorizeRequest;
+ import com.gemstone.gemfire.internal.util.ArrayUtils;
+ import com.gemstone.gemfire.rest.internal.web.controllers.support.JSONTypes;
+ import com.gemstone.gemfire.rest.internal.web.controllers.support.RegionData;
+ import com.gemstone.gemfire.rest.internal.web.controllers.support.RegionEntryData;
+ import com.gemstone.gemfire.rest.internal.web.exception.ResourceNotFoundException;
++import com.gemstone.gemfire.rest.internal.web.security.AuthorizationProvider;
++import com.gemstone.gemfire.rest.internal.web.security.RestRequestFilter;
++import com.gemstone.gemfire.security.NotAuthorizedException;
+ import com.wordnik.swagger.annotations.Api;
+ import com.wordnik.swagger.annotations.ApiOperation;
+ import com.wordnik.swagger.annotations.ApiResponse;
+ import com.wordnik.swagger.annotations.ApiResponses;
+ 
+ /**
+  * The PdxBasedCrudController class serving REST Requests related to the REST CRUD operation
on region
+  * <p/>
+  * @author Nilkanth Patel, john blum
+  * @see org.springframework.stereotype.Controller
+  * @since 8.0
+  */
+ 
+ @Controller("pdxCrudController")
+ @Api(value = "region",
+      description = "region CRUD operations")
+ @RequestMapping(PdxBasedCrudController.REST_API_VERSION)
+ @SuppressWarnings("unused")
+ public class PdxBasedCrudController extends CommonCrudController {
+ 
+   private static final Logger logger = LogService.getLogger();
+   
+   protected static final String REST_API_VERSION = "/v1";
+   
+   protected static final String DEFAULT_GETALL_RESULT_LIMIT = "50";  
+   
+   @Override
+   protected String getRestApiVersion() {
+     return REST_API_VERSION;
+   }
+ 
+   /**
+    * Creating entry into the region
+    * @param region region name where data will be created
+    * @param key gemfire region key
+    * @param json JSON document that is stored against the key
+    * @return JSON document
+    */
+   
+   @RequestMapping(method = RequestMethod.POST, value = "/{region}",
+                   consumes = MediaType.APPLICATION_JSON_VALUE,
+                   produces = { MediaType.APPLICATION_JSON_VALUE })
+   @ApiOperation(
+     value = "create entry",
+     notes = "Create (put-if-absent) data in region",
+     response  = void.class
+   )
+   @ApiResponses( {
+     @ApiResponse( code = 201, message = "Created."),
+     @ApiResponse( code = 400, message = "Data specified (JSON doc) in the request body is
invalid." ),
+     @ApiResponse( code = 404, message = "Region does not exist." ),
+     @ApiResponse( code = 409, message = "Key already exist in region."),
+     @ApiResponse( code = 500, message = "GemFire throws an error or exception.")   
+   } )
+   public ResponseEntity<?> create(@PathVariable("region") String region,
+       @RequestParam(value = "key", required = false) String key,
+       @RequestBody final String json) {
+     
+     key = generateKey(key);
+     
+     if(logger.isDebugEnabled()){
+       logger.debug("Posting (creating/putIfAbsent) JSON document ({}) to Region ({}) with
Key ({})...",
+           json, region, key);
+     }
+     region = decode(region);
 -    Object existingPdxObj = null;
+     
++    final HttpHeaders headers = new HttpHeaders();
++    headers.setLocation(toUri(region, key));
++    
++    //Do request (Pre) authorization if security is enabled.
++    if(AuthorizationProvider.isSecurityEnabled()){
++      setAuthTokenHeader(headers);
++      AuthorizationProvider.init();
++      try{
++        //TODO: add isJson type in OperationContext
++        AuthorizationProvider.putAuthorize(region, key, json, true/*isJson*/, null, PutOperationContext.CREATE);
++      }catch(NotAuthorizedException nae) {
++        return new ResponseEntity<String>(headers, HttpStatus.UNAUTHORIZED);
++      }
++    }
++    
++    Object existingPdxObj = null;
+     //Check whether the user has supplied single JSON doc or Array of JSON docs  
+     final JSONTypes jsonType = validateJsonAndFindType(json);
+     if(JSONTypes.JSON_ARRAY.equals(jsonType)){
+       existingPdxObj = postValue(region, key, convertJsonArrayIntoPdxCollection(json));
+     }else {
+       existingPdxObj = postValue(region, key, convert(json));  
+     }
+     
 -    final HttpHeaders headers = new HttpHeaders();
 -    headers.setLocation(toUri(region, key));
 -    
+     if (existingPdxObj != null) {
+       final RegionEntryData<Object> data = new RegionEntryData<Object>(region);
+       data.add(existingPdxObj);
+       headers.setContentType(MediaType.APPLICATION_JSON);
+       return new ResponseEntity<RegionEntryData<?>>(data, headers, HttpStatus.CONFLICT);
+     } else {
+       return new ResponseEntity<String>(headers, HttpStatus.CREATED);
+     }
+   }
+   
+   /**
+    * Read all or fixed number of data in a given Region
+    * @param region gemfire region name
+    * @param limit total number of entries requested
+    * @return JSON document
+    */
+   @RequestMapping(method = RequestMethod.GET, value = "/{region}", produces = MediaType.APPLICATION_JSON_VALUE)
+   @ApiOperation(
+     value = "read all data for region",
+     notes = "Read all data for region. Use limit param to get fixed or limited number of
entries.",
+     response  = void.class
+   )
+   @ApiResponses( {
+     @ApiResponse( code = 200, message = "OK."),
+     @ApiResponse( code = 400, message = "Bad request." ),
+     @ApiResponse( code = 404, message = "Region does not exist." ),
+     @ApiResponse( code = 500, message = "GemFire throws an error or exception.")    
+   } )
+   public ResponseEntity<?> read(@PathVariable("region") String region,
+       @RequestParam(value = "limit", defaultValue = DEFAULT_GETALL_RESULT_LIMIT) final String
limit) {
+     
+     if(logger.isDebugEnabled()){
+       logger.debug("Reading all data in Region ({})...", region);
+     }
+     region = decode(region);
+       
++    final HttpHeaders headers = new HttpHeaders();
++   
++    //Do request(Pre) authorization if security is enabled.
++    if(AuthorizationProvider.isSecurityEnabled()){
++      setAuthTokenHeader(headers);
++      AuthorizationProvider.init();
++      try{
++        AuthorizationProvider.getAllAuthorize(region, getRegion(region).keySet(), null);
++      }catch(NotAuthorizedException nae) {
++        return new ResponseEntity<String>(headers, HttpStatus.UNAUTHORIZED);
++      }
++    }
++    
+     Map<Object, Object> valueObjs = null;
+     final RegionData<Object> data = new RegionData<Object>(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);
+     
+     for (Map.Entry<Object, Object> entry : getValues(region).entrySet() ) {
++      //Do post authorization if security is enabled.
++      if(AuthorizationProvider.isSecurityEnabled()){
++        try{
++          AuthorizationProvider.getAuthorizePP(region, entry.getKey(), entry.getValue());
++        }catch(NotAuthorizedException nae) {
++          //Sending UNAUTHORIZED response, if any one of the key has UNAUTHORIZED access
configured.
++          return new ResponseEntity<String>(headers, HttpStatus.UNAUTHORIZED);
++        }
++      }
++      
+       Object value = entry.getValue();
+       if (value != null) {
+         keys.add(entry.getKey());
+         values.add(value);
+       }
+     }
+     
+     if ("ALL".equalsIgnoreCase(limit) ) {  
+       data.add(values);
+       keyList = StringUtils.collectionToDelimitedString(keys, ",");
+     } else {
+       try {
+         int maxLimit = Integer.valueOf(limit);
+         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);
++              convertErrorAsJson(errorMessage), headers, HttpStatus.BAD_REQUEST);
+         }
+         
+         int mapSize = keys.size();
+         if (maxLimit > mapSize) {
+           maxLimit = mapSize;
+         }
+         data.add(values.subList(0, maxLimit));
+ 
+         keyList = StringUtils.collectionToDelimitedString(
+             keys.subList(0, maxLimit), ",");
+ 
+       } catch (NumberFormatException e) {
+         // 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);
++            convertErrorAsJson(errorMessage), headers, HttpStatus.BAD_REQUEST);
+       }  
+     } 
+     
+     headers.set("Content-Location", toUri(region, keyList).toASCIIString() );
+     return new ResponseEntity<RegionData<?>>(data, headers, HttpStatus.OK);
+   }
+   
+   /**
+    * Reading data for set of keys
+    * @param region gemfire region name
+    * @param keys string containing comma seperated keys 
+    * @return JSON document
+    */
+   @RequestMapping(method = RequestMethod.GET, value = "/{region}/{keys}",
+                   produces = MediaType.APPLICATION_JSON_VALUE)
+   @ApiOperation(
+     value = "read data for specific keys",
+     notes = "Read data for specific set of keys in region.",
+     response  = void.class
+   )
+   @ApiResponses( {
+     @ApiResponse( code = 200, message = "OK."),
+     @ApiResponse( code = 400, message = "Bad Request."),
+     @ApiResponse( code = 404, message = "Region does not exist." ),
+     @ApiResponse( code = 500, message = "GemFire throws an error or exception.")  
+   } )
+   public ResponseEntity<?> read(
+       @PathVariable("region") String region,
+       @PathVariable("keys") final String[] keys,
+       @RequestParam(value = "ignoreMissingKey", required = false ) final String ignoreMissingKey)
{
+     
+     if(logger.isDebugEnabled()){
+       logger.debug("Reading data for keys ({}) in Region ({})",
+           ArrayUtils.toString(keys), region);
+     }
+     
+     final HttpHeaders headers = new HttpHeaders();
+     region = decode(region);
+     
++    //Do request(Pre) authorization if security is enabled.
++    if(AuthorizationProvider.isSecurityEnabled()){
++      setAuthTokenHeader(headers);
++      AuthorizationProvider.init();
++      try{
++        AuthorizationProvider.getAuthorize(region, keys, null);
++      } catch(NotAuthorizedException nae) {
++        return new ResponseEntity<String>(headers, HttpStatus.UNAUTHORIZED);
++      }
++    }
++    
+     if (keys.length == 1) { 
+       /* GET op on single key */
+       Object value = getValue(region, keys[0]);
+       //if region.get(K) return null (i.e INVLD or TOMBSTONE case) We consider 404, NOT
Found case  
+       if(value == null) {
+         throw new ResourceNotFoundException(String.format("Key (%1$s) does not exist for
region (%2$s) in cache!", keys[0], region));
+       }
+       
++      //Do post authorization if security is enabled.
++      if(AuthorizationProvider.isSecurityEnabled()){
++        try{
++          AuthorizationProvider.getAuthorizePP(region, keys[0], value);
++        }catch(NotAuthorizedException nae) {
++          return new ResponseEntity<String>(headers, HttpStatus.UNAUTHORIZED);
++        }
++      }
++      
+       final RegionEntryData<Object> data = new RegionEntryData<Object>(region);
+       headers.set("Content-Location", toUri(region, keys[0]).toASCIIString());
+       data.add(value);
+       return new ResponseEntity<RegionData<?>>(data, headers, HttpStatus.OK);
+ 
+     } else {
+       //fail fast for the case where ignoreMissingKey param is not specified correctly.
+       if (ignoreMissingKey != null 
+           && !(ignoreMissingKey.equalsIgnoreCase("true") || ignoreMissingKey.equalsIgnoreCase("false"))){
+         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);
++            convertErrorAsJson(errorMessage), headers, HttpStatus.BAD_REQUEST);
+       }
+       
+       if(!("true".equalsIgnoreCase(ignoreMissingKey))) { 
+         List<String> unknownKeys = checkForMultipleKeysExist(region, keys);
+         if(unknownKeys.size() > 0) {
+           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,
HttpStatus.BAD_REQUEST);
+         }
+       }  
+       
+       final Map<Object, Object> valueObjs = getValues(region, keys);
 -
++      
++      //Do post authorization if security is enabled.
++      if(AuthorizationProvider.isSecurityEnabled()){
++        for (Map.Entry<Object, Object> entry : valueObjs.entrySet() ) {
++          try{
++            AuthorizationProvider.getAuthorizePP(region, entry.getKey(), entry.getValue());
++          }catch(NotAuthorizedException nae) {
++            return new ResponseEntity<String>(headers, HttpStatus.UNAUTHORIZED);
++          }
++        }
++      }
++      
+       // Do we need to remove null values from Map..?
+       // To Remove null value entries from map.
+       // valueObjs.values().removeAll(Collections.singleton(null));
+   
+       //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);
+       data.add(valueObjs.values());
+       return new ResponseEntity<RegionData<?>>(data, headers, HttpStatus.OK);
+     }
+   }
+ 
+   /**
+    * Update data for a key or set of keys
+    * @param region gemfire data region
+    * @param keys keys for which update operation is requested
+    * @param opValue type of update (put, replace, cas etc)
+    * @param json new data for the key(s)
+    * @return JSON document
+    */
+   @RequestMapping(method = RequestMethod.PUT, value = "/{region}/{keys}",
+                   consumes = { MediaType.APPLICATION_JSON_VALUE },
+                   produces = { MediaType.APPLICATION_JSON_VALUE })
+   @ApiOperation(
+     value = "update data for key",
+     notes = "Update or insert (put) data for key in region." +
+             "op=REPLACE, update (replace) data with key if and only if the key exists in
region" +
+             "op=CAS update (compare-and-set) value having key with a new value if and only
if the \"@old\" value sent matches the current value for the key in region",
+     response  = void.class
+   )
+   @ApiResponses( {
+     @ApiResponse( code = 200, message = "OK."),
+     @ApiResponse( code = 400, message = "Bad Request."),
+     @ApiResponse( code = 404, message = "Region does not exist or if key is not mapped to
some value for REPLACE or CAS."),
+     @ApiResponse( code = 409, message = "For CAS, @old value does not match to the current
value in region" ),
+     @ApiResponse( code = 500, message = "GemFire throws an error or exception.")
+   } )
+   public ResponseEntity<?> update(@PathVariable("region") String region,
+       @PathVariable("keys") final String[] keys,
+       @RequestParam(value = "op", defaultValue = "PUT") final String opValue,
+       @RequestBody final String json) {
+     
+     if(logger.isDebugEnabled()){
+       logger.debug("updating key(s) for region ({}) ", region);
+     }
++    
+     region = decode(region);
++    HttpHeaders headers = new HttpHeaders();
++    
++    //Do request(Pre) authorization if security is enabled.
++    if(AuthorizationProvider.isSecurityEnabled()){
++      setAuthTokenHeader(headers);
++      AuthorizationProvider.init();
++      try{
++        //TODO: add isJson type in OperationContext
++        if(keys.length > 1){
++          AuthorizationProvider.putAllAuthorize(region, json, null);
++        }else {
++          //TODO: add isJson type in OperationContext
++          AuthorizationProvider.putAuthorize(region, keys[0], json, false /*isObject*/,
/*isJson,*/ null, PutOperationContext.UPDATE);
++        }
++      }catch(NotAuthorizedException nae) {
++        return new ResponseEntity<String>(headers, HttpStatus.UNAUTHORIZED);
++      }
++    }
+     
+     if(keys.length > 1){
+       //putAll case
 -      return updateMultipleKeys(region, keys, json);
++      return updateMultipleKeys(region, keys, json, headers);
+     } else {
+       //put case
 -      return updateSingleKey(region, keys[0], json, opValue);
++      return updateSingleKey(region, keys[0], json, opValue, headers);
+     }
+   }
+     
+   @RequestMapping(method = RequestMethod.HEAD, value = "/{region}", produces = MediaType.APPLICATION_JSON_VALUE)
+   @ApiOperation(
+     value = "Get total number of entries",
+     notes = "Get total number of entries into the specified region",
+     response  = void.class
+   )
+   @ApiResponses( {
+     @ApiResponse( code = 200, message = "OK."),
+     @ApiResponse( code = 400, message = "Bad request." ),
+     @ApiResponse( code = 404, message = "Region does not exist." ),
+     @ApiResponse( code = 500, message = "GemFire throws an error or exception.")    
+   } )
+   public ResponseEntity<?> size(@PathVariable("region") String region) {
+     
+     if(logger.isDebugEnabled()){
+       logger.debug("Determining the number of entries in Region ({})...", region);
+     }
+     region = decode(region);
 -      
 -    final HttpHeaders headers = new HttpHeaders();
++    //Not Authorized at REST APIs level as even client-server does not provide authz  
+     
++    final HttpHeaders headers = new HttpHeaders();
+     headers.set("Resource-Count", String.valueOf(getRegion(region).size()) );
+     return new ResponseEntity<RegionData<?>>(headers, HttpStatus.OK);
+   }
+   
+ }

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/5c01d5f4/geode-web-api/src/main/java/com/gemstone/gemfire/rest/internal/web/controllers/QueryAccessController.java
----------------------------------------------------------------------
diff --cc geode-web-api/src/main/java/com/gemstone/gemfire/rest/internal/web/controllers/QueryAccessController.java
index 0000000,ef034cb..460ed6c
mode 000000,100644..100644
--- a/geode-web-api/src/main/java/com/gemstone/gemfire/rest/internal/web/controllers/QueryAccessController.java
+++ b/geode-web-api/src/main/java/com/gemstone/gemfire/rest/internal/web/controllers/QueryAccessController.java
@@@ -1,0 -1,354 +1,459 @@@
+ /*
+  * Licensed to the Apache Software Foundation (ASF) under one or more
+  * contributor license agreements.  See the NOTICE file distributed with
+  * this work for additional information regarding copyright ownership.
+  * The ASF licenses this file to You under the Apache License, Version 2.0
+  * (the "License"); you may not use this file except in compliance with
+  * the License.  You may obtain a copy of the License at
+  *
+  *      http://www.apache.org/licenses/LICENSE-2.0
+  *
+  * Unless required by applicable law or agreed to in writing, software
+  * distributed under the License is distributed on an "AS IS" BASIS,
+  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  * See the License for the specific language governing permissions and
+  * limitations under the License.
+  */
+ 
+ package com.gemstone.gemfire.rest.internal.web.controllers;
+ 
++import java.util.Set;
+ import java.util.concurrent.ConcurrentHashMap;
+ 
+ import org.apache.logging.log4j.Logger;
+ import org.springframework.http.HttpHeaders;
+ import org.springframework.http.HttpStatus;
+ import org.springframework.http.MediaType;
+ import org.springframework.http.ResponseEntity;
+ import org.springframework.stereotype.Controller;
+ import org.springframework.web.bind.annotation.PathVariable;
+ import org.springframework.web.bind.annotation.RequestBody;
+ import org.springframework.web.bind.annotation.RequestMapping;
+ import org.springframework.web.bind.annotation.RequestMethod;
+ import org.springframework.web.bind.annotation.RequestParam;
+ import org.springframework.web.bind.annotation.ResponseBody;
+ import org.springframework.web.bind.annotation.ResponseStatus;
+ 
+ import com.gemstone.gemfire.cache.Region;
++import com.gemstone.gemfire.cache.operations.OperationContext;
++import com.gemstone.gemfire.cache.operations.OperationContext.OperationCode;
++import com.gemstone.gemfire.cache.operations.PutOperationContext;
++import com.gemstone.gemfire.cache.operations.QueryOperationContext;
+ import com.gemstone.gemfire.cache.query.FunctionDomainException;
+ import com.gemstone.gemfire.cache.query.NameResolutionException;
+ import com.gemstone.gemfire.cache.query.Query;
+ import com.gemstone.gemfire.cache.query.QueryExecutionLowMemoryException;
+ import com.gemstone.gemfire.cache.query.QueryExecutionTimeoutException;
+ import com.gemstone.gemfire.cache.query.QueryInvalidException;
+ import com.gemstone.gemfire.cache.query.QueryInvocationTargetException;
+ import com.gemstone.gemfire.cache.query.TypeMismatchException;
+ import com.gemstone.gemfire.cache.query.internal.DefaultQuery;
+ import com.gemstone.gemfire.internal.logging.LogService;
+ import com.gemstone.gemfire.rest.internal.web.exception.GemfireRestException;
+ import com.gemstone.gemfire.rest.internal.web.exception.ResourceNotFoundException;
++import com.gemstone.gemfire.rest.internal.web.security.AuthorizationProvider;
+ import com.gemstone.gemfire.rest.internal.web.util.JSONUtils;
+ import com.gemstone.gemfire.rest.internal.web.util.ValidationUtils;
++import com.gemstone.gemfire.security.NotAuthorizedException;
+ import com.wordnik.swagger.annotations.Api;
+ import com.wordnik.swagger.annotations.ApiOperation;
+ import com.wordnik.swagger.annotations.ApiResponse;
+ import com.wordnik.swagger.annotations.ApiResponses;
+ 
+ /**
+  * The QueryingController class serves all HTTP REST requests related to the gemfire querying
+  * <p/>
+  * @author Nilkanth Patel, john blum
+  * @see org.springframework.stereotype.Controller
+  * @since 8.0
+  */
+ 
+ @Controller("queryController")
+ @Api(value = "queries", description = "Rest api for gemfire query execution", produces =
MediaType.APPLICATION_JSON_VALUE)
+ @RequestMapping(QueryAccessController.REST_API_VERSION + "/queries")
+ @SuppressWarnings("unused")
+ public class QueryAccessController extends AbstractBaseController {
+ 
+   private static final Logger logger = LogService.getLogger();
+   
+   protected static final String PARAMETERIZED_QUERIES_REGION = "__ParameterizedQueries__";
+   
+   private final ConcurrentHashMap<String, DefaultQuery> compiledQueries = new ConcurrentHashMap<String,
DefaultQuery>();
+   
+   // Constant String value indicating the version of the REST API.
+   protected static final String REST_API_VERSION = "/v1";
+ 
+   /**
+    * Gets the version of the REST API implemented by this @Controller.
+    * <p/>
+    * @return a String indicating the REST API version.
+    */
+   @Override
+   protected String getRestApiVersion() {
+     return REST_API_VERSION;
+   }
+   
+   /**
+    * list all parameterized Queries created in a Gemfire data node
+    * @return result as a JSON document.
+    */
+   @RequestMapping(method = RequestMethod.GET,  produces = { MediaType.APPLICATION_JSON_VALUE
})
+   @ApiOperation(
+     value = "list all parameterized queries",
+     notes = "List all parameterized queries by id/name",
+     response  = void.class
+   )
+   @ApiResponses( {
+     @ApiResponse( code = 200, message = "OK." ),  
+     @ApiResponse( code = 500, message = "if GemFire throws an error or exception" )   
+   } )
+   @ResponseBody
+   @ResponseStatus(HttpStatus.OK)
+   public ResponseEntity<?> list() {
+  
+     if (logger.isDebugEnabled()) {
+       logger.debug("Listing all parameterized Queries in GemFire...");
+     }
++  
++    final HttpHeaders headers = new HttpHeaders();  
++    headers.setLocation(toUri("queries"));
+     
 -    final Region<String, String> parameterizedQueryRegion = getQueryStore(PARAMETERIZED_QUERIES_REGION);
++    //Do request(Pre) authorization if security is enabled.
++    if(AuthorizationProvider.isSecurityEnabled()){
++      setAuthTokenHeader(headers);
++      AuthorizationProvider.init();
++      try{
++        AuthorizationProvider.listQueriesAuthorize(OperationCode.LIST, true, "LIST_QUERIES");
++      }catch(NotAuthorizedException nae) {
++        return new ResponseEntity<String>(headers, HttpStatus.UNAUTHORIZED);
++      }
++    }
+     
++    final Region<String, String> parameterizedQueryRegion = getQueryStore(PARAMETERIZED_QUERIES_REGION);
   
+     String queryListAsJson =  JSONUtils.formulateJsonForListQueriesCall(parameterizedQueryRegion);
 -    final HttpHeaders headers = new HttpHeaders();  
 -    headers.setLocation(toUri("queries"));
++
+     return new ResponseEntity<String>(queryListAsJson, headers, HttpStatus.OK);
+   } 
+   
+   /**
+    * Create a named, parameterized Query
+    * @param queryId uniquely identify the query
+    * @param oqlInUrl OQL query string specified in a request URL
+    * @param oqlInBody OQL query string specified in a request body
+    * @return result as a JSON document.
+    */
+   @RequestMapping(method = RequestMethod.POST)
+   @ApiOperation(
+     value = "create a parameterized Query",
+     notes = "Prepare the specified parameterized query and assign the corresponding ID for
lookup",
+     response  = void.class
+   )
+   @ApiResponses( {
+     @ApiResponse( code = 201, message = "Successfully created." ),
+     @ApiResponse( code = 409, message = "QueryId already assigned to other query." ),  
+     @ApiResponse( code = 500, message = "GemFire throws an error or exception." )
+   } )
+   public ResponseEntity<?> create(@RequestParam("id") final String queryId,
+                                   @RequestParam(value = "q", required = false) String oqlInUrl,
+                                   @RequestBody(required = false) final String oqlInBody)
+   {
+     final String oqlStatement = validateQuery(oqlInUrl, oqlInBody);
+     
+     if (logger.isDebugEnabled()) {
+       logger.debug("Creating a named, parameterized Query ({}) with ID ({})...", oqlStatement,
queryId);
+     }
 -
 -    // store the compiled OQL statement with 'queryId' as the Key into the hidden, ParameterizedQueries
Region...
 -    final String existingOql = createNamedQuery(PARAMETERIZED_QUERIES_REGION, queryId, oqlStatement);
 -
++    
+     final HttpHeaders headers = new HttpHeaders();
+     headers.setLocation(toUri("queries", queryId));
 -
++    
++    
++    //Do request(Pre) authorization if security is enabled.
++    if(AuthorizationProvider.isSecurityEnabled()){
++      setAuthTokenHeader(headers);
++      AuthorizationProvider.init();
++      try{
++        AuthorizationProvider.createQueryAuthorize(OperationCode.CREATE_QUERY, true, "CREATE_QUERY",
queryId, oqlStatement);
++      }catch(NotAuthorizedException nae) {
++        return new ResponseEntity<String>(headers, HttpStatus.UNAUTHORIZED);
++      }
++    }
++    
++    // store the compiled OQL statement with 'queryId' as the Key into the hidden, ParameterizedQueries
Region...
++    final String existingOql = createNamedQuery(PARAMETERIZED_QUERIES_REGION, queryId, oqlStatement);
++    
+     if (existingOql != null) {
+       headers.setContentType(MediaType.APPLICATION_JSON);
+       return new ResponseEntity<String>(JSONUtils.formulateJsonForExistingQuery(queryId,
existingOql), headers, HttpStatus.CONFLICT);
+     } else {
+       return new ResponseEntity<String>(headers, HttpStatus.CREATED);
+     }
+   }
+ 
+   /**
+    * Run an adhoc Query specified in a query string
+    * @param oql OQL query string to be executed
+    * @return query result as a JSON document
+    */
+   @RequestMapping(method = RequestMethod.GET, value = "/adhoc", produces = { MediaType.APPLICATION_JSON_VALUE
})
+   @ApiOperation(
+     value = "run an adhoc query",
+     notes = "Run an unnamed (unidentified), ad-hoc query passed as a URL parameter",
+     response  = void.class
+   )
+   @ApiResponses( {
+     @ApiResponse( code = 200, message = "OK." ),
+     @ApiResponse( code = 500, message = "GemFire throws an error or exception" )   
+   } )
+   @ResponseBody
+   @ResponseStatus(HttpStatus.OK)
+   public ResponseEntity<String> runAdhocQuery(@RequestParam("q") String oql) {
+     
+     if (logger.isDebugEnabled()) {
+       logger.debug("Running an adhoc Query ({})...", oql);
+     }
++    
++    HttpHeaders headers = new HttpHeaders();
+     oql = decode(oql);
+     final Query query = getQueryService().newQuery(oql);
+     
++    Set regionNames = ((DefaultQuery)query).getRegionsInQuery(null);
++    
++    //Do request(Pre) authorization if security is enabled.
++    QueryOperationContext queryAuthzContext = null;
++    if(AuthorizationProvider.isSecurityEnabled()){
++      setAuthTokenHeader(headers);
++      AuthorizationProvider.init();
++      try{
++        queryAuthzContext = AuthorizationProvider.queryAuthorize(oql, regionNames, null);
++      }catch(NotAuthorizedException nae) {
++        return new ResponseEntity<String>(headers, HttpStatus.UNAUTHORIZED);
++      }
++    }
++    
+     // NOTE Query.execute throws many checked Exceptions; let the BaseControllerAdvice Exception
handlers catch
+     // and handle the Exceptions appropriately (500 Server Error)!
+     try {
+       Object queryResult =  query.execute();
 -      return processQueryResponse(queryResult, "adhoc?q=" + oql);
++      
++      //Post authorization
++      if(AuthorizationProvider.isSecurityEnabled()){
++        queryAuthzContext = AuthorizationProvider.queryAuthorizePP(oql, regionNames, queryResult,
queryAuthzContext, null);
++        if(queryAuthzContext != null){
++          queryResult = queryAuthzContext.getQueryResult();
++        }
++      }
++      return processQueryResponse(queryResult, "adhoc?q=" + oql, headers);
+     } catch (FunctionDomainException fde) {
+       throw new GemfireRestException("A function was applied to a parameter that is improper
for that function!", fde);
+     } catch (TypeMismatchException tme) {
+       throw new GemfireRestException("Bind parameter is not of the expected type!", tme);
+     }catch (NameResolutionException nre) {
+       throw new GemfireRestException("Name in the query cannot be resolved!", nre);
+     }catch (IllegalArgumentException iae) {
+       throw new GemfireRestException(" The number of bound parameters does not match the
number of placeholders!", iae);
+     }catch (IllegalStateException ise) {
+       throw new GemfireRestException("Query is not permitted on this type of region!", ise);
+     }catch (QueryExecutionTimeoutException qete) {
+       throw new GemfireRestException("Query execution time is exceeded max query execution
time (gemfire.Cache.MAX_QUERY_EXECUTION_TIME) configured! ", qete);
+     }catch (QueryInvocationTargetException qite) {
+       throw new GemfireRestException("Data referenced in from clause is not available for
querying!", qite);
+     }catch (QueryExecutionLowMemoryException qelme) {
+       throw new GemfireRestException("Query execution gets canceled due to low memory conditions
and the resource manager critical heap percentage has been set!", qelme);
+     }
+     catch (Exception e) {
+       throw new GemfireRestException("Server has encountered while executing Adhoc query!",
e);
+     }
+   }
+ 
+   /**
+    * Run named parameterized Query with ID
+    * @param queryId id of the OQL string
+    * @param arguments query bind params required while executing query
+    * @return query result as a JSON document
+    */
+   @RequestMapping(method = RequestMethod.POST, value = "/{query}", produces = {MediaType.APPLICATION_JSON_VALUE})
+   @ApiOperation(
+     value = "run parameterized query",
+     notes = "run the specified named query passing in scalar values for query parameters
in the GemFire cluster",
+     response  = void.class
+   )
+   @ApiResponses( {
+     @ApiResponse( code = 200, message = "Query successfully executed." ),
+     @ApiResponse( code = 400, message = "Query bind params specified as JSON document in
the request body is invalid" ),
+     @ApiResponse( code = 500, message = "GemFire throws an error or exception" )   
+   } )
+   @ResponseBody
+   @ResponseStatus(HttpStatus.OK)
+   public ResponseEntity<String> runNamedQuery(@PathVariable("query") String queryId,
+                                               @RequestBody String arguments)
+   {
+     if (logger.isDebugEnabled()) {
+       logger.debug("Running named Query with ID ({})...", queryId);
+     }
+     queryId = decode(queryId);
++    HttpHeaders headers = new HttpHeaders();
+     
+     if (arguments != null) {
+       // Its a compiled query.
+       
+       //Convert arguments into Object[]
+       Object args[] = jsonToObjectArray(arguments);
+       
++      final String oql = getValue(PARAMETERIZED_QUERIES_REGION, queryId);
+       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);
 -        
+         ValidationUtils.returnValueThrowOnNull(oql, new ResourceNotFoundException(
+           String.format("No Query with ID (%1$s) was found!", queryId)));
+         try {   
+           compiledQuery = getQueryService().newQuery(oql);
+         } catch (QueryInvalidException qie) {
+           throw new GemfireRestException("Syntax of the OQL queryString is invalid!", qie);
+         }
+         compiledQueries.putIfAbsent(queryId, (DefaultQuery)compiledQuery);
+       }  
 -       // NOTE Query.execute throws many checked Exceptions; let the BaseControllerAdvice
Exception handlers catch
++       
++      Set regionNames = ((DefaultQuery)compiledQuery).getRegionsInQuery(args);
++      
++      //Do request(Pre) authorization if security is enabled.
++      QueryOperationContext queryAuthzContext = null;
++      if(AuthorizationProvider.isSecurityEnabled()){
++        setAuthTokenHeader(headers);
++        AuthorizationProvider.init();
++        try{
++          queryAuthzContext= AuthorizationProvider.queryAuthorize(oql, regionNames, args);
++        }catch(NotAuthorizedException nae) {
++          return new ResponseEntity<String>(headers, HttpStatus.UNAUTHORIZED);
++        }
++      }
++      
++      // NOTE Query.execute throws many checked Exceptions; let the BaseControllerAdvice
Exception handlers catch
+        // and handle the Exceptions appropriately (500 Server Error)!
+        try {
+          Object queryResult =  compiledQuery.execute(args);
 -         return processQueryResponse(queryResult, queryId);
++         
++         //Post authorization
++         if(AuthorizationProvider.isSecurityEnabled()){
++           queryAuthzContext = AuthorizationProvider.queryAuthorizePP(oql, regionNames,
queryResult, queryAuthzContext, args);
++           if(queryAuthzContext != null){
++             queryResult = queryAuthzContext.getQueryResult();
++           }
++         }
++         
++         return processQueryResponse(queryResult, queryId, headers);
+        } catch (FunctionDomainException fde) {
+          throw new GemfireRestException("A function was applied to a parameter that is improper
for that function!", fde);
+        } catch (TypeMismatchException tme) {
+          throw new GemfireRestException("Bind parameter is not of the expected type!", tme);
+        } catch (NameResolutionException nre) {
+          throw new GemfireRestException("Name in the query cannot be resolved!", nre);
+        } catch (IllegalArgumentException iae) {
+          throw new GemfireRestException(" The number of bound parameters does not match
the number of placeholders!", iae);
+        } catch (IllegalStateException ise) {
+          throw new GemfireRestException("Query is not permitted on this type of region!",
ise);
+        } catch (QueryExecutionTimeoutException qete) {
+          throw new GemfireRestException("Query execution time is exceeded  max query execution
time (gemfire.Cache.MAX_QUERY_EXECUTION_TIME) configured!", qete);
+        } catch (QueryInvocationTargetException qite) {
+          throw new GemfireRestException("Data referenced in from clause is not available
for querying!", qite);
+        } catch (QueryExecutionLowMemoryException qelme) {
+          throw new GemfireRestException("Query gets canceled due to low memory conditions
and the resource manager critical heap percentage has been set!", qelme);
+        } catch (Exception e) {
+          throw new GemfireRestException("Error encountered while executing named query!",
e);
+        }
+      } else {
+        throw new GemfireRestException(" Bind params either not specified or not processed
properly by the server!"); 
+      }
+   }
+ 
+   /**
+    * Update named, parameterized Query
+    * @param queryId uniquely identify the query
+    * @param oqlInUrl OQL query string specified in a request URL
+    * @param oqlInBody OQL query string specified in a request body
+    */
+   @RequestMapping(method = RequestMethod.PUT, value = "/{query}")
+   @ApiOperation(
+     value = "update parameterized query",
+     notes = "Update named, parameterized query by ID",
+     response  = void.class
+   )
+   @ApiResponses( {
+     @ApiResponse( code = 200, message = "Updated successfully." ),
+     @ApiResponse( code = 404, message = "queryId does not exist." ),
+     @ApiResponse( code = 500, message = "GemFire throws an error or exception." )   
+   } )
+   public ResponseEntity<?> update( @PathVariable("query") final String queryId,
+                                    @RequestParam(value = "q", required = false) String oqlInUrl,
+                                    @RequestBody(required = false) final String oqlInBody)
{
+     
+     final String oqlStatement = validateQuery(oqlInUrl, oqlInBody);
 -
++    
+     if (logger.isDebugEnabled()) {
+       logger.debug("Updating a named, parameterized Query ({}) with ID ({})...", oqlStatement,
queryId);
+     }
 -
++    
++    HttpHeaders headers = new HttpHeaders();
++    
++    //Do request(Pre) authorization if security is enabled.
++    if(AuthorizationProvider.isSecurityEnabled()){
++      setAuthTokenHeader(headers);
++      AuthorizationProvider.init();
++      try{
++        AuthorizationProvider.updateQueryAuthorize(OperationCode.UPDATE_QUERY, true, "UPDATE_QUERY",
queryId, oqlStatement);
++      }catch(NotAuthorizedException nae) {
++        return new ResponseEntity<String>(headers, HttpStatus.UNAUTHORIZED);
++      }
++    }
++    
+     // update the OQL statement with 'queryId' as the Key into the hidden, ParameterizedQueries
Region...
+     checkForQueryIdExist(PARAMETERIZED_QUERIES_REGION, queryId);
+     updateNamedQuery(PARAMETERIZED_QUERIES_REGION, queryId, oqlStatement);
+     compiledQueries.remove(queryId);
+ 
 -    return new ResponseEntity<Object>(HttpStatus.OK);
++    return new ResponseEntity<Object>(headers, HttpStatus.OK);
+   }
+ 
+   //delete named, parameterized query
+   /**
+    * Delete named, parameterized Query
+    * @param queryId uniquely identify the query to be deleted
+    */
+   @RequestMapping(method = RequestMethod.DELETE, value = "/{query}")
+   @ApiOperation(
+     value = "delete parameterized query",
+     notes = "delete named, parameterized query by ID",
+     response  = void.class
+   )
+   @ApiResponses( {
+     @ApiResponse( code = 200, message = "Deleted successfully." ),
+     @ApiResponse( code = 404, message = "queryId does not exist." ),
+     @ApiResponse( code = 500, message = "GemFire throws an error or exception" )   
+   } )
+   public ResponseEntity<?> delete(@PathVariable("query") final String queryId) {
+ 
+     if (logger.isDebugEnabled()) {
+       logger.debug("Deleting a named, parameterized Query with ID ({}).", queryId);
+     }
+     
++    HttpHeaders headers = new HttpHeaders();
++    
++    //Do request(Pre) authorization if security is enabled.
++    if(AuthorizationProvider.isSecurityEnabled()){
++      setAuthTokenHeader(headers);
++      AuthorizationProvider.init();
++      try{
++        AuthorizationProvider.deleteQueryAuthorize(OperationCode.DELETE_QUERY, true, "DELETE_QUERY",
queryId);
++      }catch(NotAuthorizedException nae) {
++        return new ResponseEntity<String>(headers, HttpStatus.UNAUTHORIZED);
++      }
++    }
++    
+     //delete the OQL statement with 'queryId' as the Key into the hidden,
+     // ParameterizedQueries Region...
+     deleteNamedQuery(PARAMETERIZED_QUERIES_REGION, queryId);
+     compiledQueries.remove(queryId);
 -    return new ResponseEntity<Object>(HttpStatus.OK);
++    return new ResponseEntity<Object>(headers, HttpStatus.OK);
+   }
+   
+ }
+ 

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/5c01d5f4/geode-web-api/src/main/webapp/WEB-INF/web.xml
----------------------------------------------------------------------
diff --cc geode-web-api/src/main/webapp/WEB-INF/web.xml
index 0000000,ad354f1..56a1c85
mode 000000,100644..100644
--- a/geode-web-api/src/main/webapp/WEB-INF/web.xml
+++ b/geode-web-api/src/main/webapp/WEB-INF/web.xml
@@@ -1,0 -1,65 +1,75 @@@
+ <?xml version="1.0" encoding="UTF-8"?>
+ <!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements.  See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License.  You may obtain a copy of the License at
+ 
+      http://www.apache.org/licenses/LICENSE-2.0
+ 
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+ <web-app xmlns="http://java.sun.com/xml/ns/javaee"
+          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+          xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
+          version="3.0">
+ 
+   <display-name>GemFire Developer REST API</display-name>
+ 
+   <description>
+     Web deployment descriptor declaring the developer REST API for GemFire.
+   </description>
+   
+   <!-- context-param>
+     <param-name>contextConfigLocation</param-name>
+     <param-value>/META-INF/cache-config.xml</param-value>
+   </context-param -->
+   
+   <filter>
+     <filter-name>httpPutFilter</filter-name>
+     <filter-class>org.springframework.web.filter.HttpPutFormContentFilter</filter-class>
+     <async-supported>true</async-supported>
+   </filter>
+ 
+   <filter-mapping>
+     <filter-name>httpPutFilter</filter-name>
+     <url-pattern>/*</url-pattern>
+   </filter-mapping>
+ 
+   <!-- listener>
+     <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
+   </listener-->
+ 
+   <servlet>
+     <description>
+       The Spring DispatcherServlet (FrontController) handling all HTTP requests to the Developer
REST API
+       GemFire Web Application.
+     </description>
+     <servlet-name>gemfire-api</servlet-name>
+     <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
+     <load-on-startup>1</load-on-startup>
+     <async-supported>true</async-supported>
+   </servlet>
+    
+   <servlet-mapping>
+     <servlet-name>gemfire-api</servlet-name>
+     <url-pattern>/*</url-pattern>
+   </servlet-mapping>
+   
++  <filter>
++    <filter-name>restRequestFilter</filter-name>
++    <filter-class>com.gemstone.gemfire.rest.internal.web.security.RestRequestFilter</filter-class>
++  </filter>
++
++  <filter-mapping>
++    <filter-name>restRequestFilter</filter-name>
++    <url-pattern>/*</url-pattern>
++  </filter-mapping>
++
+ </web-app>



Mime
View raw message