Consolidate syncrounous and asyncronous APIs
[aai/gizmo.git] / src / main / java / org / onap / crud / service / CrudRestService.java
1 /**
2  * ============LICENSE_START=======================================================
3  * Gizmo
4  * ================================================================================
5  * Copyright © 2017 AT&T Intellectual Property.
6  * Copyright © 2017 Amdocs
7  * All rights reserved.
8  * ================================================================================
9  * Licensed under the Apache License, Version 2.0 (the "License");
10  * you may not use this file except in compliance with the License.
11  * You may obtain a copy of the License at
12  *
13  *    http://www.apache.org/licenses/LICENSE-2.0
14  *
15  * Unless required by applicable law or agreed to in writing, software
16  * distributed under the License is distributed on an "AS IS" BASIS,
17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18  * See the License for the specific language governing permissions and
19  * limitations under the License.
20  * ============LICENSE_END=========================================================
21  *
22  * ECOMP is a trademark and service mark of AT&T Intellectual Property.
23  */
24 package org.onap.crud.service;
25
26 import java.security.cert.X509Certificate;
27 import java.util.ArrayList;
28 import java.util.HashMap;
29 import java.util.List;
30 import java.util.Map;
31
32 import javax.security.auth.x500.X500Principal;
33 import javax.servlet.http.HttpServletRequest;
34 import javax.ws.rs.Consumes;
35 import javax.ws.rs.DELETE;
36 import javax.ws.rs.Encoded;
37 import javax.ws.rs.GET;
38 import javax.ws.rs.POST;
39 import javax.ws.rs.PUT;
40 import javax.ws.rs.Path;
41 import javax.ws.rs.PathParam;
42 import javax.ws.rs.Produces;
43 import javax.ws.rs.core.Context;
44 import javax.ws.rs.core.HttpHeaders;
45 import javax.ws.rs.core.MediaType;
46 import javax.ws.rs.core.Response;
47 import javax.ws.rs.core.Response.Status;
48 import javax.ws.rs.core.UriInfo;
49
50 import org.apache.cxf.jaxrs.ext.PATCH;
51 import org.onap.aaiauth.auth.Auth;
52 import org.onap.aai.cl.api.Logger;
53 import org.onap.aai.cl.eelf.LoggerFactory;
54 import org.onap.crud.exception.CrudException;
55 import org.onap.crud.logging.CrudServiceMsgs;
56 import org.onap.crud.logging.LoggingUtil;
57 import org.onap.crud.util.CrudServiceConstants;
58 import org.slf4j.MDC;
59
60 import com.google.gson.JsonElement;
61
62 public class CrudRestService {
63
64   private AbstractGraphDataService graphDataService;
65   Logger logger = LoggerFactory.getInstance().getLogger(CrudRestService.class.getName());
66   Logger auditLogger = LoggerFactory.getInstance().getAuditLogger(CrudRestService.class.getName());
67   private Auth auth;
68
69   private String mediaType = MediaType.APPLICATION_JSON;
70   public static final String HTTP_PATCH_METHOD_OVERRIDE = "X-HTTP-Method-Override";
71
72   public CrudRestService(AbstractGraphDataService graphDataService) throws Exception {
73     this.graphDataService = graphDataService;
74     this.auth = new Auth(CrudServiceConstants.CRD_AUTH_FILE);
75   }
76
77   public enum Action {
78     POST, GET, PUT, DELETE, PATCH
79   }
80
81   public void startup() {
82
83   }
84
85   @GET
86   @Path("/{version}/{type}/{id}")
87   @Consumes({ MediaType.APPLICATION_JSON })
88   @Produces({ MediaType.APPLICATION_JSON })
89   public Response getVertex(String content, @PathParam("version") String version, @PathParam("type") String type,
90       @PathParam("id") String id, @PathParam("uri") @Encoded String uri, @Context HttpHeaders headers,
91       @Context UriInfo uriInfo, @Context HttpServletRequest req) {
92     LoggingUtil.initMdcContext(req, headers);
93
94     logger.debug("Incoming request..." + content);
95     Response response = null;
96
97     if (validateRequest(req, uri, content, Action.GET, CrudServiceConstants.CRD_AUTH_POLICY_NAME)) {
98
99       try {
100         String result = graphDataService.getVertex(version, id, type);
101         response = Response.status(Status.OK).entity(result).type(mediaType).build();
102       } catch (CrudException ce) {
103         response = Response.status(ce.getHttpStatus()).entity(ce.getMessage()).build();
104       } catch (Exception e) {
105         response = Response.status(Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()).build();
106       }
107     } else {
108       response = Response.status(Status.FORBIDDEN).entity(content).type(MediaType.APPLICATION_JSON).build();
109     }
110
111     LoggingUtil.logRestRequest(logger, auditLogger, req, response);
112     return response;
113   }
114
115   @GET
116   @Path("/{version}/{type}/")
117   @Consumes({ MediaType.APPLICATION_JSON })
118   @Produces({ MediaType.APPLICATION_JSON })
119   public Response getVertices(String content, @PathParam("version") String version, @PathParam("type") String type,
120       @PathParam("uri") @Encoded String uri, @Context HttpHeaders headers, @Context UriInfo uriInfo,
121       @Context HttpServletRequest req) {
122
123     LoggingUtil.initMdcContext(req, headers);
124
125     logger.debug("Incoming request..." + content);
126     Response response = null;
127     if (validateRequest(req, uri, content, Action.GET, CrudServiceConstants.CRD_AUTH_POLICY_NAME)) {
128
129       Map<String, String> filter = new HashMap<String, String>();
130       for (Map.Entry<String, List<String>> e : uriInfo.getQueryParameters().entrySet()) {
131         filter.put(e.getKey(), e.getValue().get(0));
132       }
133
134       try {
135         String result = graphDataService.getVertices(version, type, filter);
136         response = Response.status(Status.OK).entity(result).type(mediaType).build();
137       } catch (CrudException ce) {
138         response = Response.status(ce.getHttpStatus()).entity(ce.getMessage()).build();
139       } catch (Exception e) {
140         response = Response.status(Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()).build();
141       }
142     } else {
143       response = Response.status(Status.FORBIDDEN).entity(content).type(MediaType.APPLICATION_JSON).build();
144     }
145
146     LoggingUtil.logRestRequest(logger, auditLogger, req, response);
147     return response;
148   }
149
150   @GET
151   @Path("/relationships/{version}/{type}/{id}")
152   @Consumes({ MediaType.APPLICATION_JSON })
153   @Produces({ MediaType.APPLICATION_JSON })
154   public Response getEdge(String content, @PathParam("version") String version, @PathParam("type") String type,
155       @PathParam("id") String id, @PathParam("uri") @Encoded String uri, @Context HttpHeaders headers,
156       @Context UriInfo uriInfo, @Context HttpServletRequest req) {
157     LoggingUtil.initMdcContext(req, headers);
158
159     logger.debug("Incoming request..." + content);
160     Response response = null;
161
162     if (validateRequest(req, uri, content, Action.GET, CrudServiceConstants.CRD_AUTH_POLICY_NAME)) {
163
164       try {
165
166         String result = graphDataService.getEdge(version, id, type);
167         response = Response.status(Status.OK).entity(result).type(mediaType).build();
168       } catch (CrudException ce) {
169         response = Response.status(ce.getHttpStatus()).entity(ce.getMessage()).build();
170       } catch (Exception e) {
171         response = Response.status(Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()).build();
172       }
173     } else {
174       response = Response.status(Status.FORBIDDEN).entity(content).type(MediaType.APPLICATION_JSON).build();
175     }
176
177     LoggingUtil.logRestRequest(logger, auditLogger, req, response);
178     return response;
179   }
180
181   @GET
182   @Path("/relationships/{version}/{type}/")
183   @Consumes({ MediaType.APPLICATION_JSON })
184   @Produces({ MediaType.APPLICATION_JSON })
185   public Response getEdges(String content, @PathParam("version") String version, @PathParam("type") String type,
186       @PathParam("uri") @Encoded String uri, @Context HttpHeaders headers, @Context UriInfo uriInfo,
187       @Context HttpServletRequest req) {
188
189     LoggingUtil.initMdcContext(req, headers);
190
191     logger.debug("Incoming request..." + content);
192     Response response = null;
193
194     if (validateRequest(req, uri, content, Action.GET, CrudServiceConstants.CRD_AUTH_POLICY_NAME)) {
195
196       Map<String, String> filter = new HashMap<String, String>();
197       for (Map.Entry<String, List<String>> e : uriInfo.getQueryParameters().entrySet()) {
198         filter.put(e.getKey(), e.getValue().get(0));
199       }
200
201       try {
202         String result = graphDataService.getEdges(version, type, filter);
203         response = Response.status(Status.OK).entity(result).type(mediaType).build();
204       } catch (CrudException ce) {
205         response = Response.status(ce.getHttpStatus()).entity(ce.getMessage()).build();
206       } catch (Exception e) {
207         response = Response.status(Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()).build();
208       }
209     } else {
210       response = Response.status(Status.FORBIDDEN).entity(content).type(MediaType.APPLICATION_JSON).build();
211
212     }
213
214     LoggingUtil.logRestRequest(logger, auditLogger, req, response);
215     return response;
216   }
217
218   @PUT
219   @Path("/relationships/{version}/{type}/{id}")
220   @Consumes({ MediaType.APPLICATION_JSON })
221   @Produces({ MediaType.APPLICATION_JSON })
222   public Response updateEdge(String content, @PathParam("version") String version, @PathParam("type") String type,
223       @PathParam("id") String id, @PathParam("uri") @Encoded String uri, @Context HttpHeaders headers,
224       @Context UriInfo uriInfo, @Context HttpServletRequest req) {
225
226     LoggingUtil.initMdcContext(req, headers);
227
228     logger.debug("Incoming request..." + content);
229     Response response = null;
230
231     if (validateRequest(req, uri, content, Action.PUT, CrudServiceConstants.CRD_AUTH_POLICY_NAME)) {
232
233       try {
234         EdgePayload payload = EdgePayload.fromJson(content);
235         if (payload.getProperties() == null || payload.getProperties().isJsonNull()) {
236           throw new CrudException("Invalid request Payload", Status.BAD_REQUEST);
237         }
238         if (payload.getId() != null && !payload.getId().equals(id)) {
239           throw new CrudException("ID Mismatch", Status.BAD_REQUEST);
240         }
241         String result;
242
243         if (headers.getRequestHeaders().getFirst(HTTP_PATCH_METHOD_OVERRIDE) != null
244             && headers.getRequestHeaders().getFirst(HTTP_PATCH_METHOD_OVERRIDE).equalsIgnoreCase("PATCH")) {
245           result = graphDataService.patchEdge(version, id, type, payload);
246         } else {
247
248           result = graphDataService.updateEdge(version, id, type, payload);
249         }
250
251         response = Response.status(Status.OK).entity(result).type(mediaType).build();
252       } catch (CrudException ce) {
253         response = Response.status(ce.getHttpStatus()).entity(ce.getMessage()).build();
254       } catch (Exception e) {
255         response = Response.status(Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()).build();
256       }
257     } else {
258       response = Response.status(Status.FORBIDDEN).entity(content).type(MediaType.APPLICATION_JSON).build();
259
260     }
261
262     LoggingUtil.logRestRequest(logger, auditLogger, req, response);
263     return response;
264   }
265
266   @PATCH
267   @Path("/relationships/{version}/{type}/{id}")
268   @Consumes({ "application/merge-patch+json" })
269   @Produces({ MediaType.APPLICATION_JSON })
270   public Response patchEdge(String content, @PathParam("version") String version, @PathParam("type") String type,
271       @PathParam("id") String id, @PathParam("uri") @Encoded String uri, @Context HttpHeaders headers,
272       @Context UriInfo uriInfo, @Context HttpServletRequest req) {
273
274     LoggingUtil.initMdcContext(req, headers);
275
276     logger.debug("Incoming request..." + content);
277     Response response = null;
278     if (validateRequest(req, uri, content, Action.PATCH, CrudServiceConstants.CRD_AUTH_POLICY_NAME)) {
279
280       try {
281         EdgePayload payload = EdgePayload.fromJson(content);
282         if (payload.getProperties() == null || payload.getProperties().isJsonNull()) {
283           throw new CrudException("Invalid request Payload", Status.BAD_REQUEST);
284         }
285         if (payload.getId() != null && !payload.getId().equals(id)) {
286           throw new CrudException("ID Mismatch", Status.BAD_REQUEST);
287         }
288
289         String result = graphDataService.patchEdge(version, id, type, payload);
290         response = Response.status(Status.OK).entity(result).type(mediaType).build();
291       } catch (CrudException ce) {
292         response = Response.status(ce.getHttpStatus()).entity(ce.getMessage()).build();
293       } catch (Exception e) {
294         response = Response.status(Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()).build();
295       }
296     } else {
297       response = Response.status(Status.FORBIDDEN).entity(content).type(MediaType.APPLICATION_JSON).build();
298     }
299
300     LoggingUtil.logRestRequest(logger, auditLogger, req, response);
301     return response;
302   }
303
304   @PUT
305   @Path("/{version}/{type}/{id}")
306   @Consumes({ MediaType.APPLICATION_JSON })
307   @Produces({ MediaType.APPLICATION_JSON })
308   public Response updateVertex(String content, @PathParam("version") String version, @PathParam("type") String type,
309       @PathParam("id") String id, @PathParam("uri") @Encoded String uri, @Context HttpHeaders headers,
310       @Context UriInfo uriInfo, @Context HttpServletRequest req) {
311
312     LoggingUtil.initMdcContext(req, headers);
313
314     logger.debug("Incoming request..." + content);
315     Response response = null;
316
317     if (validateRequest(req, uri, content, Action.PUT, CrudServiceConstants.CRD_AUTH_POLICY_NAME)) {
318
319       try {
320         VertexPayload payload = VertexPayload.fromJson(content);
321         if (payload.getProperties() == null || payload.getProperties().isJsonNull()) {
322           throw new CrudException("Invalid request Payload", Status.BAD_REQUEST);
323         }
324         if (payload.getId() != null && !payload.getId().equals(id)) {
325           throw new CrudException("ID Mismatch", Status.BAD_REQUEST);
326         }
327         String result;
328         if (headers.getRequestHeaders().getFirst(HTTP_PATCH_METHOD_OVERRIDE) != null
329             && headers.getRequestHeaders().getFirst(HTTP_PATCH_METHOD_OVERRIDE).equalsIgnoreCase("PATCH")) {
330           result = graphDataService.patchVertex(version, id, type, payload);
331         } else {
332
333           result = graphDataService.updateVertex(version, id, type, payload);
334         }
335         response = Response.status(Status.OK).entity(result).type(mediaType).build();
336       } catch (CrudException ce) {
337         response = Response.status(ce.getHttpStatus()).entity(ce.getMessage()).build();
338       } catch (Exception e) {
339         response = Response.status(Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()).build();
340       }
341     } else {
342       response = Response.status(Status.FORBIDDEN).entity(content).type(MediaType.APPLICATION_JSON).build();
343     }
344
345     LoggingUtil.logRestRequest(logger, auditLogger, req, response);
346     return response;
347   }
348
349   @PATCH
350   @Path("/{version}/{type}/{id}")
351   @Consumes({ "application/merge-patch+json" })
352   @Produces({ MediaType.APPLICATION_JSON })
353   public Response patchVertex(String content, @PathParam("version") String version, @PathParam("type") String type,
354       @PathParam("id") String id, @PathParam("uri") @Encoded String uri, @Context HttpHeaders headers,
355       @Context UriInfo uriInfo, @Context HttpServletRequest req) {
356
357     LoggingUtil.initMdcContext(req, headers);
358
359     logger.debug("Incoming request..." + content);
360     Response response = null;
361
362     if (validateRequest(req, uri, content, Action.PATCH, CrudServiceConstants.CRD_AUTH_POLICY_NAME)) {
363       try {
364         VertexPayload payload = VertexPayload.fromJson(content);
365         if (payload.getProperties() == null || payload.getProperties().isJsonNull()) {
366           throw new CrudException("Invalid request Payload", Status.BAD_REQUEST);
367         }
368         if (payload.getId() != null && !payload.getId().equals(id)) {
369           throw new CrudException("ID Mismatch", Status.BAD_REQUEST);
370         }
371
372         String result = graphDataService.patchVertex(version, id, type, payload);
373         response = Response.status(Status.OK).entity(result).type(mediaType).build();
374       } catch (CrudException ce) {
375         response = Response.status(ce.getHttpStatus()).entity(ce.getMessage()).build();
376       } catch (Exception e) {
377         response = Response.status(Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()).build();
378       }
379     } else {
380       response = Response.status(Status.FORBIDDEN).entity(content).type(MediaType.APPLICATION_JSON).build();
381     }
382
383     LoggingUtil.logRestRequest(logger, auditLogger, req, response);
384     return response;
385   }
386
387   @POST
388   @Path("/{version}/{type}/")
389   @Consumes({ MediaType.APPLICATION_JSON })
390   @Produces({ MediaType.APPLICATION_JSON })
391   public Response addVertex(String content, @PathParam("version") String version, @PathParam("type") String type,
392       @PathParam("uri") @Encoded String uri, @Context HttpHeaders headers, @Context UriInfo uriInfo,
393       @Context HttpServletRequest req) {
394
395     LoggingUtil.initMdcContext(req, headers);
396
397     logger.debug("Incoming request..." + content);
398     Response response = null;
399
400     if (validateRequest(req, uri, content, Action.POST, CrudServiceConstants.CRD_AUTH_POLICY_NAME)) {
401
402       try {
403         VertexPayload payload = VertexPayload.fromJson(content);
404         if (payload.getProperties() == null || payload.getProperties().isJsonNull()) {
405           throw new CrudException("Invalid request Payload", Status.BAD_REQUEST);
406         }
407         if (payload.getId() != null) {
408           throw new CrudException("ID specified , use Http PUT to update Vertex", Status.BAD_REQUEST);
409         }
410
411         if (payload.getType() != null && !payload.getType().equals(type)) {
412           throw new CrudException("Vertex Type mismatch", Status.BAD_REQUEST);
413         }
414
415         String result = graphDataService.addVertex(version, type, payload);
416         response = Response.status(Status.CREATED).entity(result).type(mediaType).build();
417       } catch (CrudException ce) {
418         response = Response.status(ce.getHttpStatus()).entity(ce.getMessage()).build();
419       } catch (Exception e) {
420         response = Response.status(Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()).build();
421       }
422     } else {
423       response = Response.status(Status.FORBIDDEN).entity(content).type(MediaType.APPLICATION_JSON).build();
424     }
425
426     LoggingUtil.logRestRequest(logger, auditLogger, req, response);
427     return response;
428   }
429
430   private void validateBulkPayload(BulkPayload payload) throws CrudException {
431     List<String> vertices = new ArrayList<String>();
432     List<String> edges = new ArrayList<String>();
433
434     for (JsonElement v : payload.getObjects()) {
435       List<Map.Entry<String, JsonElement>> entries = new ArrayList<Map.Entry<String, JsonElement>>(
436           v.getAsJsonObject().entrySet());
437
438       if (entries.size() != 2) {
439         throw new CrudException("", Status.BAD_REQUEST);
440       }
441       Map.Entry<String, JsonElement> opr = entries.get(0);
442       Map.Entry<String, JsonElement> item = entries.get(1);
443
444       if (vertices.contains(item.getKey())) {
445         throw new CrudException("duplicate vertex in payload: " + item.getKey(), Status.BAD_REQUEST);
446       }
447       VertexPayload vertexPayload = VertexPayload.fromJson(item.getValue().getAsJsonObject().toString());
448       if (vertexPayload.getType() == null) {
449         throw new CrudException("Vertex Type cannot be null for: " + item.getKey(), Status.BAD_REQUEST);
450       }
451
452       if (!opr.getKey().equalsIgnoreCase("operation")) {
453         throw new CrudException("operation missing in item: " + item.getKey(), Status.BAD_REQUEST);
454       }
455
456       if (!opr.getValue().getAsString().equalsIgnoreCase("add")
457           && !opr.getValue().getAsString().equalsIgnoreCase("modify")
458           && !opr.getValue().getAsString().equalsIgnoreCase("delete")) {
459         throw new CrudException("Invalid operation at item: " + item.getKey(), Status.BAD_REQUEST);
460       }
461       // check if ID is populate for modify/delete operation
462       if ((opr.getValue().getAsString().equalsIgnoreCase("modify")
463           || opr.getValue().getAsString().equalsIgnoreCase("delete")) && (vertexPayload.getId() == null)) {
464
465         throw new CrudException("Mising ID at item: " + item.getKey(), Status.BAD_REQUEST);
466
467       }
468
469       vertices.add(item.getKey());
470     }
471
472     for (JsonElement v : payload.getRelationships()) {
473       List<Map.Entry<String, JsonElement>> entries = new ArrayList<Map.Entry<String, JsonElement>>(
474           v.getAsJsonObject().entrySet());
475
476       if (entries.size() != 2) {
477         throw new CrudException("", Status.BAD_REQUEST);
478       }
479       Map.Entry<String, JsonElement> opr = entries.get(0);
480       Map.Entry<String, JsonElement> item = entries.get(1);
481
482       if (edges.contains(item.getKey())) {
483         throw new CrudException("duplicate Edge in payload: " + item.getKey(), Status.BAD_REQUEST);
484       }
485
486       EdgePayload edgePayload = EdgePayload.fromJson(item.getValue().getAsJsonObject().toString());
487
488       if (edgePayload.getType() == null) {
489         throw new CrudException("Edge Type cannot be null for: " + item.getKey(), Status.BAD_REQUEST);
490       }
491
492       if (!opr.getKey().equalsIgnoreCase("operation")) {
493         throw new CrudException("operation missing in item: " + item.getKey(), Status.BAD_REQUEST);
494       }
495
496       if (!opr.getValue().getAsString().equalsIgnoreCase("add")
497           && !opr.getValue().getAsString().equalsIgnoreCase("modify")
498           && !opr.getValue().getAsString().equalsIgnoreCase("delete")) {
499         throw new CrudException("Invalid operation at item: " + item.getKey(), Status.BAD_REQUEST);
500       }
501       // check if ID is populate for modify/delete operation
502       if ((edgePayload.getId() == null) && (opr.getValue().getAsString().equalsIgnoreCase("modify")
503           || opr.getValue().getAsString().equalsIgnoreCase("delete"))) {
504
505         throw new CrudException("Mising ID at item: " + item.getKey(), Status.BAD_REQUEST);
506
507       }
508       if (opr.getValue().getAsString().equalsIgnoreCase("add")) {
509         if (edgePayload.getSource() == null || edgePayload.getTarget() == null) {
510           throw new CrudException("Source/Target cannot be null for edge: " + item.getKey(), Status.BAD_REQUEST);
511         }
512         if (edgePayload.getSource().startsWith("$") && !vertices.contains(edgePayload.getSource().substring(1))) {
513           throw new CrudException(
514               "Source Vertex " + edgePayload.getSource().substring(1) + " not found for Edge: " + item.getKey(),
515               Status.BAD_REQUEST);
516         }
517
518         if (edgePayload.getTarget().startsWith("$") && !vertices.contains(edgePayload.getTarget().substring(1))) {
519           throw new CrudException(
520               "Target Vertex " + edgePayload.getSource().substring(1) + " not found for Edge: " + item.getKey(),
521               Status.BAD_REQUEST);
522         }
523       }
524       edges.add(item.getKey());
525
526     }
527
528   }
529
530   @POST
531   @Path("/{version}/bulk/")
532   @Consumes({ MediaType.APPLICATION_JSON })
533   @Produces({ MediaType.APPLICATION_JSON })
534   public Response addBulk(String content, @PathParam("version") String version, @PathParam("type") String type,
535       @PathParam("uri") @Encoded String uri, @Context HttpHeaders headers, @Context UriInfo uriInfo,
536       @Context HttpServletRequest req) {
537
538     LoggingUtil.initMdcContext(req, headers);
539
540     logger.debug("Incoming request..." + content);
541     Response response = null;
542
543     if (validateRequest(req, uri, content, Action.POST, CrudServiceConstants.CRD_AUTH_POLICY_NAME)) {
544
545       try {
546         BulkPayload payload = BulkPayload.fromJson(content);
547         if ((payload.getObjects() == null && payload.getRelationships() == null)
548             || (payload.getObjects() != null && payload.getObjects().isEmpty() && payload.getRelationships() != null
549                 && payload.getRelationships().isEmpty())) {
550           throw new CrudException("Invalid request Payload", Status.BAD_REQUEST);
551         }
552
553         validateBulkPayload(payload);
554         String result = graphDataService.addBulk(version, payload);
555         response = Response.status(Status.OK).entity(result).type(mediaType).build();
556       } catch (CrudException ce) {
557         response = Response.status(ce.getHttpStatus()).entity(ce.getMessage()).build();
558       } catch (Exception e) {
559         response = Response.status(Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()).build();
560       }
561     } else {
562       response = Response.status(Status.FORBIDDEN).entity(content).type(MediaType.APPLICATION_JSON).build();
563     }
564
565     LoggingUtil.logRestRequest(logger, auditLogger, req, response);
566     return response;
567   }
568
569   @POST
570   @Path("/{version}/")
571   @Consumes({ MediaType.APPLICATION_JSON })
572   @Produces({ MediaType.APPLICATION_JSON })
573   public Response addVertex(String content, @PathParam("version") String version, @PathParam("uri") @Encoded String uri,
574       @Context HttpHeaders headers, @Context UriInfo uriInfo, @Context HttpServletRequest req) {
575
576     LoggingUtil.initMdcContext(req, headers);
577
578     logger.debug("Incoming request..." + content);
579     Response response = null;
580
581     if (validateRequest(req, uri, content, Action.POST, CrudServiceConstants.CRD_AUTH_POLICY_NAME)) {
582       try {
583
584         VertexPayload payload = VertexPayload.fromJson(content);
585         if (payload.getProperties() == null || payload.getProperties().isJsonNull()) {
586           throw new CrudException("Invalid request Payload", Status.BAD_REQUEST);
587         }
588         if (payload.getId() != null) {
589           throw new CrudException("ID specified , use Http PUT to update Vertex", Status.BAD_REQUEST);
590         }
591
592         if (payload.getType() == null || payload.getType().isEmpty()) {
593           throw new CrudException("Missing Vertex Type ", Status.BAD_REQUEST);
594         }
595         String result = graphDataService.addVertex(version, payload.getType(), payload);
596         response = Response.status(Status.CREATED).entity(result).type(mediaType).build();
597       } catch (CrudException ce) {
598         response = Response.status(ce.getHttpStatus()).entity(ce.getMessage()).build();
599       } catch (Exception e) {
600         response = Response.status(Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()).build();
601       }
602     } else {
603       response = Response.status(Status.FORBIDDEN).entity(content).type(MediaType.APPLICATION_JSON).build();
604     }
605
606     LoggingUtil.logRestRequest(logger, auditLogger, req, response);
607     return response;
608   }
609
610   @POST
611   @Path("/relationships/{version}/{type}/")
612   @Consumes({ MediaType.APPLICATION_JSON })
613   @Produces({ MediaType.APPLICATION_JSON })
614   public Response addEdge(String content, @PathParam("version") String version, @PathParam("type") String type,
615       @PathParam("uri") @Encoded String uri, @Context HttpHeaders headers, @Context UriInfo uriInfo,
616       @Context HttpServletRequest req) {
617
618     LoggingUtil.initMdcContext(req, headers);
619
620     logger.debug("Incoming request..." + content);
621     Response response = null;
622
623     if (validateRequest(req, uri, content, Action.POST, CrudServiceConstants.CRD_AUTH_POLICY_NAME)) {
624
625       try {
626         EdgePayload payload = EdgePayload.fromJson(content);
627         if (payload.getProperties() == null || payload.getProperties().isJsonNull()) {
628           throw new CrudException("Invalid request Payload", Status.BAD_REQUEST);
629         }
630         if (payload.getId() != null) {
631           throw new CrudException("ID specified , use Http PUT to update Edge", Status.BAD_REQUEST);
632         }
633
634         if (payload.getType() != null && !payload.getType().equals(type)) {
635           throw new CrudException("Edge Type mismatch", Status.BAD_REQUEST);
636         }
637         String result = graphDataService.addEdge(version, type, payload);
638         response = Response.status(Status.CREATED).entity(result).type(mediaType).build();
639       } catch (CrudException ce) {
640         response = Response.status(ce.getHttpStatus()).entity(ce.getMessage()).build();
641       } catch (Exception e) {
642         response = Response.status(Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()).build();
643       }
644     } else {
645       response = Response.status(Status.FORBIDDEN).entity(content).type(MediaType.APPLICATION_JSON).build();
646     }
647
648     LoggingUtil.logRestRequest(logger, auditLogger, req, response);
649     return response;
650   }
651
652   @POST
653   @Path("/relationships/{version}/")
654   @Consumes({ MediaType.APPLICATION_JSON })
655   @Produces({ MediaType.APPLICATION_JSON })
656   public Response addEdge(String content, @PathParam("version") String version, @PathParam("uri") @Encoded String uri,
657       @Context HttpHeaders headers, @Context UriInfo uriInfo, @Context HttpServletRequest req) {
658
659     LoggingUtil.initMdcContext(req, headers);
660
661     logger.debug("Incoming request..." + content);
662     Response response = null;
663
664     if (validateRequest(req, uri, content, Action.POST, CrudServiceConstants.CRD_AUTH_POLICY_NAME)) {
665
666       try {
667         EdgePayload payload = EdgePayload.fromJson(content);
668         if (payload.getProperties() == null || payload.getProperties().isJsonNull()) {
669           throw new CrudException("Invalid request Payload", Status.BAD_REQUEST);
670         }
671         if (payload.getId() != null) {
672           throw new CrudException("ID specified , use Http PUT to update Edge", Status.BAD_REQUEST);
673         }
674
675         if (payload.getType() == null || payload.getType().isEmpty()) {
676           throw new CrudException("Missing Edge Type ", Status.BAD_REQUEST);
677         }
678         String result = graphDataService.addEdge(version, payload.getType(), payload);
679
680         response = Response.status(Status.CREATED).entity(result).type(mediaType).build();
681       } catch (CrudException ce) {
682         response = Response.status(ce.getHttpStatus()).entity(ce.getMessage()).build();
683       } catch (Exception e) {
684         response = Response.status(Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()).build();
685       }
686     } else {
687       response = Response.status(Status.FORBIDDEN).entity(content).type(MediaType.APPLICATION_JSON).build();
688     }
689
690     LoggingUtil.logRestRequest(logger, auditLogger, req, response);
691     return response;
692   }
693
694   @DELETE
695   @Path("/{version}/{type}/{id}")
696   @Consumes({ MediaType.APPLICATION_JSON })
697   @Produces({ MediaType.APPLICATION_JSON })
698   public Response deleteVertex(String content, @PathParam("version") String version, @PathParam("type") String type,
699       @PathParam("id") String id, @PathParam("uri") @Encoded String uri, @Context HttpHeaders headers,
700       @Context UriInfo uriInfo, @Context HttpServletRequest req) {
701
702     LoggingUtil.initMdcContext(req, headers);
703
704     logger.debug("Incoming request..." + content);
705     Response response = null;
706
707     if (validateRequest(req, uri, content, Action.DELETE, CrudServiceConstants.CRD_AUTH_POLICY_NAME)) {
708
709       try {
710         String result = graphDataService.deleteVertex(version, id, type);
711         response = Response.status(Status.OK).entity(result).type(mediaType).build();
712       } catch (CrudException ce) {
713         response = Response.status(ce.getHttpStatus()).entity(ce.getMessage()).build();
714       } catch (Exception e) {
715         response = Response.status(Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()).build();
716       }
717     } else {
718       response = Response.status(Status.FORBIDDEN).entity(content).type(MediaType.APPLICATION_JSON).build();
719     }
720
721     LoggingUtil.logRestRequest(logger, auditLogger, req, response);
722     return response;
723   }
724
725   @DELETE
726   @Path("/relationships/{version}/{type}/{id}")
727   @Consumes({ MediaType.APPLICATION_JSON })
728   @Produces({ MediaType.APPLICATION_JSON })
729   public Response deleteEdge(String content, @PathParam("version") String version, @PathParam("type") String type,
730       @PathParam("id") String id, @PathParam("uri") @Encoded String uri, @Context HttpHeaders headers,
731       @Context UriInfo uriInfo, @Context HttpServletRequest req) {
732
733     LoggingUtil.initMdcContext(req, headers);
734
735     logger.debug("Incoming request..." + content);
736     Response response = null;
737     if (validateRequest(req, uri, content, Action.DELETE, CrudServiceConstants.CRD_AUTH_POLICY_NAME)) {
738
739       try {
740         String result = graphDataService.deleteEdge(version, id, type);
741         response = Response.status(Status.OK).entity(result).type(mediaType).build();
742       } catch (CrudException ce) {
743         response = Response.status(ce.getHttpStatus()).entity(ce.getMessage()).build();
744       } catch (Exception e) {
745         response = Response.status(Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()).build();
746       }
747     } else {
748       response = Response.status(Status.FORBIDDEN).entity(content).type(MediaType.APPLICATION_JSON).build();
749     }
750
751     LoggingUtil.logRestRequest(logger, auditLogger, req, response);
752     return response;
753   }
754
755   protected boolean validateRequest(HttpServletRequest req, String uri, String content, Action action,
756       String authPolicyFunctionName) {
757     try {
758       String cipherSuite = (String) req.getAttribute("javax.servlet.request.cipher_suite");
759       String authUser = null;
760       if (cipherSuite != null) {
761         X509Certificate[] certChain = (X509Certificate[]) req.getAttribute("javax.servlet.request.X509Certificate");
762         X509Certificate clientCert = certChain[0];
763         X500Principal subjectDn = clientCert.getSubjectX500Principal();
764         authUser = subjectDn.toString();
765       }
766       return this.auth.validateRequest(authUser.toLowerCase(), action.toString() + ":" + authPolicyFunctionName);
767     } catch (Exception e) {
768       logResult(action, uri, e);
769       return false;
770     }
771   }
772
773   void logResult(Action op, String uri, Exception e) {
774
775     logger.error(CrudServiceMsgs.EXCEPTION_DURING_METHOD_CALL, op.toString(), uri, e.getStackTrace().toString());
776
777     // Clear the MDC context so that no other transaction inadvertently
778     // uses our transaction id.
779     MDC.clear();
780   }
781 }