private Response executeVertexExtension(final String graphName, final String id, final HttpMethod httpMethodRequested) {
final Vertex vertex = this.getRexsterApplicationGraph(graphName).getGraph().getVertex(id);
ExtensionResponse extResponse;
ExtensionMethod methodToCall;
final ExtensionSegmentSet extensionSegmentSet = parseUriForExtensionSegment(graphName, ExtensionPoint.VERTEX);
// determine if the namespace and extension are enabled for this graph
final RexsterApplicationGraph rag = this.getRexsterApplicationGraph(graphName);
if (rag.isExtensionAllowed(extensionSegmentSet)) {
final Object returnValue;
// namespace was allowed so try to run the extension
try {
// look for the extension as loaded through serviceloader
final List<RexsterExtension> rexsterExtensions;
try {
rexsterExtensions = findExtensionClasses(extensionSegmentSet);
} catch (ServiceConfigurationError sce) {
logger.error("ServiceLoader could not find a class referenced in com.tinkerpop.rexster.extension.RexsterExtension.");
final JSONObject error = generateErrorObject(
"Class specified in com.tinkerpop.rexster.extension.RexsterExtension could not be found.",
sce);
throw new WebApplicationException(Response.status(Status.NOT_FOUND).entity(error).build());
}
if (rexsterExtensions == null || rexsterExtensions.size() == 0) {
// extension was not found for some reason
logger.error("The [" + extensionSegmentSet + "] extension was not found for [" + graphName + "]. Check com.tinkerpop.rexster.extension.RexsterExtension file in META-INF.services.");
final JSONObject error = generateErrorObject(
"The [" + extensionSegmentSet + "] extension was not found for [" + graphName + "]");
throw new WebApplicationException(Response.status(Status.NOT_FOUND).entity(error).build());
}
// look up the method on the extension that needs to be called.
methodToCall = findExtensionMethod(rexsterExtensions, ExtensionPoint.VERTEX, extensionSegmentSet.getExtensionMethod(), httpMethodRequested);
if (methodToCall == null) {
// extension method was not found for some reason
if (httpMethodRequested == HttpMethod.OPTIONS) {
// intercept the options call and return the standard business
// no need to stop the transaction here
return buildOptionsResponse();
}
logger.error("The [" + extensionSegmentSet + "] extension was not found for [" + graphName + "] with a HTTP method of [" + httpMethodRequested.name() + "]. Check com.tinkerpop.rexster.extension.RexsterExtension file in META-INF.services.");
final JSONObject error = generateErrorObject(
"The [" + extensionSegmentSet + "] extension was not found for [" + graphName + "] with a HTTP method of [" + httpMethodRequested.name() + "]");
throw new WebApplicationException(Response.status(Status.NOT_FOUND).entity(error).build());
}
// found the method...time to do work
returnValue = invokeExtension(rag, methodToCall, vertex);
} catch (WebApplicationException wae) {
// already logged this...just throw it up.
rag.tryRollback();
throw wae;
} catch (Exception ex) {
logger.error("Dynamic invocation of the [" + extensionSegmentSet + "] extension failed.", ex);
if (ex.getCause() != null) {
final Throwable cause = ex.getCause();
logger.error("It would be smart to trap this this exception within the extension and supply a good response to the user:" + cause.getMessage(), cause);
}
rag.tryRollback();
final JSONObject error = generateErrorObjectJsonFail(ex);
throw new WebApplicationException(Response.status(Status.INTERNAL_SERVER_ERROR).entity(error).build());
}
if (returnValue instanceof ExtensionResponse) {
extResponse = (ExtensionResponse) returnValue;
if (extResponse.isErrorResponse()) {
// an error was raised within the extension. pass it back out as an error.
logger.warn("The [" + extensionSegmentSet + "] extension raised an error response.");
if (methodToCall.getExtensionDefinition().autoCommitTransaction()) {
rag.tryRollback();
}
throw new WebApplicationException(Response.fromResponse(extResponse.getJerseyResponse()).build());
}
if (methodToCall.getExtensionDefinition().autoCommitTransaction()) {
rag.tryCommit();
}
} else {
// extension method is not returning the correct type...needs to be an ExtensionResponse
logger.error("The [" + extensionSegmentSet + "] extension does not return an ExtensionResponse.");
final JSONObject error = generateErrorObject(
"The [" + extensionSegmentSet + "] extension does not return an ExtensionResponse.");
rag.tryRollback();
throw new WebApplicationException(Response.status(Status.INTERNAL_SERVER_ERROR).entity(error).build());
}
} else {
// namespace was not allowed
logger.error("The [" + extensionSegmentSet + "] extension was not configured for [" + graphName + "]");
final JSONObject error = generateErrorObject(
"The [" + extensionSegmentSet + "] extension was not configured for [" + graphName + "]");
throw new WebApplicationException(Response.status(Status.INTERNAL_SERVER_ERROR).entity(error).build());
}
String mediaType = MediaType.APPLICATION_JSON;
if (methodToCall != null) {
mediaType = methodToCall.getExtensionDefinition().produces();
extResponse = tryAppendRexsterAttributesIfJson(extResponse, methodToCall, mediaType);
}
return Response.fromResponse(extResponse.getJerseyResponse()).type(mediaType).build();
}