use of datawave.webservice.common.exception.BadRequestException in project datawave by NationalSecurityAgency.
the class QueryExecutorBean method lookupContentByUUIDBatch.
/**
* @param queryParameters
* @param httpHeaders
* @return content results, either as a paged BaseQueryResponse or StreamingOutput
* @RequestHeader X-ProxiedEntitiesChain use when proxying request for user, by specifying a chain of DNs of the identities to proxy
* @RequestHeader X-ProxiedIssuersChain required when using X-ProxiedEntitiesChain, specify one issuer DN per subject DN listed in X-ProxiedEntitiesChain
* @ResponseHeader query-session-id this header and value will be in the Set-Cookie header, subsequent calls for this session will need to supply the
* query-session-id header in the request in a Cookie header or as a query parameter
* @ResponseHeader X-OperationTimeInMS time spent on the server performing the operation, does not account for network or result serialization
* @ResponseHeader X-Partial-Results true if the page contains less than the requested number of results
*
* @HTTP 200 success
* @HTTP 204 success and no results
* @HTTP 400 invalid or missing parameter
* @HTTP 500 internal server error
*/
@POST
@Path("/lookupContentUUID")
@Produces({ "application/xml", "text/xml", "application/json", "text/yaml", "text/x-yaml", "application/x-yaml", "application/x-protobuf", "application/x-protostuff" })
@GZIP
@GenerateQuerySessionId(cookieBasePath = "/DataWave/Query/")
@Interceptors({ ResponseInterceptor.class, RequiredInterceptor.class })
@Override
@Timed(name = "dw.query.lookupContentUUIDBatch", absolute = true)
public <T> T lookupContentByUUIDBatch(MultivaluedMap<String, String> queryParameters, @Required("httpHeaders") @Context HttpHeaders httpHeaders) {
if (!queryParameters.containsKey("uuidPairs")) {
throw new BadRequestException(new IllegalArgumentException("uuidPairs missing from query parameters"), new VoidResponse());
}
T response = null;
String queryId = null;
try {
String uuidPairs = queryParameters.getFirst("uuidPairs");
String streaming = queryParameters.getFirst("streaming");
boolean streamingOutput = false;
if (!StringUtils.isEmpty(streaming)) {
streamingOutput = Boolean.parseBoolean(streaming);
}
// Create the criteria for looking up the respective events, which we need to get the shard IDs and column families
// required for the content lookup
final PostUUIDCriteria criteria = new PostUUIDCriteria(uuidPairs, queryParameters);
// Set the HTTP headers if a streamed response is required
if (streamingOutput) {
criteria.setStreamingOutputHeaders(httpHeaders);
}
response = this.lookupUUIDUtil.lookupContentByUUIDs(criteria);
if (response instanceof BaseQueryResponse) {
queryId = ((BaseQueryResponse) response).getQueryId();
}
return response;
} finally {
if (null != queryId) {
asyncClose(queryId);
}
}
}
use of datawave.webservice.common.exception.BadRequestException in project datawave by NationalSecurityAgency.
the class QueryExecutorBean method createQuery.
/**
* @param queryLogicName
* @param queryParameters
* @return
*/
@POST
@Produces({ "application/xml", "text/xml", "application/json", "text/yaml", "text/x-yaml", "application/x-yaml", "application/x-protobuf", "application/x-protostuff" })
@Path("/{logicName}/create")
@GZIP
@GenerateQuerySessionId(cookieBasePath = "/DataWave/Query/")
@EnrichQueryMetrics(methodType = MethodType.CREATE)
@Interceptors({ RequiredInterceptor.class, ResponseInterceptor.class })
@Timed(name = "dw.query.createQuery", absolute = true)
public GenericResponse<String> createQuery(@Required("logicName") @PathParam("logicName") String queryLogicName, MultivaluedMap<String, String> queryParameters, @Context HttpHeaders httpHeaders) {
CreateQuerySessionIDFilter.QUERY_ID.set(null);
QueryData qd = validateQuery(queryLogicName, queryParameters, httpHeaders);
GenericResponse<String> response = new GenericResponse<>();
Query q = null;
Connector connection = null;
AccumuloConnectionFactory.Priority priority;
Span createSpan = null;
RunningQuery rq = null;
try {
// Default hasResults to true. If a query logic is actually able to set this value,
// then their value will overwrite this one. Otherwise, we return true so that
// callers know they have to call next (even though next may not return results).
response.setHasResults(true);
AuditType auditType = qd.logic.getAuditType(null);
try {
MultivaluedMap<String, String> optionalQueryParameters = new MultivaluedMapImpl<>();
optionalQueryParameters.putAll(qp.getUnknownParameters(queryParameters));
q = persister.create(qd.userDn, qd.dnList, marking, queryLogicName, qp, optionalQueryParameters);
auditType = qd.logic.getAuditType(q);
} finally {
queryParameters.add(PrivateAuditConstants.AUDIT_TYPE, auditType.name());
if (!auditType.equals(AuditType.NONE)) {
// audit the query before its executed.
try {
try {
List<String> selectors = qd.logic.getSelectors(q);
if (selectors != null && !selectors.isEmpty()) {
queryParameters.put(PrivateAuditConstants.SELECTORS, selectors);
}
} catch (Exception e) {
log.error("Error accessing query selector", e);
}
// if the user didn't set an audit id, use the query id
if (!queryParameters.containsKey(AuditParameters.AUDIT_ID)) {
queryParameters.putSingle(AuditParameters.AUDIT_ID, q.getId().toString());
}
auditor.audit(queryParameters);
} catch (IllegalArgumentException e) {
log.error("Error validating audit parameters", e);
BadRequestQueryException qe = new BadRequestQueryException(DatawaveErrorCode.MISSING_REQUIRED_PARAMETER, e);
response.addException(qe);
throw new BadRequestException(qe, response);
} catch (Exception e) {
log.error("Error auditing query", e);
QueryException qe = new QueryException(DatawaveErrorCode.QUERY_AUDITING_ERROR, e);
response.addException(qe);
throw qe;
}
}
}
priority = qd.logic.getConnectionPriority();
Map<String, String> trackingMap = connectionFactory.getTrackingMap(Thread.currentThread().getStackTrace());
addQueryToTrackingMap(trackingMap, q);
accumuloConnectionRequestBean.requestBegin(q.getId().toString());
try {
connection = connectionFactory.getConnection(qd.logic.getConnPoolName(), priority, trackingMap);
} finally {
accumuloConnectionRequestBean.requestEnd(q.getId().toString());
}
// If we're supposed to trace this query, then turn tracing on and set information about the query
// onto the span so that it is saved in the trace table.
TInfo traceInfo = null;
boolean shouldTraceQuery = shouldTraceQuery(qp.getQuery(), qd.userid, qp.isTrace());
if (shouldTraceQuery) {
Span span = Trace.on("query:" + q.getId());
log.debug("Tracing query " + q.getId() + " [" + qp.getQuery() + "] on trace ID " + Long.toHexString(span.traceId()));
for (Entry<String, List<String>> param : queryParameters.entrySet()) {
span.data(param.getKey(), param.getValue().get(0));
}
traceInfo = Tracer.traceInfo();
createSpan = Trace.start("query:create");
}
// hold on to a reference of the query logic so we cancel it if need be.
qlCache.add(q.getId().toString(), qd.userid, qd.logic, connection);
rq = new RunningQuery(metrics, null, priority, qd.logic, q, qp.getAuths(), qd.p, new RunningQueryTimingImpl(queryExpirationConf, qp.getPageTimeout()), this.executor, this.predictor, this.metricFactory);
rq.setActiveCall(true);
rq.setTraceInfo(traceInfo);
rq.getMetric().setProxyServers(qd.proxyServers);
rq.setConnection(connection);
// Put in the cache by id. Don't put the cache in by name because multiple users may use the same name
// and only the last one will be in the cache.
queryCache.put(q.getId().toString(), rq);
response.setResult(q.getId().toString());
rq.setActiveCall(false);
CreateQuerySessionIDFilter.QUERY_ID.set(q.getId().toString());
return response;
} catch (Throwable t) {
response.setHasResults(false);
if (rq != null) {
rq.getMetric().setError(t);
}
// close the logic on exception
try {
if (null != qd.logic) {
qd.logic.close();
}
} catch (Exception e) {
log.error("Exception occured while closing query logic; may be innocuous if scanners were running.", e);
}
if (null != connection) {
try {
connectionFactory.returnConnection(connection);
} catch (Exception e) {
log.error("Error returning connection on failed create", e);
}
}
try {
if (null != q)
persister.remove(q);
} catch (Exception e) {
response.addException(new QueryException(DatawaveErrorCode.DEPERSIST_ERROR, e).getBottomQueryException());
}
/*
* Allow web services to throw their own WebApplicationExceptions
*/
if (t instanceof Error && !(t instanceof TokenMgrError)) {
log.error(t.getMessage(), t);
throw (Error) t;
} else if (t instanceof WebApplicationException) {
log.error(t.getMessage(), t);
throw ((WebApplicationException) t);
} else if (t instanceof InterruptedException) {
if (rq != null) {
rq.getMetric().setLifecycle(QueryMetric.Lifecycle.CANCELLED);
}
log.info("Query " + q.getId() + " canceled on request");
QueryException qe = new QueryException(DatawaveErrorCode.QUERY_CANCELED, t);
response.addException(qe.getBottomQueryException());
int statusCode = qe.getBottomQueryException().getStatusCode();
throw new DatawaveWebApplicationException(qe, response, statusCode);
} else {
log.error(t.getMessage(), t);
QueryException qe = new QueryException(DatawaveErrorCode.RUNNING_QUERY_CACHE_ERROR, t);
response.addException(qe.getBottomQueryException());
int statusCode = qe.getBottomQueryException().getStatusCode();
throw new DatawaveWebApplicationException(qe, response, statusCode);
}
} finally {
if (createSpan != null) {
createSpan.stop();
// TODO: not sure this makes any sense anymore in Accumulo 1.8.1
// Stop the main query span since we're done working with it on this thread.
// We'll continue it later.
// createSpan.parent().stop();
}
if (null != q) {
// - Remove the logic from the cache
qlCache.poll(q.getId().toString());
}
}
}
use of datawave.webservice.common.exception.BadRequestException in project datawave by NationalSecurityAgency.
the class QueryExecutorBean method lookupUUIDBatch.
/**
* @param queryParameters
* @param httpHeaders
* @return event results, either as a paged BaseQueryResponse or StreamingOutput
* @RequestHeader X-ProxiedEntitiesChain use when proxying request for user, by specifying a chain of DNs of the identities to proxy
* @RequestHeader X-ProxiedIssuersChain required when using X-ProxiedEntitiesChain, specify one issuer DN per subject DN listed in X-ProxiedEntitiesChain
* @ResponseHeader query-session-id this header and value will be in the Set-Cookie header, subsequent calls for this session will need to supply the
* query-session-id header in the request in a Cookie header or as a query parameter
* @ResponseHeader X-OperationTimeInMS time spent on the server performing the operation, does not account for network or result serialization
* @ResponseHeader X-Partial-Results true if the page contains less than the requested number of results
*
* @HTTP 200 success
* @HTTP 204 success and no results
* @HTTP 400 invalid or missing parameter
* @HTTP 500 internal server error
*/
@POST
@Path("/lookupUUID")
@Produces({ "application/xml", "text/xml", "application/json", "text/yaml", "text/x-yaml", "application/x-yaml", "application/x-protobuf", "application/x-protostuff" })
@GZIP
@GenerateQuerySessionId(cookieBasePath = "/DataWave/Query/")
@Interceptors({ ResponseInterceptor.class, RequiredInterceptor.class })
@Override
@Timed(name = "dw.query.lookupUUIDBatch", absolute = true)
public <T> T lookupUUIDBatch(MultivaluedMap<String, String> queryParameters, @Required("httpHeaders") @Context HttpHeaders httpHeaders) {
if (!queryParameters.containsKey("uuidPairs")) {
throw new BadRequestException(new IllegalArgumentException("uuidPairs missing from query parameters"), new VoidResponse());
}
T response;
String queryId = null;
try {
String uuidPairs = queryParameters.getFirst("uuidPairs");
String streaming = queryParameters.getFirst("streaming");
boolean streamingOutput = false;
if (!StringUtils.isEmpty(streaming)) {
streamingOutput = Boolean.parseBoolean(streaming);
}
final PostUUIDCriteria criteria = new PostUUIDCriteria(uuidPairs, queryParameters);
if (streamingOutput) {
criteria.setStreamingOutputHeaders(httpHeaders);
}
response = this.lookupUUIDUtil.createUUIDQueryAndNext(criteria);
if (response instanceof BaseQueryResponse) {
queryId = ((BaseQueryResponse) response).getQueryId();
}
return response;
} finally {
if (null != queryId) {
asyncClose(queryId);
}
}
}
use of datawave.webservice.common.exception.BadRequestException in project datawave by NationalSecurityAgency.
the class MapReduceBean method ooziesubmit.
/**
* Execute a Oozie workflow with the given workFlow name and runtime parameters
*
* @param queryParameters
* @return
*/
@POST
@Produces({ "application/xml", "text/xml", "application/json", "text/yaml", "text/x-yaml", "application/x-yaml", "application/x-protobuf", "application/x-protostuff" })
@javax.ws.rs.Path("/ooziesubmit")
@GZIP
public GenericResponse<String> ooziesubmit(MultivaluedMap<String, String> queryParameters) {
GenericResponse<String> response = new GenericResponse<>();
String workFlow = queryParameters.getFirst(OozieJobConstants.WORKFLOW_PARAM);
if (StringUtils.isBlank(workFlow)) {
throw new BadRequestException(new IllegalArgumentException(OozieJobConstants.WORKFLOW_PARAM + " parameter missing"), response);
}
String parameters = queryParameters.getFirst(OozieJobConstants.PARAMETERS);
// Find out who/what called this method
Principal p = ctx.getCallerPrincipal();
String sid = null;
String userDn = p.getName();
DatawavePrincipal datawavePrincipal = null;
if (p instanceof DatawavePrincipal) {
datawavePrincipal = (DatawavePrincipal) p;
sid = datawavePrincipal.getShortName();
} else {
QueryException qe = new QueryException(DatawaveErrorCode.UNEXPECTED_PRINCIPAL_ERROR, MessageFormat.format("Class: {0}", p.getClass().getName()));
response.addException(qe);
throw new DatawaveWebApplicationException(qe, response);
}
OozieJobConfiguration job;
try {
MapReduceJobConfiguration mrConfig = this.mapReduceConfiguration.getConfiguration(workFlow);
if (mrConfig instanceof OozieJobConfiguration) {
job = (OozieJobConfiguration) mrConfig;
} else {
throw new IllegalArgumentException(workFlow + " not an Oozie job configuration");
}
} catch (IllegalArgumentException e) {
BadRequestQueryException qe = new BadRequestQueryException(DatawaveErrorCode.JOB_CONFIGURATION_ERROR, e);
response.addException(qe);
throw new BadRequestException(qe, response);
}
if (job instanceof NeedCallerDetails) {
((NeedCallerDetails) job).setUserSid(sid);
((NeedCallerDetails) job).setPrincipal(p);
}
// Ensure that the user has the required roles and has passed the required auths
if (null != job.getRequiredRoles() || null != job.getRequiredAuths()) {
try {
canRunJob(datawavePrincipal, queryParameters, job.getRequiredRoles(), job.getRequiredAuths());
} catch (UnauthorizedQueryException qe) {
// user does not have all of the required roles or did not pass the required auths
response.addException(qe);
throw new UnauthorizedException(qe, response);
}
}
String id = sid + "_" + UUID.randomUUID();
OozieClient oozieClient = null;
Properties oozieConf = null;
try {
oozieClient = new OozieClient((String) job.getJobConfigurationProperties().get(OozieJobConstants.OOZIE_CLIENT_PROP));
oozieConf = oozieClient.createConfiguration();
job.initializeOozieConfiguration(id, oozieConf, queryParameters);
job.validateWorkflowParameter(oozieConf, mapReduceConfiguration);
} catch (QueryException qe) {
log.error(qe.getMessage(), qe);
response.addException(qe);
throw new DatawaveWebApplicationException(qe, response);
} catch (Exception e) {
log.error(e.getMessage(), e);
response.addException(new QueryException(e.getMessage(), e));
throw new DatawaveWebApplicationException(e, response);
} finally {
// audit query here
Auditor.AuditType auditType = job.getAuditType();
log.trace("Audit type is: " + auditType.name());
if (!auditType.equals(Auditor.AuditType.NONE)) {
try {
marking.validate(queryParameters);
PrivateAuditConstants.stripPrivateParameters(queryParameters);
queryParameters.putSingle(PrivateAuditConstants.USER_DN, userDn);
queryParameters.putSingle(PrivateAuditConstants.COLUMN_VISIBILITY, marking.toColumnVisibilityString());
queryParameters.putSingle(PrivateAuditConstants.AUDIT_TYPE, auditType.name());
List<String> selectors = job.getSelectors(queryParameters, oozieConf);
if (selectors != null && !selectors.isEmpty()) {
queryParameters.put(PrivateAuditConstants.SELECTORS, selectors);
}
// if the user didn't set an audit id, use the query id
if (!queryParameters.containsKey(AuditParameters.AUDIT_ID)) {
queryParameters.putSingle(AuditParameters.AUDIT_ID, id);
}
auditor.audit(queryParameters);
} catch (IllegalArgumentException e) {
log.error("Error validating audit parameters", e);
BadRequestQueryException qe = new BadRequestQueryException(DatawaveErrorCode.MISSING_REQUIRED_PARAMETER, e);
response.addException(qe);
throw new BadRequestException(qe, response);
} catch (Exception e) {
log.error("Error auditing query", e);
response.addMessage("Error auditing query - " + e.getMessage());
throw new BadRequestException(e, response);
}
}
}
// Submit the Oozie workflow.
try {
String jobID = null;
try {
jobID = oozieClient.run(oozieConf);
} catch (Exception e) {
throw new QueryException(DatawaveErrorCode.OOZIE_JOB_START_ERROR, e);
}
try {
String jobResultstDir = oozieConf.getProperty(OozieJobConstants.OUT_DIR_PROP) + "/" + id;
response.setResult(id);
Path baseDir = new Path(this.mapReduceConfiguration.getMapReduceBaseDirectory());
// Create a directory path for this job
Path jobDir = new Path(baseDir, id);
mapReduceState.create(id, job.getHdfsUri(), job.getJobTracker(), jobDir.toString(), jobID, jobResultstDir, parameters, workFlow);
} catch (Exception e) {
QueryException qe = new QueryException(DatawaveErrorCode.MAPREDUCE_STATE_PERSISTENCE_ERROR, e);
response.addException(qe.getBottomQueryException());
try {
oozieClient.kill(jobID);
// if we successfully kill the job, throw the original exception
throw qe;
} catch (Exception e2) {
// throw the exception from killing the job
throw new QueryException(DatawaveErrorCode.MAPREDUCE_JOB_KILL_ERROR, e2);
}
}
} catch (QueryException qe) {
log.error(qe.getMessage(), qe);
response.addException(qe);
throw new DatawaveWebApplicationException(qe, response);
} catch (Exception e) {
log.error(e.getMessage(), e);
QueryException qe = new QueryException(DatawaveErrorCode.UNKNOWN_SERVER_ERROR, e.getMessage());
response.addException(qe);
throw new DatawaveWebApplicationException(qe, response);
}
return response;
}
use of datawave.webservice.common.exception.BadRequestException in project datawave by NationalSecurityAgency.
the class ExtendedQueryExecutorBeanTest method testCreateQueryAndNext_InvalidExpirationDate.
@Test
public void testCreateQueryAndNext_InvalidExpirationDate() throws Exception {
// Set local test input
String queryLogicName = "queryLogicName";
String query = "query";
String queryName = "queryName";
String queryVisibility = "A&B";
long currentTime = System.currentTimeMillis();
Date beginDate = new Date(currentTime - 5000);
Date endDate = new Date(currentTime - 1000);
String queryAuthorizations = "AUTH_1";
Date expirationDate = new Date(currentTime - 500);
int pagesize = 1;
int pageTimeout = -1;
Long maxResultsOverride = null;
QueryPersistence persistenceMode = QueryPersistence.PERSISTENT;
String parameters = null;
boolean trace = false;
MultivaluedMap<String, String> p = new MultivaluedMapImpl<>();
p.putAll(QueryParametersImpl.paramsToMap(queryLogicName, query, queryName, queryVisibility, beginDate, endDate, queryAuthorizations, expirationDate, pagesize, pageTimeout, maxResultsOverride, persistenceMode, parameters, trace));
// Run the test
PowerMock.replayAll();
QueryExecutorBean subject = new QueryExecutorBean();
setInternalState(subject, QueryParameters.class, new QueryParametersImpl());
setInternalState(subject, QueryMetricFactory.class, new QueryMetricFactoryImpl());
Throwable result1 = null;
try {
subject.createQueryAndNext(queryLogicName, p);
} catch (DatawaveWebApplicationException e) {
result1 = e;
}
PowerMock.verifyAll();
// Verify results
assertTrue("BadRequestException expected to have been thrown", result1 instanceof BadRequestException);
assertEquals("Thrown exception expected to have been due to invalid expiration date", "400-3", ((QueryException) result1.getCause()).getErrorCode());
}
Aggregations