X-Git-Url: https://gerrit.onap.org/r/gitweb?a=blobdiff_plain;f=src%2Fmain%2Fjava%2Forg%2Fonap%2Fcrud%2Fservice%2FAaiResourceService.java;h=afabe7eed685c2e347bbaacecc9f659b963a3bb6;hb=refs%2Fchanges%2F67%2F54967%2F3;hp=2e4464d6f8f39393b6b220cf59128ad0ec0057da;hpb=908b4693e5a0a4c2f323dbf518b35e4620f183a1;p=aai%2Fgizmo.git diff --git a/src/main/java/org/onap/crud/service/AaiResourceService.java b/src/main/java/org/onap/crud/service/AaiResourceService.java index 2e4464d..afabe7e 100644 --- a/src/main/java/org/onap/crud/service/AaiResourceService.java +++ b/src/main/java/org/onap/crud/service/AaiResourceService.java @@ -1,16 +1,15 @@ /** * ============LICENSE_START======================================================= - * Gizmo + * org.onap.aai * ================================================================================ - * Copyright © 2017 AT&T Intellectual Property. - * Copyright © 2017 Amdocs - * All rights reserved. + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017-2018 Amdocs * ================================================================================ * Licensed 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 + * 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, @@ -18,8 +17,6 @@ * See the License for the specific language governing permissions and * limitations under the License. * ============LICENSE_END========================================================= - * - * ECOMP is a trademark and service mark of AT&T Intellectual Property. */ package org.onap.crud.service; @@ -29,7 +26,6 @@ import java.util.HashSet; import java.util.Map; import java.util.Map.Entry; import java.util.Set; - import javax.security.auth.x500.X500Principal; import javax.servlet.http.HttpServletRequest; import javax.ws.rs.Consumes; @@ -40,29 +36,29 @@ import javax.ws.rs.Path; import javax.ws.rs.PathParam; import javax.ws.rs.Produces; import javax.ws.rs.core.Context; +import javax.ws.rs.core.EntityTag; import javax.ws.rs.core.HttpHeaders; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; -import javax.ws.rs.core.UriInfo; import javax.ws.rs.core.Response.Status; - +import javax.ws.rs.core.UriInfo; +import org.apache.commons.lang3.tuple.ImmutablePair; +import org.onap.aai.cl.api.Logger; +import org.onap.aai.cl.eelf.LoggerFactory; import org.onap.aai.exceptions.AAIException; import org.onap.aai.serialization.db.EdgeProperty; import org.onap.aai.serialization.db.EdgeRule; import org.onap.aai.serialization.db.EdgeRules; import org.onap.aai.serialization.db.EdgeType; -import org.openecomp.auth.Auth; -import org.onap.aai.cl.api.Logger; -import org.onap.aai.cl.eelf.LoggerFactory; +import org.onap.aaiauth.auth.Auth; import org.onap.crud.exception.CrudException; import org.onap.crud.logging.CrudServiceMsgs; import org.onap.crud.logging.LoggingUtil; import org.onap.crud.service.CrudRestService.Action; import org.onap.crud.util.CrudServiceConstants; -import org.onap.schema.RelationshipSchemaLoader; +import org.onap.schema.EdgeRulesLoader; import org.onap.schema.RelationshipSchemaValidator; import org.slf4j.MDC; - import com.google.gson.Gson; import com.google.gson.JsonElement; import com.google.gson.JsonPrimitive; @@ -77,78 +73,78 @@ public class AaiResourceService { private String mediaType = MediaType.APPLICATION_JSON; public static final String HTTP_PATCH_METHOD_OVERRIDE = "X-HTTP-Method-Override"; - + private Auth auth; - CrudGraphDataService crudGraphDataService; + AbstractGraphDataService graphDataService; Gson gson = new Gson(); - + private Logger logger = LoggerFactory.getInstance().getLogger(AaiResourceService.class.getName()); private Logger auditLogger = LoggerFactory.getInstance().getAuditLogger(AaiResourceService.class.getName()); - + public AaiResourceService() {} - + /** * Creates a new instance of the AaiResourceService. - * + * * @param crudGraphDataService - Service used for interacting with the graph. - * + * * @throws Exception */ - public AaiResourceService(CrudGraphDataService crudGraphDataService) throws Exception { - this.crudGraphDataService = crudGraphDataService; - this.auth = new Auth(CrudServiceConstants.CRD_AUTH_FILE); + public AaiResourceService(AbstractGraphDataService graphDataService) throws Exception { + this.graphDataService = graphDataService; + this.auth = new Auth(CrudServiceConstants.CRD_AUTH_FILE); } - + /** * Perform any one-time initialization required when starting the service. */ public void startup() { - + if(logger.isDebugEnabled()) { logger.debug("AaiResourceService started!"); } } - - + + /** * Creates a new relationship in the graph, automatically populating the edge * properties based on the A&AI edge rules. - * + * * @param content - Json structure describing the relationship to create. * @param type - Relationship type supplied as a URI parameter. * @param uri - Http request uri * @param headers - Http request headers * @param uriInfo - Http URI info field * @param req - Http request structure. - * + * * @return - Standard HTTP response. */ @POST @Path("/relationships/{type}/") @Consumes({MediaType.APPLICATION_JSON}) @Produces({MediaType.APPLICATION_JSON}) - public Response createRelationship(String content, - @PathParam("type") String type, + public Response createRelationship(String content, + @PathParam("type") String type, @PathParam("uri") @Encoded String uri, - @Context HttpHeaders headers, + @Context HttpHeaders headers, @Context UriInfo uriInfo, @Context HttpServletRequest req) { - + LoggingUtil.initMdcContext(req, headers); if(logger.isDebugEnabled()) { logger.debug("Incoming request..." + content); } - + Response response = null; if (validateRequest(req, uri, content, Action.POST, CrudServiceConstants.CRD_AUTH_POLICY_NAME)) { - + try { - + // Extract the edge payload from the request. - EdgePayload payload = EdgePayload.fromJson(content); - + EdgePayload payload = EdgePayload.fromJson(content); + // Do some basic validation on the payload. if (payload.getProperties() == null || payload.getProperties().isJsonNull()) { throw new CrudException("Invalid request Payload", Status.BAD_REQUEST); @@ -159,50 +155,50 @@ public class AaiResourceService { if (payload.getType() != null && !payload.getType().equals(type)) { throw new CrudException("Edge Type mismatch", Status.BAD_REQUEST); } - + // Apply the edge rules to our edge. payload = applyEdgeRulesToPayload(payload); - + if(logger.isDebugEnabled()) { - logger.debug("Creating AAI edge using version " + RelationshipSchemaLoader.getLatestSchemaVersion() ); + logger.debug("Creating AAI edge using version " + EdgeRulesLoader.getLatestSchemaVersion() ); } - + // Now, create our edge in the graph store. - String result = crudGraphDataService.addEdge(RelationshipSchemaLoader.getLatestSchemaVersion(), type, payload); - response = Response.status(Status.CREATED).entity(result).type(mediaType).build(); - + ImmutablePair result = graphDataService.addEdge(EdgeRulesLoader.getLatestSchemaVersion(), type, payload); + response = Response.status(Status.CREATED).entity(result.getValue()).tag(result.getKey()).type(mediaType).build(); + } catch (CrudException e) { response = Response.status(Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()).build(); - } + } } - + LoggingUtil.logRestRequest(logger, auditLogger, req, response); return response; } - - + + /** * Creates a new relationship in the graph, automatically populating the edge * properties based on the A&AI edge rules. - * + * * @param content - Json structure describing the relationship to create. * @param uri - Http request uri * @param headers - Http request headers * @param uriInfo - Http URI info field * @param req - Http request structure. - * + * * @return - Standard HTTP response. - * + * */ @POST @Path("/relationships/") @Consumes({MediaType.APPLICATION_JSON}) @Produces({MediaType.APPLICATION_JSON}) - public Response createRelationship(String content, - @PathParam("uri") @Encoded String uri, + public Response createRelationship(String content, + @PathParam("uri") @Encoded String uri, @Context HttpHeaders headers, - @Context UriInfo uriInfo, + @Context UriInfo uriInfo, @Context HttpServletRequest req) { LoggingUtil.initMdcContext(req, headers); @@ -213,10 +209,10 @@ public class AaiResourceService { if (validateRequest(req, uri, content, Action.POST, CrudServiceConstants.CRD_AUTH_POLICY_NAME)) { try { - + // Extract the edge payload from the request. EdgePayload payload = EdgePayload.fromJson(content); - + // Do some basic validation on the payload. if (payload.getProperties() == null || payload.getProperties().isJsonNull()) { throw new CrudException("Invalid request Payload", Status.BAD_REQUEST); @@ -227,14 +223,14 @@ public class AaiResourceService { if (payload.getType() == null || payload.getType().isEmpty()) { throw new CrudException("Missing Edge Type ", Status.BAD_REQUEST); } - + // Apply the edge rules to our edge. payload = applyEdgeRulesToPayload(payload); - + // Now, create our edge in the graph store. - String result = crudGraphDataService.addEdge(RelationshipSchemaLoader.getLatestSchemaVersion(), payload.getType(), payload); - response = Response.status(Status.CREATED).entity(result).type(mediaType).build(); - + ImmutablePair result = graphDataService.addEdge(EdgeRulesLoader.getLatestSchemaVersion(), payload.getType(), payload); + response = Response.status(Status.CREATED).entity(result.getValue()).tag(result.getKey()).type(mediaType).build(); + } catch (CrudException ce) { response = Response.status(ce.getHttpStatus()).entity(ce.getMessage()).build(); } catch (Exception e) { @@ -249,17 +245,17 @@ public class AaiResourceService { return response; } - - + + /** * Upserts a relationship into the graph, automatically populating the edge properties * based on the A&AI edge rules. The behaviour is as follows: *

- *

  • If no relationship with the supplied identifier already exists, then a new relationship + *
  • If no relationship with the supplied identifier already exists, then a new relationship * is created with that id.
    - *
  • If a relationship with the supplied id DOES exist, then it is replaced with the supplied + *
  • If a relationship with the supplied id DOES exist, then it is replaced with the supplied * content. - * + * * @param content - Json structure describing the relationship to create. * @param type - Relationship type supplied as a URI parameter. * @param id - Edge identifier. @@ -267,19 +263,19 @@ public class AaiResourceService { * @param headers - Http request headers * @param uriInfo - Http URI info field * @param req - Http request structure. - * + * * @return - Standard HTTP response. */ @PUT @Path("/relationships/{type}/{id}") @Consumes({MediaType.APPLICATION_JSON}) @Produces({MediaType.APPLICATION_JSON}) - public Response upsertEdge(String content, - @PathParam("type") String type, + public Response upsertEdge(String content, + @PathParam("type") String type, @PathParam("id") String id, - @PathParam("uri") @Encoded String uri, + @PathParam("uri") @Encoded String uri, @Context HttpHeaders headers, - @Context UriInfo uriInfo, + @Context UriInfo uriInfo, @Context HttpServletRequest req) { LoggingUtil.initMdcContext(req, headers); @@ -287,12 +283,12 @@ public class AaiResourceService { Response response = null; if (validateRequest(req, uri, content, Action.PUT, CrudServiceConstants.CRD_AUTH_POLICY_NAME)) { - + try { - + // Extract the edge payload from the request. EdgePayload payload = EdgePayload.fromJson(content); - + // Do some basic validation on the payload. if (payload.getProperties() == null || payload.getProperties().isJsonNull()) { throw new CrudException("Invalid request Payload", Status.BAD_REQUEST); @@ -300,47 +296,45 @@ public class AaiResourceService { if (payload.getId() != null && !payload.getId().equals(id)) { throw new CrudException("ID Mismatch", Status.BAD_REQUEST); } - + // Apply the edge rules to our edge. payload = applyEdgeRulesToPayload(payload); - - String result; + ImmutablePair result; if (headers.getRequestHeaders().getFirst(HTTP_PATCH_METHOD_OVERRIDE) != null && headers.getRequestHeaders().getFirst(HTTP_PATCH_METHOD_OVERRIDE).equalsIgnoreCase("PATCH")) { - result = crudGraphDataService.patchEdge(RelationshipSchemaLoader.getLatestSchemaVersion(), id, type, payload); + result = graphDataService.patchEdge(EdgeRulesLoader.getLatestSchemaVersion(), id, type, payload); + response = Response.status(Status.OK).entity(result.getValue()).type(mediaType).tag(result.getKey()).build(); } else { - - result = crudGraphDataService.updateEdge(RelationshipSchemaLoader.getLatestSchemaVersion(), id, type, payload); + result = graphDataService.updateEdge(EdgeRulesLoader.getLatestSchemaVersion(), id, type, payload); + response = Response.status(Status.OK).entity(result.getValue()).type(mediaType).tag(result.getKey()).build(); } - response = Response.status(Status.OK).entity(result).type(mediaType).build(); - } catch (CrudException ce) { response = Response.status(ce.getHttpStatus()).entity(ce.getMessage()).build(); } catch (Exception e) { response = Response.status(Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()).build(); } - + } else { - + response = Response.status(Status.FORBIDDEN).entity(content) .type(MediaType.APPLICATION_JSON).build(); } - + LoggingUtil.logRestRequest(logger, auditLogger, req, response); return response; } - - + + /** - * Retrieves the properties defined in the edge rules for a relationship between the + * Retrieves the properties defined in the edge rules for a relationship between the * supplied vertex types. - * + * * @param sourceVertexType - Type of source vertex for the relationship. * @param targetVertexType - Type of target vertex for the relationship. - * + * * @return - The defined properties for the relationship type. - * + * * @throws CrudException */ private Map getEdgeRuleProperties(String sourceVertexType, String targetVertexType) throws CrudException { @@ -348,119 +342,119 @@ public class AaiResourceService { if(logger.isDebugEnabled()) { logger.debug("Lookup db edge rules for " + sourceVertexType + " -> " + targetVertexType); } - + EdgeRules rules = EdgeRules.getInstance(); EdgeRule rule; try { - + if(logger.isDebugEnabled()) { logger.debug("Lookup by edge type TREE"); } - + // We have no way of knowing in advance whether our relationship is considered to // be a tree or cousing relationship, so try looking it up as a tree type first. rule = rules.getEdgeRule(EdgeType.TREE, sourceVertexType, targetVertexType); - + } catch (AAIException e) { try { - + if(logger.isDebugEnabled()) { logger.debug("Lookup by edge type COUSIN"); } - + // If we are here, then our lookup by 'tree' type failed, so try looking it up // as a 'cousin' relationship. rule = rules.getEdgeRule(EdgeType.COUSIN, sourceVertexType, targetVertexType); - + } catch (AAIException e1) { - + // If we're here then we failed to find edge rules for this relationship. Time to // give up... throw new CrudException("No edge rules for " + sourceVertexType + " -> " + targetVertexType, Status.NOT_FOUND); } } catch (Exception e) { - - throw new CrudException("General failure getting edge rule properties - " + + + throw new CrudException("General failure getting edge rule properties - " + e.getMessage(), Status.INTERNAL_SERVER_ERROR); } - + return rule.getEdgeProperties(); } - - + + /** * This method takes an inbound edge request payload, looks up the edge rules for the * sort of relationship defined in the payload, and automatically applies the defined * edge properties to it. - * + * * @param payload - The original edge request payload - * + * * @return - An updated edge request payload, with the properties defined in the edge * rules automatically populated. - * + * * @throws CrudException */ public EdgePayload applyEdgeRulesToPayload(EdgePayload payload) throws CrudException { - + // Extract the types for both the source and target vertices. String srcType = RelationshipSchemaValidator.vertexTypeFromUri(payload.getSource()); String tgtType = RelationshipSchemaValidator.vertexTypeFromUri(payload.getTarget()); // Now, get the default properties for this edge based on the edge rules definition... Map props = getEdgeRuleProperties(srcType, tgtType); - + // ...and merge them with any custom properties provided in the request. JsonElement mergedProperties = mergeProperties(payload.getProperties(), props); payload.setProperties(mergedProperties); - - + + if(logger.isDebugEnabled()) { logger.debug("Edge properties after applying rules for '" + srcType + " -> " + tgtType + "': " + mergedProperties); } - + return payload; } - - + + /** * Given a set of edge properties extracted from an edge request payload and a set of properties * taken from the db edge rules, this method merges them into one set of properties. *

    * If the client has attempted to override the defined value for a property in the db edge rules * then the request will be rejected as invalid. - * + * * @param propertiesFromRequest - Set of properties from the edge request. * @param propertyDefaults - Set of properties from the db edge rules. - * + * * @return - A merged set of properties. - * + * * @throws CrudException */ public JsonElement mergeProperties(JsonElement propertiesFromRequest, Map propertyDefaults) throws CrudException { - + // Convert the properties from the edge payload into something we can // manipulate. Set> properties = new HashSet>(); properties.addAll(propertiesFromRequest.getAsJsonObject().entrySet()); - + Set propertyKeys = new HashSet(); for(Map.Entry property : properties) { propertyKeys.add(property.getKey()); } - + // Now, merge in the properties specified in the Db Edge Rules. for(EdgeProperty defProperty : propertyDefaults.keySet()) { - + // If the edge rules property was explicitly specified by the // client then we will reject the request... if(!propertyKeys.contains(defProperty.toString())) { properties.add(new AbstractMap.SimpleEntry(defProperty.toString(), - (JsonElement)(new JsonPrimitive(propertyDefaults.get(defProperty))))); - + (new JsonPrimitive(propertyDefaults.get(defProperty))))); + } else { - throw new CrudException("Property " + defProperty + " defined in db edge rules can not be overriden by the client.", + throw new CrudException("Property " + defProperty + " defined in db edge rules can not be overriden by the client.", Status.BAD_REQUEST); - } + } } Object[] propArray = properties.toArray(); @@ -468,7 +462,7 @@ public class AaiResourceService { sb.append("{"); boolean first=true; for(int i=0; i entry = (Entry) propArray[i]; if(!first) { sb.append(","); @@ -477,7 +471,7 @@ public class AaiResourceService { first=false; } sb.append("}"); - + // We're done. Return the result as a JsonElement. return gson.fromJson(sb.toString(), JsonElement.class); } @@ -485,45 +479,45 @@ public class AaiResourceService { /** * Invokes authentication validation on an incoming HTTP request. - * + * * @param req - The HTTP request. * @param uri - HTTP URI * @param content - Payload of the HTTP request. * @param action - What HTTP action is being performed (GET/PUT/POST/PATCH/DELETE) * @param authPolicyFunctionName - Policy function being invoked. - * + * * @return true - if the request passes validation, * false - otherwise. */ - protected boolean validateRequest(HttpServletRequest req, - String uri, + protected boolean validateRequest(HttpServletRequest req, + String uri, String content, - Action action, + Action action, String authPolicyFunctionName) { try { String cipherSuite = (String) req.getAttribute("javax.servlet.request.cipher_suite"); String authUser = null; if (cipherSuite != null) { - + X509Certificate[] certChain = (X509Certificate[]) req.getAttribute("javax.servlet.request.X509Certificate"); X509Certificate clientCert = certChain[0]; X500Principal subjectDn = clientCert.getSubjectX500Principal(); authUser = subjectDn.toString(); } - + return this.auth.validateRequest(authUser.toLowerCase(), action.toString() + ":" + authPolicyFunctionName); - + } catch (Exception e) { logResult(action, uri, e); return false; } } - + protected void logResult(Action op, String uri, Exception e) { - logger.error(CrudServiceMsgs.EXCEPTION_DURING_METHOD_CALL, - op.toString(), - uri, + logger.error(CrudServiceMsgs.EXCEPTION_DURING_METHOD_CALL, + op.toString(), + uri, e.getStackTrace().toString()); // Clear the MDC context so that no other transaction inadvertently