Repository: usergrid Updated Branches: refs/heads/master 3b1b0ca1c -> d92110853
http://git-wip-us.apache.org/repos/asf/usergrid/blob/a4941462/stack/rest/src/main/java/org/apache/usergrid/rest/exceptions/QueryAnalyzerEnforcementExceptionMapper.java ---------------------------------------------------------------------- diff --git a/stack/rest/src/main/java/org/apache/usergrid/rest/exceptions/QueryAnalyzerEnforcementExceptionMapper.java b/stack/rest/src/main/java/org/apache/usergrid/rest/exceptions/QueryAnalyzerEnforcementExceptionMapper.java new file mode 100644 index 0000000..fed97d1 --- /dev/null +++ b/stack/rest/src/main/java/org/apache/usergrid/rest/exceptions/QueryAnalyzerEnforcementExceptionMapper.java @@ -0,0 +1,51 @@ +/* + * 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.usergrid.rest.exceptions; + + +import org.apache.usergrid.persistence.index.exceptions.QueryAnalyzerEnforcementException; +import org.apache.usergrid.rest.ApiResponse; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.ws.rs.core.Response; +import javax.ws.rs.ext.Provider; + +import static javax.ws.rs.core.Response.Status.SERVICE_UNAVAILABLE; +import static org.apache.usergrid.utils.JsonUtils.mapToJsonString; + + +@Provider +public class QueryAnalyzerEnforcementExceptionMapper extends AbstractExceptionMapper<QueryAnalyzerEnforcementException> { + + private static final Logger logger = LoggerFactory.getLogger( QueryAnalyzerEnforcementExceptionMapper.class ); + + @Override + public Response toResponse( QueryAnalyzerEnforcementException e ) { + + // build a proper ApiResponse object + ApiResponse apiResponse = new ApiResponse(); + apiResponse.setError("query_analyzer_violations_enforced"); + apiResponse.setErrorDescription(e.getErrorMessage()); + + logger.warn(e.getErrorMessage()); + + // give toResponse() the json string value of the ApiResponse + // skip logging because we use a 5XX but it's not technically an error for the logs + return toResponse( SERVICE_UNAVAILABLE, mapToJsonString(apiResponse), true ); + } +} http://git-wip-us.apache.org/repos/asf/usergrid/blob/a4941462/stack/rest/src/main/java/org/apache/usergrid/rest/exceptions/QueryAnalyzerExceptionMapper.java ---------------------------------------------------------------------- diff --git a/stack/rest/src/main/java/org/apache/usergrid/rest/exceptions/QueryAnalyzerExceptionMapper.java b/stack/rest/src/main/java/org/apache/usergrid/rest/exceptions/QueryAnalyzerExceptionMapper.java new file mode 100644 index 0000000..bd5db14 --- /dev/null +++ b/stack/rest/src/main/java/org/apache/usergrid/rest/exceptions/QueryAnalyzerExceptionMapper.java @@ -0,0 +1,69 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.usergrid.rest.exceptions; + + +import org.apache.usergrid.persistence.index.QueryAnalyzer; +import org.apache.usergrid.persistence.index.exceptions.QueryAnalyzerException; +import org.apache.usergrid.rest.ApiResponse; + +import javax.ws.rs.core.MultivaluedHashMap; +import javax.ws.rs.core.MultivaluedMap; +import javax.ws.rs.core.Response; +import javax.ws.rs.ext.Provider; + +import java.util.Collections; +import java.util.HashMap; + +import static javax.ws.rs.core.Response.Status.OK; +import static org.apache.usergrid.utils.JsonUtils.mapToFormattedJsonString; + + +@Provider +public class QueryAnalyzerExceptionMapper extends AbstractExceptionMapper<QueryAnalyzerException> { + + // This mapper is used to short-circuit the query process on any collection query. Therefore, it does its best + // job to build a normal ApiResponse format with 200 OK status. + + @Override + public Response toResponse( QueryAnalyzerException e ) { + + + MultivaluedMap<String, String> params = new MultivaluedHashMap<>(); + params.add("ql", e.getOriginalQuery()); + params.add("analyzeOnly", "true"); + + // build a proper ApiResponse object + ApiResponse apiResponse = new ApiResponse(); + apiResponse.setParams(params); + apiResponse.setSuccess(); + + // remove large_index warnings because indexes are shared buckets and not specific for an app + for( int i=0; i < e.getViolations().size(); i++) { + if (e.getViolations().get(i).get(QueryAnalyzer.k_violation) == QueryAnalyzer.v_large_index) { + e.getViolations().remove(i); + } + } + + apiResponse.setMetadata(new HashMap<String,Object>(){{put("queryWarnings", e.getViolations());}}); + apiResponse.setEntities(Collections.emptyList()); + apiResponse.setAction("query analysis only"); + + // give toResponse() the json string value of the ApiResponse + return toResponse( OK, mapToFormattedJsonString(apiResponse) ); + } +} http://git-wip-us.apache.org/repos/asf/usergrid/blob/a4941462/stack/services/src/main/java/org/apache/usergrid/services/AbstractService.java ---------------------------------------------------------------------- diff --git a/stack/services/src/main/java/org/apache/usergrid/services/AbstractService.java b/stack/services/src/main/java/org/apache/usergrid/services/AbstractService.java index 6736894..f60bfdd 100644 --- a/stack/services/src/main/java/org/apache/usergrid/services/AbstractService.java +++ b/stack/services/src/main/java/org/apache/usergrid/services/AbstractService.java @@ -29,6 +29,7 @@ import org.apache.usergrid.persistence.cache.CacheFactory; import org.apache.usergrid.persistence.core.metrics.MetricsFactory; import org.apache.usergrid.persistence.core.metrics.ObservableTimer; import org.apache.usergrid.persistence.core.rx.RxTaskScheduler; +import org.apache.usergrid.persistence.index.exceptions.QueryAnalyzerException; import org.apache.usergrid.security.shiro.utils.LocalShiroCache; import org.apache.usergrid.security.shiro.utils.SubjectUtils; import org.apache.usergrid.services.ServiceParameter.IdParameter; @@ -686,6 +687,7 @@ public abstract class AbstractService implements Service { Query.fromIdentifier( name ), parameters, payload ); } else if ( query != null ) { + query.setAnalyzeOnly(request.isAnalyzeQueryOnly()); return new ServiceContext( this, action, request, previousResults, owner, collectionName, query, parameters, payload ); } http://git-wip-us.apache.org/repos/asf/usergrid/blob/a4941462/stack/services/src/main/java/org/apache/usergrid/services/ServiceManager.java ---------------------------------------------------------------------- diff --git a/stack/services/src/main/java/org/apache/usergrid/services/ServiceManager.java b/stack/services/src/main/java/org/apache/usergrid/services/ServiceManager.java index 04e00e0..075278f 100644 --- a/stack/services/src/main/java/org/apache/usergrid/services/ServiceManager.java +++ b/stack/services/src/main/java/org/apache/usergrid/services/ServiceManager.java @@ -31,7 +31,6 @@ import org.apache.usergrid.mq.QueueManager; import org.apache.usergrid.persistence.Entity; import org.apache.usergrid.persistence.EntityManager; import org.apache.usergrid.persistence.EntityRef; -import org.apache.usergrid.persistence.cassandra.CassandraService; import org.apache.usergrid.persistence.entities.Application; import org.apache.usergrid.services.ServiceParameter.IdParameter; import org.apache.usergrid.services.applications.ApplicationsService; @@ -358,13 +357,13 @@ public class ServiceManager { public ServiceRequest newRequest( ServiceAction action, List<ServiceParameter> parameters ) throws Exception { - return newRequest( action, false, parameters, null, true, true ); + return newRequest( action, false, parameters, null, true, true, false); } public ServiceRequest newRequest( ServiceAction action, List<ServiceParameter> parameters, ServicePayload payload ) throws Exception { - return newRequest( action, false, parameters, payload, true, true ); + return newRequest( action, false, parameters, payload, true, true, false); } @@ -381,9 +380,9 @@ public class ServiceManager { static ApplicationsService appService = new ApplicationsService(); - public ServiceRequest newRequest( ServiceAction action, boolean returnsTree, List<ServiceParameter> parameters, - ServicePayload payload, boolean returnsInboundConnections, - boolean returnsOutboundConnections ) throws Exception { + public ServiceRequest newRequest(ServiceAction action, boolean returnsTree, List<ServiceParameter> parameters, + ServicePayload payload, boolean returnsInboundConnections, + boolean returnsOutboundConnections, boolean analyzeQueryOnly) throws Exception { if ( em != null ) { if ( action != null ) { @@ -414,12 +413,12 @@ public class ServiceManager { String serviceName = pluralize( ServiceParameter.dequeueParameter( parameters ).getName() ); return new ServiceRequest( this, action, serviceName, parameters, payload, returnsTree, - returnsInboundConnections, returnsOutboundConnections ); + returnsInboundConnections, returnsOutboundConnections, analyzeQueryOnly); } public ServiceRequest newRequest( ServiceAction action, boolean returnsTree, List<ServiceParameter> parameters, ServicePayload payload ) throws Exception { - return newRequest( action, returnsTree, parameters, payload, true, true ); + return newRequest( action, returnsTree, parameters, payload, true, true, false); } public void notifyExecutionEventListeners( ServiceAction action, ServiceRequest request, ServiceResults results, http://git-wip-us.apache.org/repos/asf/usergrid/blob/a4941462/stack/services/src/main/java/org/apache/usergrid/services/ServiceRequest.java ---------------------------------------------------------------------- diff --git a/stack/services/src/main/java/org/apache/usergrid/services/ServiceRequest.java b/stack/services/src/main/java/org/apache/usergrid/services/ServiceRequest.java index f8a5abb..89f4976 100644 --- a/stack/services/src/main/java/org/apache/usergrid/services/ServiceRequest.java +++ b/stack/services/src/main/java/org/apache/usergrid/services/ServiceRequest.java @@ -59,13 +59,14 @@ public class ServiceRequest { private final boolean returnsOutboundConnections; private final ServicePayload payload; private final List<ServiceParameter> originalParameters; + private final boolean analyzeQueryOnly; // return results_set, result_entity, new_service, param_list, properties - public ServiceRequest( ServiceManager services, ServiceAction action, String serviceName, - List<ServiceParameter> parameters, ServicePayload payload, boolean returnsTree, - boolean returnsInboundConnections, boolean returnsOutboundConnections ) { + public ServiceRequest(ServiceManager services, ServiceAction action, String serviceName, + List<ServiceParameter> parameters, ServicePayload payload, boolean returnsTree, + boolean returnsInboundConnections, boolean returnsOutboundConnections, boolean analyzeQueryOnly) { this.services = services; this.action = action; parent = null; @@ -78,6 +79,7 @@ public class ServiceRequest { this.returnsTree = returnsTree; this.returnsInboundConnections = returnsInboundConnections; this.returnsOutboundConnections = returnsOutboundConnections; + this.analyzeQueryOnly = analyzeQueryOnly; if ( payload == null ) { payload = new ServicePayload(); } @@ -87,13 +89,13 @@ public class ServiceRequest { public ServiceRequest( ServiceManager services, ServiceAction action, String serviceName, List<ServiceParameter> parameters, ServicePayload payload, boolean returnsTree) { - this( services, action, serviceName, parameters, payload, returnsTree, true, true); + this( services, action, serviceName, parameters, payload, returnsTree, true, true, false); } public ServiceRequest( ServiceManager services, ServiceAction action, String serviceName, List<ServiceParameter> parameters, ServicePayload payload ) { - this( services, action, serviceName, parameters, payload, false, true, true ); + this( services, action, serviceName, parameters, payload, false, true, true, false); } @@ -103,6 +105,7 @@ public class ServiceRequest { this.returnsTree = parent.returnsTree; this.returnsInboundConnections = parent.returnsInboundConnections; this.returnsOutboundConnections = parent.returnsOutboundConnections; + this.analyzeQueryOnly = parent.analyzeQueryOnly; this.action = parent.action; this.payload = parent.payload; this.parent = parent; @@ -121,7 +124,7 @@ public class ServiceRequest { public ServiceRequest( ServiceManager services, ServiceAction action, ServiceRequest parent, EntityRef owner, String path, String childPath, String serviceName, List<ServiceParameter> parameters, ServicePayload payload, boolean returnsTree, boolean returnsInboundConnections, - boolean returnsOutboundConnections ) { + boolean returnsOutboundConnections, boolean analyzeQueryOnly ) { this.services = services; this.action = action; this.parent = parent; @@ -134,25 +137,26 @@ public class ServiceRequest { this.returnsTree = returnsTree; this.returnsInboundConnections = returnsInboundConnections; this.returnsOutboundConnections = returnsOutboundConnections; + this.analyzeQueryOnly = analyzeQueryOnly; this.payload = payload; } public ServiceRequest( ServiceManager services, ServiceAction action, ServiceRequest parent, EntityRef owner, String path, String childPath, String serviceName, List<ServiceParameter> parameters, ServicePayload payload, boolean returnsTree ) { - this(services, action, parent, owner, path, childPath, serviceName, parameters, payload, returnsTree, true, true); + this(services, action, parent, owner, path, childPath, serviceName, parameters, payload, returnsTree, true, true, false); } public static ServiceRequest withPath( ServiceRequest r, String path ) { return new ServiceRequest( r.services, r.action, r.parent, r.owner, path, r.childPath, r.serviceName, - r.parameters, r.payload, r.returnsTree, r.returnsInboundConnections, r.returnsOutboundConnections ); + r.parameters, r.payload, r.returnsTree, r.returnsInboundConnections, r.returnsOutboundConnections, r.analyzeQueryOnly ); } public static ServiceRequest withChildPath( ServiceRequest r, String childPath ) { return new ServiceRequest( r.services, r.action, r.parent, r.owner, r.path, childPath, r.serviceName, - r.parameters, r.payload, r.returnsTree, r.returnsInboundConnections, r.returnsOutboundConnections ); + r.parameters, r.payload, r.returnsTree, r.returnsInboundConnections, r.returnsOutboundConnections, r.analyzeQueryOnly ); } @@ -390,4 +394,8 @@ public class ServiceRequest { public List<ServiceParameter> getOriginalParameters() { return originalParameters; } + + public boolean isAnalyzeQueryOnly(){ + return analyzeQueryOnly; + } }