From f61e8a4b2581165ae6c0c4663bf52e841c5be39e Mon Sep 17 00:00:00 2001 From: Fiete Ostkamp Date: Wed, 26 Oct 2022 14:15:46 +0000 Subject: Run the formatter for the resources service - reduces the format violations from ~7000 to ~400 Issue-ID: AAI-3567 Signed-off-by: Fiete Ostkamp Change-Id: I570805692bfbd3f80a43c0813831adcdb98016d4 --- .../main/java/org/onap/aai/IncreaseNodesTool.java | 204 ++-- .../src/main/java/org/onap/aai/Profiles.java | 16 +- .../src/main/java/org/onap/aai/ResourcesApp.java | 280 ++--- .../onap/aai/TenantIsolation/DataImportTasks.java | 136 ++- .../java/org/onap/aai/config/ErrorHandler.java | 27 +- .../org/onap/aai/config/JettyPasswordDecoder.java | 1 + .../java/org/onap/aai/config/PasswordDecoder.java | 1 + .../aai/config/PropertyPasswordConfiguration.java | 13 +- .../main/java/org/onap/aai/dbgen/tags/Command.java | 3 +- .../onap/aai/interceptors/AAIContainerFilter.java | 31 +- .../onap/aai/interceptors/AAIHeaderProperties.java | 38 +- .../org/onap/aai/interceptors/package-info.java | 5 +- .../post/AAIResponseFilterPriority.java | 14 +- .../interceptors/post/InvalidResponseStatus.java | 50 +- .../post/ResponseHeaderManipulation.java | 40 +- .../post/ResponseTransactionLogging.java | 33 +- .../interceptors/pre/AAIRequestFilterPriority.java | 30 +- .../aai/interceptors/pre/HeaderValidation.java | 215 ++-- .../interceptors/pre/HttpHeaderInterceptor.java | 28 +- .../interceptors/pre/OneWaySslAuthorization.java | 36 +- .../pre/RequestHeaderManipulation.java | 27 +- .../aai/interceptors/pre/RequestModification.java | 55 +- .../pre/RequestTransactionLogging.java | 190 +-- .../aai/interceptors/pre/RetiredInterceptor.java | 68 +- .../aai/interceptors/pre/VersionInterceptor.java | 45 +- .../interceptors/pre/VersionLatestInterceptor.java | 16 +- .../java/org/onap/aai/rest/BulkAddConsumer.java | 36 +- .../main/java/org/onap/aai/rest/BulkConsumer.java | 1026 ++++++++-------- .../org/onap/aai/rest/BulkProcessConsumer.java | 37 +- .../java/org/onap/aai/rest/ExampleConsumer.java | 104 +- .../java/org/onap/aai/rest/ExceptionHandler.java | 144 ++- .../java/org/onap/aai/rest/LegacyMoxyConsumer.java | 1283 ++++++++++---------- .../org/onap/aai/rest/URLFromVertexIdConsumer.java | 133 +- .../java/org/onap/aai/rest/VertexIdConsumer.java | 167 +-- .../java/org/onap/aai/rest/bulk/BulkOperation.java | 131 +- .../onap/aai/rest/bulk/BulkOperationResponse.java | 116 +- .../rest/bulk/BulkSingleTransactionConsumer.java | 830 ++++++------- .../java/org/onap/aai/rest/bulk/BulkUriInfo.java | 204 ++-- .../org/onap/aai/rest/bulk/pojos/Operation.java | 1 + .../aai/rest/bulk/pojos/OperationResponse.java | 1 + .../org/onap/aai/rest/bulk/pojos/Transaction.java | 1 + .../aai/rest/bulk/pojos/TransactionResponse.java | 1 + .../rest/exceptions/AAIInvalidXMLNamespace.java | 23 +- .../onap/aai/rest/security/WebSecurityConfig.java | 15 +- .../java/org/onap/aai/rest/util/EchoResponse.java | 30 +- .../org/onap/aai/rest/util/LogFormatTools.java | 14 +- .../org/onap/aai/rest/util/ValidateEncoding.java | 256 ++-- .../org/onap/aai/service/AuthorizationService.java | 46 +- .../java/org/onap/aai/service/RetiredService.java | 28 +- .../java/org/onap/aai/tasks/AaiGraphChecker.java | 39 +- .../org/onap/aai/util/PositiveNumValidator.java | 17 +- .../java/org/onap/aai/web/JerseyConfiguration.java | 34 +- .../java/org/onap/aai/web/LocalHostAccessLog.java | 21 +- .../org/onap/aai/web/MicrometerConfiguration.java | 17 +- .../java/org/onap/aai/web/WebConfiguration.java | 31 +- 55 files changed, 3235 insertions(+), 3153 deletions(-) (limited to 'aai-resources/src/main/java') diff --git a/aai-resources/src/main/java/org/onap/aai/IncreaseNodesTool.java b/aai-resources/src/main/java/org/onap/aai/IncreaseNodesTool.java index 614d16f..a473c2a 100644 --- a/aai-resources/src/main/java/org/onap/aai/IncreaseNodesTool.java +++ b/aai-resources/src/main/java/org/onap/aai/IncreaseNodesTool.java @@ -17,17 +17,17 @@ * limitations under the License. * ============LICENSE_END========================================================= */ + package org.onap.aai; +import com.beust.jcommander.JCommander; +import com.beust.jcommander.Parameter; + import java.io.UnsupportedEncodingException; import java.util.ArrayList; import java.util.List; import java.util.UUID; -import org.onap.aai.restclient.PropertyPasswordConfiguration; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.context.ApplicationContext; import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource; import org.apache.tinkerpop.gremlin.structure.Vertex; import org.janusgraph.core.JanusGraph; @@ -41,76 +41,76 @@ import org.onap.aai.introspection.LoaderFactory; import org.onap.aai.introspection.ModelType; import org.onap.aai.introspection.exceptions.AAIUnknownObjectException; import org.onap.aai.logging.ErrorLogHelper; +import org.onap.aai.restclient.PropertyPasswordConfiguration; +import org.onap.aai.serialization.db.EdgeSerializer; +import org.onap.aai.serialization.engines.TransactionalGraphEngine; import org.onap.aai.setup.SchemaVersions; import org.onap.aai.util.AAISystemExitUtil; import org.onap.aai.util.PositiveNumValidator; -import org.onap.aai.serialization.engines.TransactionalGraphEngine; -import org.onap.aai.serialization.db.EdgeSerializer; -import com.beust.jcommander.JCommander; -import com.beust.jcommander.Parameter; -import org.springframework.context.annotation.AnnotationConfigApplicationContext; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationContext; +import org.springframework.context.annotation.AnnotationConfigApplicationContext; public class IncreaseNodesTool { - public static long nodeCount = 0; - - @Autowired - protected static EdgeSerializer edgeSerializer; - - private LoaderFactory loaderFactory; - private SchemaVersions schemaVersions; - protected TransactionalGraphEngine engine; + public static long nodeCount = 0; + + @Autowired + protected static EdgeSerializer edgeSerializer; + + private LoaderFactory loaderFactory; + private SchemaVersions schemaVersions; + protected TransactionalGraphEngine engine; Vertex parentVtx; private static final Logger LOGGER = LoggerFactory.getLogger(IncreaseNodesTool.class); - public IncreaseNodesTool(LoaderFactory loaderFactory, SchemaVersions schemaVersions){ - this.loaderFactory = loaderFactory; - this.schemaVersions = schemaVersions; - } - - public static void main(String[] args) throws AAIUnknownObjectException, UnsupportedEncodingException, AAIException { - - AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(); - PropertyPasswordConfiguration initializer = new PropertyPasswordConfiguration(); - initializer.initialize(context); - try { - context.scan( - "org.onap.aai.config", - "org.onap.aai.setup" - ); - context.refresh(); - } catch (Exception e) { - AAIException aai = null; - if(e.getCause() instanceof AAIException){ - aai = (AAIException)e.getCause(); - } else { - aai = ResourcesApp.schemaServiceExceptionTranslator(e); - } - LOGGER.error("Problems starting the Increase Nodes Tool due to {}", aai.getMessage()); - ErrorLogHelper.logException(aai); - throw aai; - } - - LoaderFactory loaderFactory = context.getBean(LoaderFactory.class); - SchemaVersions schemaVersions = (SchemaVersions) SpringContextAware.getBean("schemaVersions"); - - IncreaseNodesTool increaseNodesTool = new IncreaseNodesTool(loaderFactory, schemaVersions); - JanusGraph janusGraph = AAIGraph.getInstance().getGraph(); - - ApplicationContext ctx = (ApplicationContext) SpringContextAware.getApplicationContext(); - edgeSerializer = ctx.getBean(EdgeSerializer.class); - - increaseNodesTool.run(janusGraph,args); - AAISystemExitUtil.systemExitCloseAAIGraph(0); - - } - - - public void run(JanusGraph janusGraph, String[] args) throws AAIUnknownObjectException, UnsupportedEncodingException { + public IncreaseNodesTool(LoaderFactory loaderFactory, SchemaVersions schemaVersions) { + this.loaderFactory = loaderFactory; + this.schemaVersions = schemaVersions; + } + + public static void main(String[] args) + throws AAIUnknownObjectException, UnsupportedEncodingException, AAIException { + + AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(); + PropertyPasswordConfiguration initializer = new PropertyPasswordConfiguration(); + initializer.initialize(context); + try { + context.scan("org.onap.aai.config", "org.onap.aai.setup"); + context.refresh(); + } catch (Exception e) { + AAIException aai = null; + if (e.getCause() instanceof AAIException) { + aai = (AAIException) e.getCause(); + } else { + aai = ResourcesApp.schemaServiceExceptionTranslator(e); + } + LOGGER.error("Problems starting the Increase Nodes Tool due to {}", aai.getMessage()); + ErrorLogHelper.logException(aai); + throw aai; + } + + LoaderFactory loaderFactory = context.getBean(LoaderFactory.class); + SchemaVersions schemaVersions = (SchemaVersions) SpringContextAware.getBean("schemaVersions"); + + IncreaseNodesTool increaseNodesTool = new IncreaseNodesTool(loaderFactory, schemaVersions); + JanusGraph janusGraph = AAIGraph.getInstance().getGraph(); + + ApplicationContext ctx = (ApplicationContext) SpringContextAware.getApplicationContext(); + edgeSerializer = ctx.getBean(EdgeSerializer.class); + + increaseNodesTool.run(janusGraph, args); + AAISystemExitUtil.systemExitCloseAAIGraph(0); + + } + + public void run(JanusGraph janusGraph, String[] args) + throws AAIUnknownObjectException, UnsupportedEncodingException { CommandLineArgs cArgs = new CommandLineArgs(); - JCommander jCommander = new JCommander(cArgs,args); + JCommander jCommander = new JCommander(cArgs, args); jCommander.setProgramName(IncreaseNodesTool.class.getSimpleName()); Loader loader = loaderFactory.createLoaderForVersion(ModelType.MOXY, schemaVersions.getDefaultVersion()); @@ -119,20 +119,21 @@ public class IncreaseNodesTool { List propList = new ArrayList(); propList.addAll(obj.getRequiredProperties()); - nodeCount = Long.parseLong(cArgs.numberOfNodes); - addVertex(janusGraph, cArgs.nodeType,propList,cArgs); + addVertex(janusGraph, cArgs.nodeType, propList, cArgs); } + /*** * adds a vertex based on user inputs of node type number of nodes and the node uri * /cloud-infrastructure/pservers/pserver/ * /network/pnfs/pnf/ * /cloud-infrastructure/pservers/pserver/random-056fd6c4-7313-4fa0-b854-0d9983bdb0ab/p-interfaces/p-interface/ + * * @param * @param * @param cArgs */ - public void addVertex(JanusGraph janusGraph, String nodeType, List propList,CommandLineArgs cArgs){ + public void addVertex(JanusGraph janusGraph, String nodeType, List propList, CommandLineArgs cArgs) { long startTime = System.currentTimeMillis(); try (JanusGraphTransaction transaction = janusGraph.newTransaction()) { @@ -143,47 +144,44 @@ public class IncreaseNodesTool { for (long i = 1; i <= nodeCount; i++) { String randomId = UUID.randomUUID().toString(); Vertex v = g.addV(nodeType).next(); - + v.property("aai-node-type", nodeType); v.property("source-of-truth", "IncreaseNodesTool"); - v.property("aai-uri", cArgs.uri+"random-"+randomId); - + v.property("aai-uri", cArgs.uri + "random-" + randomId); - for(String propName : propList){ - if(propName.equals("in-maint")){ - v.property(propName,"false"); + for (String propName : propList) { + if (propName.equals("in-maint")) { + v.property(propName, "false"); continue; } v.property(propName, "random-" + randomId); - System.out.println("node " + i + " added " + propList.get(0)+": " + "random-"+randomId); + System.out.println("node " + i + " added " + propList.get(0) + ": " + "random-" + randomId); } - - if(cArgs.child.equals("true")){ - if(parentVtx == null){ + if (cArgs.child.equals("true")) { + + if (parentVtx == null) { String[] uriTokens = cArgs.uri.split("/"); - String ParentNodeType = uriTokens[uriTokens.length-4]; //parent node type - String keyVal = uriTokens[uriTokens.length-3]; // parent unique key - Loader loader = loaderFactory.createLoaderForVersion(ModelType.MOXY, schemaVersions.getDefaultVersion()); - if (loader != null) - { - Introspector objParent = loader.introspectorFromName(ParentNodeType); - if (objParent != null) - { - List parentPropList = new ArrayList(); - parentPropList.addAll(objParent.getRequiredProperties()); - if (parentPropList.size() > 0) - { - System.out.println("parent node (" + ParentNodeType + ") key (" + parentPropList.get(0)+" ) =" + keyVal); - parentVtx = g.V().has(parentPropList.get(0),keyVal).next(); - edgeSerializer.addTreeEdgeIfPossible(g,parentVtx,v); - } - } + String ParentNodeType = uriTokens[uriTokens.length - 4]; // parent node type + String keyVal = uriTokens[uriTokens.length - 3]; // parent unique key + Loader loader = loaderFactory.createLoaderForVersion(ModelType.MOXY, + schemaVersions.getDefaultVersion()); + if (loader != null) { + Introspector objParent = loader.introspectorFromName(ParentNodeType); + if (objParent != null) { + List parentPropList = new ArrayList(); + parentPropList.addAll(objParent.getRequiredProperties()); + if (parentPropList.size() > 0) { + System.out.println("parent node (" + ParentNodeType + ") key (" + + parentPropList.get(0) + " ) =" + keyVal); + parentVtx = g.V().has(parentPropList.get(0), keyVal).next(); + edgeSerializer.addTreeEdgeIfPossible(g, parentVtx, v); + } + } } - } - else{ - edgeSerializer.addTreeEdgeIfPossible(g,parentVtx,v); + } else { + edgeSerializer.addTreeEdgeIfPossible(g, parentVtx, v); } } @@ -195,7 +193,7 @@ public class IncreaseNodesTool { transaction.commit(); System.out.println("Transaction Committed"); long endTime = System.currentTimeMillis(); - System.out.println("Total Time: "+ ((endTime - startTime)/ 1000.0) + "seconds"); + System.out.println("Total Time: " + ((endTime - startTime) / 1000.0) + "seconds"); } else { transaction.rollback(); } @@ -203,23 +201,25 @@ public class IncreaseNodesTool { } } - } - +} class CommandLineArgs { - @Parameter(names = "-numberOfNodes", description = "how many nodes you would like to enter", required = true , validateWith = PositiveNumValidator.class) + @Parameter( + names = "-numberOfNodes", + description = "how many nodes you would like to enter", + required = true, + validateWith = PositiveNumValidator.class) public String numberOfNodes; @Parameter(names = "-nodeType", description = "The aai-node-type of the node being entered", required = true) public String nodeType; - @Parameter(names = "-uri", description = "uri to be passed for the node",required = true) + @Parameter(names = "-uri", description = "uri to be passed for the node", required = true) public String uri; - @Parameter(names = "-child", description = "is this a child node",required = true) + @Parameter(names = "-child", description = "is this a child node", required = true) public String child; } - diff --git a/aai-resources/src/main/java/org/onap/aai/Profiles.java b/aai-resources/src/main/java/org/onap/aai/Profiles.java index 25f51c3..9c7c05f 100644 --- a/aai-resources/src/main/java/org/onap/aai/Profiles.java +++ b/aai-resources/src/main/java/org/onap/aai/Profiles.java @@ -17,19 +17,21 @@ * limitations under the License. * ============LICENSE_END========================================================= */ + package org.onap.aai; public final class Profiles { - public static final String DMAAP = "dmaap"; - public static final String DME2 = "dme2"; + public static final String DMAAP = "dmaap"; + public static final String DME2 = "dme2"; - public static final String ONE_WAY_SSL = "one-way-ssl"; + public static final String ONE_WAY_SSL = "one-way-ssl"; // AAF Basic Auth - public static final String AAF_AUTHENTICATION = "aaf-auth"; + public static final String AAF_AUTHENTICATION = "aaf-auth"; // AAF Auth with Client Certs - public static final String AAF_CERT_AUTHENTICATION = "aaf-cert-auth"; - public static final String TWO_WAY_SSL = "two-way-ssl"; + public static final String AAF_CERT_AUTHENTICATION = "aaf-cert-auth"; + public static final String TWO_WAY_SSL = "two-way-ssl"; - private Profiles(){} + private Profiles() { + } } diff --git a/aai-resources/src/main/java/org/onap/aai/ResourcesApp.java b/aai-resources/src/main/java/org/onap/aai/ResourcesApp.java index 419fee5..0538416 100644 --- a/aai-resources/src/main/java/org/onap/aai/ResourcesApp.java +++ b/aai-resources/src/main/java/org/onap/aai/ResourcesApp.java @@ -22,6 +22,7 @@ package org.onap.aai; import javax.annotation.PostConstruct; import javax.annotation.PreDestroy; + import org.apache.commons.lang3.exception.ExceptionUtils; import org.onap.aai.aailog.logs.AaiDebugLog; import org.onap.aai.config.SpringContextAware; @@ -43,159 +44,140 @@ import org.springframework.context.annotation.ComponentScan; import org.springframework.core.env.Environment; @SpringBootApplication( - exclude = { - DataSourceAutoConfiguration.class, - DataSourceTransactionManagerAutoConfiguration.class, - HibernateJpaAutoConfiguration.class - } -) + exclude = {DataSourceAutoConfiguration.class, DataSourceTransactionManagerAutoConfiguration.class, + HibernateJpaAutoConfiguration.class}) // Component Scan provides a way to look for spring beans // It only searches beans in the following packages // Any method annotated with @Bean annotation or any class // with @Component, @Configuration, @Service will be picked up -@ComponentScan(basePackages = { - "org.onap.aai.config", - "org.onap.aai.web", - "org.onap.aai.setup", - "org.onap.aai.tasks", - "org.onap.aai.service", - "org.onap.aai.rest", - "org.onap.aai.aaf", - "org.onap.aai.TenantIsolation", - "org.onap.aai.aailog", - "org.onap.aai.prevalidation" -}) +@ComponentScan( + basePackages = {"org.onap.aai.config", "org.onap.aai.web", "org.onap.aai.setup", "org.onap.aai.tasks", + "org.onap.aai.service", "org.onap.aai.rest", "org.onap.aai.aaf", "org.onap.aai.TenantIsolation", + "org.onap.aai.aailog", "org.onap.aai.prevalidation"}) public class ResourcesApp { - private static final Logger logger = LoggerFactory.getLogger(ResourcesApp.class.getName()); - - private static final String APP_NAME = "aai-resources"; - private static AaiDebugLog debugLog = new AaiDebugLog(); - static { - debugLog.setupMDC(); - } - - @Autowired - private Environment env; - - @Autowired - private NodeIngestor nodeIngestor; - - @Autowired - private SpringContextAware context; - - @Autowired - private SpringContextAware loaderFactory; - - - @PostConstruct - private void init() throws AAIException { - System.setProperty("org.onap.aai.serverStarted", "false"); - setDefaultProps(); - logger.info("AAI Server initialization started..."); - - // Setting this property to allow for encoded slash (/) in the path parameter - // This is only needed for tomcat keeping this as temporary - System.setProperty("org.apache.tomcat.util.buf.UDecoder.ALLOW_ENCODED_SLASH", "true"); - - logger.info("Starting AAIGraph connections and the NodeInjestor"); - - if(env.acceptsProfiles(Profiles.TWO_WAY_SSL) && env.acceptsProfiles(Profiles.ONE_WAY_SSL)){ - logger.warn("You have seriously misconfigured your application"); - } - - } - - @PreDestroy - public void cleanup(){ - logger.info("Shutting down both realtime and cached connections"); - AAIGraph.getInstance().graphShutdown(); - } - - public static void main(String[] args) throws AAIException { - - setDefaultProps(); - - Environment env =null; - AAIConfig.init(); - try { - SpringApplication app = new SpringApplication(ResourcesApp.class); - app.setLogStartupInfo(false); - app.setRegisterShutdownHook(true); - app.addInitializers(new PropertyPasswordConfiguration()); - env = app.run(args).getEnvironment(); - } - catch(Exception ex){ - AAIException aai = null; - if(ex.getCause() instanceof AAIException){ - aai = (AAIException)ex.getCause(); - } else { - aai = schemaServiceExceptionTranslator(ex); - } - logger.error("Problems starting the ResourcesApp due to {}", aai.getMessage()); - ErrorLogHelper.logException(aai); - throw aai; - } - - logger.info( - "Application '{}' is running on {}!" , - env.getProperty("spring.application.name"), - env.getProperty("server.port") - ); - - // The main reason this was moved from the constructor is due - // to the SchemaGenerator needs the bean and during the constructor - // the Spring Context is not yet initialized - - AAIConfig.init(); - AAIGraph.getInstance(); - - logger.info("Resources MicroService Started"); - logger.debug("Resources MicroService Started"); - - System.out.println("Resources Microservice Started"); - - } - - public static void setDefaultProps(){ - - if (System.getProperty("file.separator") == null) { - System.setProperty("file.separator", "/"); - } - - String currentDirectory = System.getProperty("user.dir"); - System.setProperty("aai.service.name", ResourcesApp.class.getSimpleName()); - - if (System.getProperty("AJSC_HOME") == null) { - System.setProperty("AJSC_HOME", "."); - } - - if(currentDirectory.contains(APP_NAME)){ - if (System.getProperty("BUNDLECONFIG_DIR") == null) { - System.setProperty("BUNDLECONFIG_DIR", "src/main/resources"); - } - } else { - if (System.getProperty("BUNDLECONFIG_DIR") == null) { - System.setProperty("BUNDLECONFIG_DIR", "aai-resources/src/main/resources"); - } - } - } - public static AAIException schemaServiceExceptionTranslator(Exception ex) { - AAIException aai = null; - String message = ExceptionUtils.getRootCause(ex).getMessage(); - if(message.contains("NodeIngestor")){ - aai = new AAIException("AAI_3026","Error reading OXM from SchemaService - Investigate"); - } - else if(message.contains("EdgeIngestor")){ - aai = new AAIException("AAI_3027","Error reading EdgeRules from SchemaService - Investigate"); - } - else if(message.contains("Connection refused")){ - aai = new AAIException("AAI_3025","Error connecting to SchemaService - Investigate"); - } - else { - aai = new AAIException("AAI_3025","Unable to determine what the error is, please check external.log"); - } - - return aai; - } + private static final Logger logger = LoggerFactory.getLogger(ResourcesApp.class.getName()); + + private static final String APP_NAME = "aai-resources"; + private static AaiDebugLog debugLog = new AaiDebugLog(); + static { + debugLog.setupMDC(); + } + + @Autowired + private Environment env; + + @Autowired + private NodeIngestor nodeIngestor; + + @Autowired + private SpringContextAware context; + + @Autowired + private SpringContextAware loaderFactory; + + @PostConstruct + private void init() throws AAIException { + System.setProperty("org.onap.aai.serverStarted", "false"); + setDefaultProps(); + logger.info("AAI Server initialization started..."); + + // Setting this property to allow for encoded slash (/) in the path parameter + // This is only needed for tomcat keeping this as temporary + System.setProperty("org.apache.tomcat.util.buf.UDecoder.ALLOW_ENCODED_SLASH", "true"); + + logger.info("Starting AAIGraph connections and the NodeInjestor"); + + if (env.acceptsProfiles(Profiles.TWO_WAY_SSL) && env.acceptsProfiles(Profiles.ONE_WAY_SSL)) { + logger.warn("You have seriously misconfigured your application"); + } + + } + + @PreDestroy + public void cleanup() { + logger.info("Shutting down both realtime and cached connections"); + AAIGraph.getInstance().graphShutdown(); + } + + public static void main(String[] args) throws AAIException { + + setDefaultProps(); + + Environment env = null; + AAIConfig.init(); + try { + SpringApplication app = new SpringApplication(ResourcesApp.class); + app.setLogStartupInfo(false); + app.setRegisterShutdownHook(true); + app.addInitializers(new PropertyPasswordConfiguration()); + env = app.run(args).getEnvironment(); + } catch (Exception ex) { + AAIException aai = null; + if (ex.getCause() instanceof AAIException) { + aai = (AAIException) ex.getCause(); + } else { + aai = schemaServiceExceptionTranslator(ex); + } + logger.error("Problems starting the ResourcesApp due to {}", aai.getMessage()); + ErrorLogHelper.logException(aai); + throw aai; + } + + logger.info("Application '{}' is running on {}!", env.getProperty("spring.application.name"), + env.getProperty("server.port")); + + // The main reason this was moved from the constructor is due + // to the SchemaGenerator needs the bean and during the constructor + // the Spring Context is not yet initialized + + AAIConfig.init(); + AAIGraph.getInstance(); + + logger.info("Resources MicroService Started"); + logger.debug("Resources MicroService Started"); + + System.out.println("Resources Microservice Started"); + + } + + public static void setDefaultProps() { + + if (System.getProperty("file.separator") == null) { + System.setProperty("file.separator", "/"); + } + + String currentDirectory = System.getProperty("user.dir"); + System.setProperty("aai.service.name", ResourcesApp.class.getSimpleName()); + + if (System.getProperty("AJSC_HOME") == null) { + System.setProperty("AJSC_HOME", "."); + } + + if (currentDirectory.contains(APP_NAME)) { + if (System.getProperty("BUNDLECONFIG_DIR") == null) { + System.setProperty("BUNDLECONFIG_DIR", "src/main/resources"); + } + } else { + if (System.getProperty("BUNDLECONFIG_DIR") == null) { + System.setProperty("BUNDLECONFIG_DIR", "aai-resources/src/main/resources"); + } + } + } + + public static AAIException schemaServiceExceptionTranslator(Exception ex) { + AAIException aai = null; + String message = ExceptionUtils.getRootCause(ex).getMessage(); + if (message.contains("NodeIngestor")) { + aai = new AAIException("AAI_3026", "Error reading OXM from SchemaService - Investigate"); + } else if (message.contains("EdgeIngestor")) { + aai = new AAIException("AAI_3027", "Error reading EdgeRules from SchemaService - Investigate"); + } else if (message.contains("Connection refused")) { + aai = new AAIException("AAI_3025", "Error connecting to SchemaService - Investigate"); + } else { + aai = new AAIException("AAI_3025", "Unable to determine what the error is, please check external.log"); + } + + return aai; + } } diff --git a/aai-resources/src/main/java/org/onap/aai/TenantIsolation/DataImportTasks.java b/aai-resources/src/main/java/org/onap/aai/TenantIsolation/DataImportTasks.java index c22251d..3aeac7e 100644 --- a/aai-resources/src/main/java/org/onap/aai/TenantIsolation/DataImportTasks.java +++ b/aai-resources/src/main/java/org/onap/aai/TenantIsolation/DataImportTasks.java @@ -17,8 +17,11 @@ * limitations under the License. * ============LICENSE_END========================================================= */ + package org.onap.aai.TenantIsolation; +import com.att.eelf.configuration.Configuration; + import java.io.BufferedReader; import java.io.File; import java.io.FileFilter; @@ -38,25 +41,21 @@ import java.util.UUID; import java.util.regex.Matcher; import java.util.regex.Pattern; - +import org.apache.commons.io.FileUtils; +import org.apache.commons.io.comparator.LastModifiedFileComparator; +import org.apache.commons.io.filefilter.DirectoryFileFilter; +import org.apache.commons.io.filefilter.FileFileFilter; +import org.apache.commons.io.filefilter.RegexFileFilter; import org.onap.aai.exceptions.AAIException; import org.onap.aai.logging.ErrorLogHelper; import org.onap.aai.util.AAIConfig; import org.onap.aai.util.AAIConstants; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.context.annotation.PropertySource; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component; -import com.att.eelf.configuration.Configuration; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import org.apache.commons.io.comparator.LastModifiedFileComparator; -import org.apache.commons.io.filefilter.DirectoryFileFilter; -import org.apache.commons.io.filefilter.FileFileFilter; -import org.apache.commons.io.FileUtils; -import org.apache.commons.io.filefilter.RegexFileFilter; - /** * DataImportTasks * @@ -76,24 +75,24 @@ public class DataImportTasks { props.setProperty(Configuration.PROPERTY_LOGGING_FILE_PATH, AAIConstants.AAI_HOME_BUNDLECONFIG); LOGGER = LoggerFactory.getLogger(DataImportTasks.class); } + /** * Scheduled task to invoke importTask */ - @Scheduled(cron = "${dataimporttask.cron}" ) + @Scheduled(cron = "${dataimporttask.cron}") public void import1() { try { importTask(); - } - catch (Exception e) { + } catch (Exception e) { } } + /** * The importTask method. * * @throws AAIException, Exception */ - public void importTask() throws AAIException, Exception { - + public void importTask() throws AAIException, Exception { if (AAIConfig.get("aai.dataimport.enable").equalsIgnoreCase("false")) { LOGGER.info("Data Import is not enabled"); @@ -107,12 +106,12 @@ public class DataImportTasks { LOGGER.info("Started importTask: " + dateFormat.format(new Date())); - String inputLocation = AAIConstants.AAI_HOME_BUNDLECONFIG + AAIConfig.get("aai.dataimport.input.location"); + String inputLocation = AAIConstants.AAI_HOME_BUNDLECONFIG + AAIConfig.get("aai.dataimport.input.location"); // Check that the input location exist File targetDirFile = new File(inputLocation); - if ( targetDirFile.exists() ) { - //Delete any existing payload file directories + if (targetDirFile.exists()) { + // Delete any existing payload file directories deletePayload(targetDirFile); } @@ -120,22 +119,25 @@ public class DataImportTasks { if (payloadFile == null) return; // already logged error in the findExportedPayload function - if ( unpackPayloadFile(payloadFile.getAbsolutePath())) { + if (unpackPayloadFile(payloadFile.getAbsolutePath())) { String[] command = new String[2]; - command[0] = AAIConstants.AAI_HOME + AAIConstants.AAI_FILESEP + "bin" + AAIConstants.AAI_FILESEP + "install" + AAIConstants.AAI_FILESEP + "addManualData.sh"; + command[0] = AAIConstants.AAI_HOME + AAIConstants.AAI_FILESEP + "bin" + AAIConstants.AAI_FILESEP + "install" + + AAIConstants.AAI_FILESEP + "addManualData.sh"; command[1] = "tenant_isolation"; runAddManualDataScript(command); } - //clean up + // clean up payloadFile.delete(); } + /** * The isDataImportRunning method, checks if the data import task was started separately via command line + * * @return true if another process is running, false if not */ - private static boolean isDataImportRunning(){ + private static boolean isDataImportRunning() { Process process = null; @@ -146,18 +148,19 @@ public class DataImportTasks { InputStreamReader isr = new InputStreamReader(is); BufferedReader br = new BufferedReader(isr); - while (br.readLine() != null){ + while (br.readLine() != null) { count++; } int exitVal = process.waitFor(); LOGGER.info("Check if dataImport is running returned: " + exitVal); } catch (Exception e) { - ErrorLogHelper.logError("AAI_8002", "Exception while running the check to see if dataImport is running "+ e.getMessage()); - LOGGER.info("Exception while running the check to see if dataImport is running "+ e.getMessage()); + ErrorLogHelper.logError("AAI_8002", + "Exception while running the check to see if dataImport is running " + e.getMessage()); + LOGGER.info("Exception while running the check to see if dataImport is running " + e.getMessage()); } - if(count > 0){ + if (count > 0) { return true; } else { return false; @@ -168,57 +171,55 @@ public class DataImportTasks { * The findPayExportedPayload method tries to find the latest exported payload. * Also deletes the old files if any or any other file in this directory */ - private static File findExportedPayload() throws AAIException { + private static File findExportedPayload() throws AAIException { String targetDir = AAIConstants.AAI_HOME_BUNDLECONFIG + AAIConfig.get("aai.dataimport.input.location"); File targetDirFile = new File(targetDir); File payloadFile = null; File[] allFilesArr = targetDirFile.listFiles((FileFilter) FileFileFilter.FILE); - if ( allFilesArr == null || allFilesArr.length == 0 ) { + if (allFilesArr == null || allFilesArr.length == 0) { ErrorLogHelper.logError("AAI_8001", "Unable to find payload file at " + targetDir); - LOGGER.info ("Unable to find payload at " + targetDir); + LOGGER.info("Unable to find payload at " + targetDir); return null; } - if ( allFilesArr.length > 1 ) { + if (allFilesArr.length > 1) { Arrays.sort(allFilesArr, LastModifiedFileComparator.LASTMODIFIED_REVERSE); // get the latest payload file boolean foundTheLatestPayload = false; for (File f : allFilesArr) { - if (!foundTheLatestPayload && isTargzExtension(f.getAbsolutePath())) { - payloadFile = f; - foundTheLatestPayload = true; - } - else // delete all files except the latest payload file! - f.delete(); + if (!foundTheLatestPayload && isTargzExtension(f.getAbsolutePath())) { + payloadFile = f; + foundTheLatestPayload = true; + } else // delete all files except the latest payload file! + f.delete(); } - } - else { + } else { if (isTargzExtension(allFilesArr[0].getAbsolutePath())) payloadFile = allFilesArr[0]; } - return payloadFile; + return payloadFile; } /** * The deletePayload method deletes all the payload files that it finds at targetDirectory + * * @param targetDirFile the directory that contains payload files * @throws AAIException */ private static void deletePayload(File targetDirFile) throws AAIException { - File[] allFilesArr = targetDirFile.listFiles((FileFilter)DirectoryFileFilter.DIRECTORY); - if ( allFilesArr == null || allFilesArr.length == 0 ) { - LOGGER.info ("No payload files found at " + targetDirFile.getPath()); + File[] allFilesArr = targetDirFile.listFiles((FileFilter) DirectoryFileFilter.DIRECTORY); + if (allFilesArr == null || allFilesArr.length == 0) { + LOGGER.info("No payload files found at " + targetDirFile.getPath()); return; } - for ( File f : allFilesArr ) { + for (File f : allFilesArr) { try { FileUtils.deleteDirectory(f); - } - catch (IOException e) { + } catch (IOException e) { - LOGGER.info ("Unable to delete directory " + f.getAbsolutePath() + " " + e.getMessage()); + LOGGER.info("Unable to delete directory " + f.getAbsolutePath() + " " + e.getMessage()); } } @@ -227,35 +228,37 @@ public class DataImportTasks { /** * The isDataImportRunning method, checks if the data import task was started separately via command line + * * @return true if another process is running, false if not */ - private static boolean unpackPayloadFile(String payLoadFileName){ + private static boolean unpackPayloadFile(String payLoadFileName) { Process process = null; try { - process = new ProcessBuilder().command("bash", "-c", "gzip –d < " + payLoadFileName + " | tar xf -").start(); + process = + new ProcessBuilder().command("bash", "-c", "gzip –d < " + payLoadFileName + " | tar xf -").start(); int exitVal = process.waitFor(); LOGGER.info("gzip -d returned: " + exitVal); } catch (Exception e) { - ErrorLogHelper.logError("AAI_8002", "Exception while running the unzip "+ e.getMessage()); - LOGGER.info("Exception while running the unzip "+ e.getMessage()); + ErrorLogHelper.logError("AAI_8002", "Exception while running the unzip " + e.getMessage()); + LOGGER.info("Exception while running the unzip " + e.getMessage()); return false; } /* - if (payLoadFileName.indexOf(".") > 0) - payLoadFileName = payLoadFileName.substring(0, payLoadFileName.lastIndexOf(".")); - - try { - process = new ProcessBuilder().command("bash", "-c", "tar xf " + payLoadFileName).start(); - int exitVal = process.waitFor(); - LOGGER.info("tar xf returned: " + exitVal); - } catch (Exception e) { - ErrorLogHelper.logError("AAI_8002", "Exception while running the tar xf "+ e.getMessage()); - LOGGER.info("Exception while running the tar xf "+ e.getMessage()); - return false; - } - */ + * if (payLoadFileName.indexOf(".") > 0) + * payLoadFileName = payLoadFileName.substring(0, payLoadFileName.lastIndexOf(".")); + * + * try { + * process = new ProcessBuilder().command("bash", "-c", "tar xf " + payLoadFileName).start(); + * int exitVal = process.waitFor(); + * LOGGER.info("tar xf returned: " + exitVal); + * } catch (Exception e) { + * ErrorLogHelper.logError("AAI_8002", "Exception while running the tar xf "+ e.getMessage()); + * LOGGER.info("Exception while running the tar xf "+ e.getMessage()); + * return false; + * } + */ return true; } @@ -271,16 +274,17 @@ public class DataImportTasks { /** * The runAddManualDataScript method runs a shell script/command with a variable number of arguments + * * @param script The script/command arguments */ - private static void runAddManualDataScript(String ...script ) { + private static void runAddManualDataScript(String... script) { Process process = null; try { process = new ProcessBuilder().command(script).start(); int exitVal = process.waitFor(); LOGGER.info("addManualData.sh returned: " + exitVal); } catch (Exception e) { - ErrorLogHelper.logError("AAI_8002", "Exception while running addManualData.sh "+ e.getMessage()); + ErrorLogHelper.logError("AAI_8002", "Exception while running addManualData.sh " + e.getMessage()); LOGGER.info("Exception while running addManualData.sh" + e.getMessage()); } diff --git a/aai-resources/src/main/java/org/onap/aai/config/ErrorHandler.java b/aai-resources/src/main/java/org/onap/aai/config/ErrorHandler.java index 22e12a6..98fa14b 100644 --- a/aai-resources/src/main/java/org/onap/aai/config/ErrorHandler.java +++ b/aai-resources/src/main/java/org/onap/aai/config/ErrorHandler.java @@ -17,23 +17,25 @@ * limitations under the License. * ============LICENSE_END========================================================= */ + package org.onap.aai.config; -import org.onap.aai.exceptions.AAIException; -import org.onap.aai.logging.ErrorLogHelper; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.core.annotation.Order; -import org.springframework.stereotype.Component; -import org.springframework.web.filter.OncePerRequestFilter; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; import javax.servlet.FilterChain; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.ws.rs.core.MediaType; -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; + +import org.onap.aai.exceptions.AAIException; +import org.onap.aai.logging.ErrorLogHelper; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; +import org.springframework.web.filter.OncePerRequestFilter; /** * Responsible for dealing with uri that doesn't start with basePath @@ -46,15 +48,16 @@ public class ErrorHandler extends OncePerRequestFilter { private String basePath; - public ErrorHandler(@Value("${schema.uri.base.path}") String basePath){ + public ErrorHandler(@Value("${schema.uri.base.path}") String basePath) { this.basePath = basePath; - if(!basePath.endsWith("/")){ + if (!basePath.endsWith("/")) { this.basePath = basePath + "/"; } } @Override - protected void doFilterInternal(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, FilterChain filterChain) throws ServletException, IOException { + protected void doFilterInternal(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, + FilterChain filterChain) throws ServletException, IOException { String uri = httpServletRequest.getRequestURI(); diff --git a/aai-resources/src/main/java/org/onap/aai/config/JettyPasswordDecoder.java b/aai-resources/src/main/java/org/onap/aai/config/JettyPasswordDecoder.java index 944f951..833fd56 100644 --- a/aai-resources/src/main/java/org/onap/aai/config/JettyPasswordDecoder.java +++ b/aai-resources/src/main/java/org/onap/aai/config/JettyPasswordDecoder.java @@ -17,6 +17,7 @@ * limitations under the License. * ============LICENSE_END========================================================= */ + package org.onap.aai.config; import org.eclipse.jetty.util.security.Password; diff --git a/aai-resources/src/main/java/org/onap/aai/config/PasswordDecoder.java b/aai-resources/src/main/java/org/onap/aai/config/PasswordDecoder.java index 0dcb845..8ad75d9 100644 --- a/aai-resources/src/main/java/org/onap/aai/config/PasswordDecoder.java +++ b/aai-resources/src/main/java/org/onap/aai/config/PasswordDecoder.java @@ -17,6 +17,7 @@ * limitations under the License. * ============LICENSE_END========================================================= */ + package org.onap.aai.config; public interface PasswordDecoder { diff --git a/aai-resources/src/main/java/org/onap/aai/config/PropertyPasswordConfiguration.java b/aai-resources/src/main/java/org/onap/aai/config/PropertyPasswordConfiguration.java index ae77e5a..4c92eb2 100644 --- a/aai-resources/src/main/java/org/onap/aai/config/PropertyPasswordConfiguration.java +++ b/aai-resources/src/main/java/org/onap/aai/config/PropertyPasswordConfiguration.java @@ -17,8 +17,12 @@ * limitations under the License. * ============LICENSE_END========================================================= */ + package org.onap.aai.config; +import com.att.eelf.configuration.EELFLogger; +import com.att.eelf.configuration.EELFManager; + import java.io.File; import java.io.FileInputStream; import java.io.IOException; @@ -37,9 +41,6 @@ import org.springframework.core.env.EnumerablePropertySource; import org.springframework.core.env.MapPropertySource; import org.springframework.core.env.PropertySource; -import com.att.eelf.configuration.EELFLogger; -import com.att.eelf.configuration.EELFManager; - public class PropertyPasswordConfiguration implements ApplicationContextInitializer { private static final Pattern decodePasswordPattern = Pattern.compile("password\\((.*?)\\)"); @@ -116,7 +117,8 @@ public class PropertyPasswordConfiguration implements ApplicationContextInitiali Map propertyOverrides = new LinkedHashMap<>(); decodePasswords(propertySource, propertyOverrides); if (!propertyOverrides.isEmpty()) { - PropertySource decodedProperties = new MapPropertySource("decoded "+ propertySource.getName(), propertyOverrides); + PropertySource decodedProperties = + new MapPropertySource("decoded " + propertySource.getName(), propertyOverrides); environment.getPropertySources().addBefore(propertySource.getName(), decodedProperties); } @@ -142,7 +144,8 @@ public class PropertyPasswordConfiguration implements ApplicationContextInitiali } private String decodePasswordsInString(String input) { - if (input == null) return null; + if (input == null) + return null; StringBuffer output = new StringBuffer(); Matcher matcher = decodePasswordPattern.matcher(input); while (matcher.find()) { diff --git a/aai-resources/src/main/java/org/onap/aai/dbgen/tags/Command.java b/aai-resources/src/main/java/org/onap/aai/dbgen/tags/Command.java index bc18047..25f93d2 100644 --- a/aai-resources/src/main/java/org/onap/aai/dbgen/tags/Command.java +++ b/aai-resources/src/main/java/org/onap/aai/dbgen/tags/Command.java @@ -17,9 +17,10 @@ * limitations under the License. * ============LICENSE_END========================================================= */ + package org.onap.aai.dbgen.tags; @FunctionalInterface interface Command { - public abstract void execute() throws Exception; + public abstract void execute() throws Exception; } diff --git a/aai-resources/src/main/java/org/onap/aai/interceptors/AAIContainerFilter.java b/aai-resources/src/main/java/org/onap/aai/interceptors/AAIContainerFilter.java index f70febf..0f9d1bf 100644 --- a/aai-resources/src/main/java/org/onap/aai/interceptors/AAIContainerFilter.java +++ b/aai-resources/src/main/java/org/onap/aai/interceptors/AAIContainerFilter.java @@ -17,25 +17,26 @@ * limitations under the License. * ============LICENSE_END========================================================= */ + package org.onap.aai.interceptors; import java.util.UUID; import org.onap.aai.util.FormatDate; -public abstract class AAIContainerFilter { - - protected String genDate() { - FormatDate fd = new FormatDate("YYMMdd-HH:mm:ss:SSS"); - return fd.getDateTime(); - } - - protected boolean isValidUUID(String transId) { - try { - UUID.fromString(transId); - } catch (IllegalArgumentException e) { - return false; - } - return true; - } +public abstract class AAIContainerFilter { + + protected String genDate() { + FormatDate fd = new FormatDate("YYMMdd-HH:mm:ss:SSS"); + return fd.getDateTime(); + } + + protected boolean isValidUUID(String transId) { + try { + UUID.fromString(transId); + } catch (IllegalArgumentException e) { + return false; + } + return true; + } } diff --git a/aai-resources/src/main/java/org/onap/aai/interceptors/AAIHeaderProperties.java b/aai-resources/src/main/java/org/onap/aai/interceptors/AAIHeaderProperties.java index 8783ed2..461dae3 100644 --- a/aai-resources/src/main/java/org/onap/aai/interceptors/AAIHeaderProperties.java +++ b/aai-resources/src/main/java/org/onap/aai/interceptors/AAIHeaderProperties.java @@ -17,25 +17,27 @@ * limitations under the License. * ============LICENSE_END========================================================= */ + package org.onap.aai.interceptors; public final class AAIHeaderProperties { - - private AAIHeaderProperties(){} - - public static final String REQUEST_CONTEXT = "aai-request-context"; - - public static final String HTTP_METHOD_OVERRIDE = "X-HTTP-Method-Override"; - - public static final String TRANSACTION_ID = "X-TransactionId"; - - public static final String FROM_APP_ID = "X-FromAppId"; - - public static final String SOURCE_OF_TRUTH = "X-SourceOfTruth"; - - public static final String AAI_TX_ID = "X-AAI-TXID"; - - public static final String AAI_REQUEST = "X-REQUEST"; - - public static final String AAI_REQUEST_TS = "X-REQUEST-TS"; + + private AAIHeaderProperties() { + } + + public static final String REQUEST_CONTEXT = "aai-request-context"; + + public static final String HTTP_METHOD_OVERRIDE = "X-HTTP-Method-Override"; + + public static final String TRANSACTION_ID = "X-TransactionId"; + + public static final String FROM_APP_ID = "X-FromAppId"; + + public static final String SOURCE_OF_TRUTH = "X-SourceOfTruth"; + + public static final String AAI_TX_ID = "X-AAI-TXID"; + + public static final String AAI_REQUEST = "X-REQUEST"; + + public static final String AAI_REQUEST_TS = "X-REQUEST-TS"; } diff --git a/aai-resources/src/main/java/org/onap/aai/interceptors/package-info.java b/aai-resources/src/main/java/org/onap/aai/interceptors/package-info.java index ee9c334..7bad8f2 100644 --- a/aai-resources/src/main/java/org/onap/aai/interceptors/package-info.java +++ b/aai-resources/src/main/java/org/onap/aai/interceptors/package-info.java @@ -26,11 +26,12 @@ * *
  *     
- *         @Priority(AAIRequestFilterPriority.YOUR_PRIORITY)
+ *         @Priority(AAIRequestFilterPriority.YOUR_PRIORITY)
  *         public class YourInterceptor extends AAIContainerFilter implements ContainerRequestFilter {
  *
  *         }
  *     
  * 
*/ -package org.onap.aai.interceptors; \ No newline at end of file + +package org.onap.aai.interceptors; diff --git a/aai-resources/src/main/java/org/onap/aai/interceptors/post/AAIResponseFilterPriority.java b/aai-resources/src/main/java/org/onap/aai/interceptors/post/AAIResponseFilterPriority.java index 146f847..feec781 100644 --- a/aai-resources/src/main/java/org/onap/aai/interceptors/post/AAIResponseFilterPriority.java +++ b/aai-resources/src/main/java/org/onap/aai/interceptors/post/AAIResponseFilterPriority.java @@ -17,6 +17,7 @@ * limitations under the License. * ============LICENSE_END========================================================= */ + package org.onap.aai.interceptors.post; /** @@ -26,15 +27,16 @@ package org.onap.aai.interceptors.post; * and INVALID_RESPONSE_STATUS */ public final class AAIResponseFilterPriority { - - private AAIResponseFilterPriority() {} - public static final int INVALID_RESPONSE_STATUS = 1000; + private AAIResponseFilterPriority() { + } + + public static final int INVALID_RESPONSE_STATUS = 1000; - public static final int RESET_LOGGING_CONTEXT = 2000; + public static final int RESET_LOGGING_CONTEXT = 2000; - public static final int RESPONSE_TRANS_LOGGING = 3000; + public static final int RESPONSE_TRANS_LOGGING = 3000; - public static final int HEADER_MANIPULATION = 4000; + public static final int HEADER_MANIPULATION = 4000; } diff --git a/aai-resources/src/main/java/org/onap/aai/interceptors/post/InvalidResponseStatus.java b/aai-resources/src/main/java/org/onap/aai/interceptors/post/InvalidResponseStatus.java index 7fd0b9c..61ada79 100644 --- a/aai-resources/src/main/java/org/onap/aai/interceptors/post/InvalidResponseStatus.java +++ b/aai-resources/src/main/java/org/onap/aai/interceptors/post/InvalidResponseStatus.java @@ -17,49 +17,51 @@ * limitations under the License. * ============LICENSE_END========================================================= */ + package org.onap.aai.interceptors.post; -import org.onap.aai.exceptions.AAIException; -import org.onap.aai.interceptors.AAIContainerFilter; -import org.onap.aai.logging.ErrorLogHelper; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; import javax.annotation.Priority; import javax.ws.rs.container.ContainerRequestContext; import javax.ws.rs.container.ContainerResponseContext; import javax.ws.rs.container.ContainerResponseFilter; import javax.ws.rs.core.MediaType; -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; + +import org.onap.aai.exceptions.AAIException; +import org.onap.aai.interceptors.AAIContainerFilter; +import org.onap.aai.logging.ErrorLogHelper; @Priority(AAIResponseFilterPriority.INVALID_RESPONSE_STATUS) public class InvalidResponseStatus extends AAIContainerFilter implements ContainerResponseFilter { - @Override - public void filter(ContainerRequestContext requestContext, ContainerResponseContext responseContext) - throws IOException { + @Override + public void filter(ContainerRequestContext requestContext, ContainerResponseContext responseContext) + throws IOException { - if(responseContext.getStatus() == 405){ + if (responseContext.getStatus() == 405) { - responseContext.setStatus(400); - AAIException e = new AAIException("AAI_3012"); - ArrayList templateVars = new ArrayList<>(); + responseContext.setStatus(400); + AAIException e = new AAIException("AAI_3012"); + ArrayList templateVars = new ArrayList<>(); - List mediaTypeList = new ArrayList<>(); + List mediaTypeList = new ArrayList<>(); - String contentType = responseContext.getHeaderString("Content-Type"); + String contentType = responseContext.getHeaderString("Content-Type"); - if (contentType == null) { - mediaTypeList.add(MediaType.APPLICATION_XML_TYPE); - } else { - mediaTypeList.add(MediaType.valueOf(contentType)); - } + if (contentType == null) { + mediaTypeList.add(MediaType.APPLICATION_XML_TYPE); + } else { + mediaTypeList.add(MediaType.valueOf(contentType)); + } - String message = ErrorLogHelper.getRESTAPIErrorResponse(mediaTypeList, e, templateVars); + String message = ErrorLogHelper.getRESTAPIErrorResponse(mediaTypeList, e, templateVars); - responseContext.setEntity(message); - } + responseContext.setEntity(message); + } - } + } } diff --git a/aai-resources/src/main/java/org/onap/aai/interceptors/post/ResponseHeaderManipulation.java b/aai-resources/src/main/java/org/onap/aai/interceptors/post/ResponseHeaderManipulation.java index 3809540..93e213e 100644 --- a/aai-resources/src/main/java/org/onap/aai/interceptors/post/ResponseHeaderManipulation.java +++ b/aai-resources/src/main/java/org/onap/aai/interceptors/post/ResponseHeaderManipulation.java @@ -17,6 +17,7 @@ * limitations under the License. * ============LICENSE_END========================================================= */ + package org.onap.aai.interceptors.post; import java.io.IOException; @@ -33,33 +34,34 @@ import org.onap.aai.interceptors.AAIHeaderProperties; @Priority(AAIResponseFilterPriority.HEADER_MANIPULATION) public class ResponseHeaderManipulation extends AAIContainerFilter implements ContainerResponseFilter { - private static final String DEFAULT_XML_TYPE = MediaType.APPLICATION_XML; + private static final String DEFAULT_XML_TYPE = MediaType.APPLICATION_XML; - @Override - public void filter(ContainerRequestContext requestContext, ContainerResponseContext responseContext) - throws IOException { + @Override + public void filter(ContainerRequestContext requestContext, ContainerResponseContext responseContext) + throws IOException { - updateResponseHeaders(requestContext, responseContext); + updateResponseHeaders(requestContext, responseContext); - } + } - private void updateResponseHeaders(ContainerRequestContext requestContext, - ContainerResponseContext responseContext) { + private void updateResponseHeaders(ContainerRequestContext requestContext, + ContainerResponseContext responseContext) { - responseContext.getHeaders().add(AAIHeaderProperties.AAI_TX_ID, requestContext.getProperty(AAIHeaderProperties.AAI_TX_ID)); + responseContext.getHeaders().add(AAIHeaderProperties.AAI_TX_ID, + requestContext.getProperty(AAIHeaderProperties.AAI_TX_ID)); - String responseContentType = responseContext.getHeaderString("Content-Type"); + String responseContentType = responseContext.getHeaderString("Content-Type"); - if(responseContentType == null){ - String acceptType = requestContext.getHeaderString("Accept"); + if (responseContentType == null) { + String acceptType = requestContext.getHeaderString("Accept"); - if(acceptType == null || "*/*".equals(acceptType)){ - responseContext.getHeaders().putSingle("Content-Type", DEFAULT_XML_TYPE); - } else { - responseContext.getHeaders().putSingle("Content-Type", acceptType); - } - } + if (acceptType == null || "*/*".equals(acceptType)) { + responseContext.getHeaders().putSingle("Content-Type", DEFAULT_XML_TYPE); + } else { + responseContext.getHeaders().putSingle("Content-Type", acceptType); + } + } - } + } } diff --git a/aai-resources/src/main/java/org/onap/aai/interceptors/post/ResponseTransactionLogging.java b/aai-resources/src/main/java/org/onap/aai/interceptors/post/ResponseTransactionLogging.java index 2a573b3..cb193af 100644 --- a/aai-resources/src/main/java/org/onap/aai/interceptors/post/ResponseTransactionLogging.java +++ b/aai-resources/src/main/java/org/onap/aai/interceptors/post/ResponseTransactionLogging.java @@ -17,17 +17,14 @@ * limitations under the License. * ============LICENSE_END========================================================= */ + package org.onap.aai.interceptors.post; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import com.google.gson.JsonObject; -import org.onap.aai.exceptions.AAIException; -import org.onap.aai.interceptors.AAIContainerFilter; -import org.onap.aai.interceptors.AAIHeaderProperties; -import org.onap.aai.logging.ErrorLogHelper; -import org.onap.aai.util.AAIConfig; -import org.springframework.beans.factory.annotation.Autowired; + +import java.io.IOException; +import java.util.Objects; +import java.util.Optional; import javax.annotation.Priority; import javax.servlet.http.HttpServletResponse; @@ -35,9 +32,15 @@ import javax.ws.rs.HttpMethod; import javax.ws.rs.container.ContainerRequestContext; import javax.ws.rs.container.ContainerResponseContext; import javax.ws.rs.container.ContainerResponseFilter; -import java.io.IOException; -import java.util.Objects; -import java.util.Optional; + +import org.onap.aai.exceptions.AAIException; +import org.onap.aai.interceptors.AAIContainerFilter; +import org.onap.aai.interceptors.AAIHeaderProperties; +import org.onap.aai.logging.ErrorLogHelper; +import org.onap.aai.util.AAIConfig; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; @Priority(AAIResponseFilterPriority.RESPONSE_TRANS_LOGGING) public class ResponseTransactionLogging extends AAIContainerFilter implements ContainerResponseFilter { @@ -49,7 +52,7 @@ public class ResponseTransactionLogging extends AAIContainerFilter implements Co @Override public void filter(ContainerRequestContext requestContext, ContainerResponseContext responseContext) - throws IOException { + throws IOException { this.transLogging(requestContext, responseContext); @@ -69,14 +72,13 @@ public class ResponseTransactionLogging extends AAIContainerFilter implements Co String httpMethod = requestContext.getMethod(); - if(Boolean.parseBoolean(logValue)){ + if (Boolean.parseBoolean(logValue)) { String transId = requestContext.getHeaderString(AAIHeaderProperties.TRANSACTION_ID); String fromAppId = requestContext.getHeaderString(AAIHeaderProperties.FROM_APP_ID); String fullUri = requestContext.getUriInfo().getRequestUri().toString(); String requestTs = (String) requestContext.getProperty(AAIHeaderProperties.AAI_REQUEST_TS); - String status = Integer.toString(responseContext.getStatus()); String request = (String) requestContext.getProperty(AAIHeaderProperties.AAI_REQUEST); @@ -85,7 +87,6 @@ public class ResponseTransactionLogging extends AAIContainerFilter implements Co response = this.getResponseString(responseContext); } - JsonObject logEntry = new JsonObject(); logEntry.addProperty("transactionId", transId); logEntry.addProperty("status", status); @@ -95,7 +96,7 @@ public class ResponseTransactionLogging extends AAIContainerFilter implements Co logEntry.addProperty("resourceId", fullUri); logEntry.addProperty("resourceType", httpMethod); logEntry.addProperty("rqstBuf", Objects.toString(request, "")); - if (response != null ) { + if (response != null) { logEntry.addProperty("respBuf", Objects.toString(response)); } diff --git a/aai-resources/src/main/java/org/onap/aai/interceptors/pre/AAIRequestFilterPriority.java b/aai-resources/src/main/java/org/onap/aai/interceptors/pre/AAIRequestFilterPriority.java index c3d9d3b..8dff548 100644 --- a/aai-resources/src/main/java/org/onap/aai/interceptors/pre/AAIRequestFilterPriority.java +++ b/aai-resources/src/main/java/org/onap/aai/interceptors/pre/AAIRequestFilterPriority.java @@ -17,30 +17,32 @@ * limitations under the License. * ============LICENSE_END========================================================= */ + package org.onap.aai.interceptors.pre; public final class AAIRequestFilterPriority { - - private AAIRequestFilterPriority() {} - - public static final int REQUEST_TRANS_LOGGING = 1000; - - public static final int HEADER_VALIDATION = 2000; - public static final int SET_LOGGING_CONTEXT = 3000; + private AAIRequestFilterPriority() { + } + + public static final int REQUEST_TRANS_LOGGING = 1000; + + public static final int HEADER_VALIDATION = 2000; + + public static final int SET_LOGGING_CONTEXT = 3000; - public static final int HTTP_HEADER = 4000; + public static final int HTTP_HEADER = 4000; - public static final int LATEST = 4250; + public static final int LATEST = 4250; - public static final int AUTHORIZATION = 4500; + public static final int AUTHORIZATION = 4500; - public static final int RETIRED_SERVICE = 5000; + public static final int RETIRED_SERVICE = 5000; - public static final int VERSION = 5500; + public static final int VERSION = 5500; - public static final int HEADER_MANIPULATION = 6000; + public static final int HEADER_MANIPULATION = 6000; - public static final int REQUEST_MODIFICATION = 7000; + public static final int REQUEST_MODIFICATION = 7000; } diff --git a/aai-resources/src/main/java/org/onap/aai/interceptors/pre/HeaderValidation.java b/aai-resources/src/main/java/org/onap/aai/interceptors/pre/HeaderValidation.java index 8113fa7..f0eaac9 100644 --- a/aai-resources/src/main/java/org/onap/aai/interceptors/pre/HeaderValidation.java +++ b/aai-resources/src/main/java/org/onap/aai/interceptors/pre/HeaderValidation.java @@ -17,6 +17,7 @@ * limitations under the License. * ============LICENSE_END========================================================= */ + package org.onap.aai.interceptors.pre; import java.io.IOException; @@ -45,111 +46,111 @@ import org.onap.logging.ref.slf4j.ONAPLogConstants; @Priority(AAIRequestFilterPriority.HEADER_VALIDATION) public class HeaderValidation extends AAIContainerFilter implements ContainerRequestFilter { - @Override - public void filter(ContainerRequestContext requestContext) throws IOException { - - Optional oResp; - List acceptHeaderValues = requestContext.getAcceptableMediaTypes(); - - String fromAppId = getPartnerName(requestContext); - oResp = this.validateHeaderValuePresence(fromAppId, "AAI_4009", acceptHeaderValues); - if (oResp.isPresent()) { - requestContext.abortWith(oResp.get()); - return; - } - - String transId = getRequestId(requestContext); - oResp = this.validateHeaderValuePresence(transId, "AAI_4010", acceptHeaderValues); - if (oResp.isPresent()) { - requestContext.abortWith(oResp.get()); - return; - } - } - - private Optional validateHeaderValuePresence(String value, String errorCode, - List acceptHeaderValues) { - Response response = null; - AAIException aaie; - if (value == null || value.isEmpty()) { - aaie = new AAIException(errorCode); - return Optional.of(Response.status(aaie.getErrorObject().getHTTPResponseCode()) - .entity(ErrorLogHelper.getRESTAPIErrorResponse(acceptHeaderValues, aaie, new ArrayList<>())) - .build()); - } - - return Optional.ofNullable(response); - } - public String getRequestId(ContainerRequestContext requestContext) { - String requestId = requestContext.getHeaderString(ONAPLogConstants.Headers.REQUEST_ID); - if (requestId == null || requestId.isEmpty()) { - requestId = requestContext.getHeaderString(Constants.HttpHeaders.HEADER_REQUEST_ID); - if (requestId == null || requestId.isEmpty()) { - requestId = requestContext.getHeaderString(Constants.HttpHeaders.TRANSACTION_ID); - if (requestId == null || requestId.isEmpty()) { - requestId = requestContext.getHeaderString(Constants.HttpHeaders.ECOMP_REQUEST_ID); - if (requestId == null || requestId.isEmpty()) { - return requestId; - } - } - } - } - if (requestContext.getHeaders().get(ONAPLogConstants.Headers.REQUEST_ID) != null) { - requestContext.getHeaders().get(ONAPLogConstants.Headers.REQUEST_ID).clear(); - } - if (requestContext.getHeaders().get(Constants.HttpHeaders.TRANSACTION_ID) != null) { - requestContext.getHeaders().get(Constants.HttpHeaders.TRANSACTION_ID).clear(); - } - if (requestContext.getHeaders().get(Constants.HttpHeaders.HEADER_REQUEST_ID) != null) { - requestContext.getHeaders().get(Constants.HttpHeaders.HEADER_REQUEST_ID).clear(); - } - if (requestContext.getHeaders().get(Constants.HttpHeaders.ECOMP_REQUEST_ID) != null) { - requestContext.getHeaders().get(Constants.HttpHeaders.ECOMP_REQUEST_ID).clear(); - } - requestContext.getHeaders().add(Constants.HttpHeaders.TRANSACTION_ID, requestId); - - return requestId; - } - - public String getPartnerName(ContainerRequestContext requestContext) { - - // CDM header overrides everything else for source of truth - String sourceOfTruth = requestContext.getHeaderString(AAIHeaderProperties.SOURCE_OF_TRUTH); - String partnerName = requestContext.getHeaderString(ONAPLogConstants.Headers.PARTNER_NAME); - if ( sourceOfTruth == null || sourceOfTruth.isEmpty()) { - - if (partnerName != null && !(partnerName.isEmpty())) { - String components[] = partnerName.split("\\."); - if (components.length > 1) { - if (!(ONAPComponents.AAI.toString().equalsIgnoreCase(components[0]))) { - sourceOfTruth = components[0]; - } else { - // request is coming internally from AAI, check X-FromAppId - partnerName = null; - } - } - } - if (sourceOfTruth == null || sourceOfTruth.isEmpty()) { - if (partnerName == null || (partnerName.isEmpty())) { - partnerName = requestContext.getHeaderString(AAIHeaderProperties.FROM_APP_ID); - if (partnerName == null || (partnerName.isEmpty())) { - return partnerName; - } - } - } - } - if (requestContext.getHeaders().get(ONAPLogConstants.Headers.PARTNER_NAME) != null) { - requestContext.getHeaders().get(ONAPLogConstants.Headers.PARTNER_NAME).clear(); - } - if (requestContext.getHeaders().get(AAIHeaderProperties.FROM_APP_ID) != null) { - requestContext.getHeaders().get(AAIHeaderProperties.FROM_APP_ID).clear(); - } - if ((sourceOfTruth != null) && !(sourceOfTruth.isEmpty())) { - requestContext.getHeaders().add(AAIHeaderProperties.FROM_APP_ID, sourceOfTruth); - partnerName = sourceOfTruth; - } - else { - requestContext.getHeaders().add(AAIHeaderProperties.FROM_APP_ID, partnerName); - } - return partnerName; - } + @Override + public void filter(ContainerRequestContext requestContext) throws IOException { + + Optional oResp; + List acceptHeaderValues = requestContext.getAcceptableMediaTypes(); + + String fromAppId = getPartnerName(requestContext); + oResp = this.validateHeaderValuePresence(fromAppId, "AAI_4009", acceptHeaderValues); + if (oResp.isPresent()) { + requestContext.abortWith(oResp.get()); + return; + } + + String transId = getRequestId(requestContext); + oResp = this.validateHeaderValuePresence(transId, "AAI_4010", acceptHeaderValues); + if (oResp.isPresent()) { + requestContext.abortWith(oResp.get()); + return; + } + } + + private Optional validateHeaderValuePresence(String value, String errorCode, + List acceptHeaderValues) { + Response response = null; + AAIException aaie; + if (value == null || value.isEmpty()) { + aaie = new AAIException(errorCode); + return Optional.of(Response.status(aaie.getErrorObject().getHTTPResponseCode()) + .entity(ErrorLogHelper.getRESTAPIErrorResponse(acceptHeaderValues, aaie, new ArrayList<>())) + .build()); + } + + return Optional.ofNullable(response); + } + + public String getRequestId(ContainerRequestContext requestContext) { + String requestId = requestContext.getHeaderString(ONAPLogConstants.Headers.REQUEST_ID); + if (requestId == null || requestId.isEmpty()) { + requestId = requestContext.getHeaderString(Constants.HttpHeaders.HEADER_REQUEST_ID); + if (requestId == null || requestId.isEmpty()) { + requestId = requestContext.getHeaderString(Constants.HttpHeaders.TRANSACTION_ID); + if (requestId == null || requestId.isEmpty()) { + requestId = requestContext.getHeaderString(Constants.HttpHeaders.ECOMP_REQUEST_ID); + if (requestId == null || requestId.isEmpty()) { + return requestId; + } + } + } + } + if (requestContext.getHeaders().get(ONAPLogConstants.Headers.REQUEST_ID) != null) { + requestContext.getHeaders().get(ONAPLogConstants.Headers.REQUEST_ID).clear(); + } + if (requestContext.getHeaders().get(Constants.HttpHeaders.TRANSACTION_ID) != null) { + requestContext.getHeaders().get(Constants.HttpHeaders.TRANSACTION_ID).clear(); + } + if (requestContext.getHeaders().get(Constants.HttpHeaders.HEADER_REQUEST_ID) != null) { + requestContext.getHeaders().get(Constants.HttpHeaders.HEADER_REQUEST_ID).clear(); + } + if (requestContext.getHeaders().get(Constants.HttpHeaders.ECOMP_REQUEST_ID) != null) { + requestContext.getHeaders().get(Constants.HttpHeaders.ECOMP_REQUEST_ID).clear(); + } + requestContext.getHeaders().add(Constants.HttpHeaders.TRANSACTION_ID, requestId); + + return requestId; + } + + public String getPartnerName(ContainerRequestContext requestContext) { + + // CDM header overrides everything else for source of truth + String sourceOfTruth = requestContext.getHeaderString(AAIHeaderProperties.SOURCE_OF_TRUTH); + String partnerName = requestContext.getHeaderString(ONAPLogConstants.Headers.PARTNER_NAME); + if (sourceOfTruth == null || sourceOfTruth.isEmpty()) { + + if (partnerName != null && !(partnerName.isEmpty())) { + String components[] = partnerName.split("\\."); + if (components.length > 1) { + if (!(ONAPComponents.AAI.toString().equalsIgnoreCase(components[0]))) { + sourceOfTruth = components[0]; + } else { + // request is coming internally from AAI, check X-FromAppId + partnerName = null; + } + } + } + if (sourceOfTruth == null || sourceOfTruth.isEmpty()) { + if (partnerName == null || (partnerName.isEmpty())) { + partnerName = requestContext.getHeaderString(AAIHeaderProperties.FROM_APP_ID); + if (partnerName == null || (partnerName.isEmpty())) { + return partnerName; + } + } + } + } + if (requestContext.getHeaders().get(ONAPLogConstants.Headers.PARTNER_NAME) != null) { + requestContext.getHeaders().get(ONAPLogConstants.Headers.PARTNER_NAME).clear(); + } + if (requestContext.getHeaders().get(AAIHeaderProperties.FROM_APP_ID) != null) { + requestContext.getHeaders().get(AAIHeaderProperties.FROM_APP_ID).clear(); + } + if ((sourceOfTruth != null) && !(sourceOfTruth.isEmpty())) { + requestContext.getHeaders().add(AAIHeaderProperties.FROM_APP_ID, sourceOfTruth); + partnerName = sourceOfTruth; + } else { + requestContext.getHeaders().add(AAIHeaderProperties.FROM_APP_ID, partnerName); + } + return partnerName; + } } diff --git a/aai-resources/src/main/java/org/onap/aai/interceptors/pre/HttpHeaderInterceptor.java b/aai-resources/src/main/java/org/onap/aai/interceptors/pre/HttpHeaderInterceptor.java index faca530..17cdeff 100644 --- a/aai-resources/src/main/java/org/onap/aai/interceptors/pre/HttpHeaderInterceptor.java +++ b/aai-resources/src/main/java/org/onap/aai/interceptors/pre/HttpHeaderInterceptor.java @@ -17,17 +17,19 @@ * limitations under the License. * ============LICENSE_END========================================================= */ + package org.onap.aai.interceptors.pre; -import org.onap.aai.interceptors.AAIContainerFilter; -import org.onap.aai.interceptors.AAIHeaderProperties; + +import java.io.IOException; import javax.annotation.Priority; +import javax.ws.rs.HttpMethod; import javax.ws.rs.container.ContainerRequestContext; import javax.ws.rs.container.ContainerRequestFilter; import javax.ws.rs.container.PreMatching; -import javax.ws.rs.HttpMethod; -import java.io.IOException; +import org.onap.aai.interceptors.AAIContainerFilter; +import org.onap.aai.interceptors.AAIHeaderProperties; /** * The Class HttpHeaderInterceptor @@ -35,16 +37,16 @@ import java.io.IOException; @PreMatching @Priority(AAIRequestFilterPriority.HTTP_HEADER) public class HttpHeaderInterceptor extends AAIContainerFilter implements ContainerRequestFilter { - public static final String patchMethod = "PATCH"; - + public static final String patchMethod = "PATCH"; + @Override public void filter(ContainerRequestContext containerRequestContext) throws IOException { - String overrideMethod = containerRequestContext.getHeaderString(AAIHeaderProperties.HTTP_METHOD_OVERRIDE); - String httpMethod = containerRequestContext.getMethod(); - - if (HttpMethod.POST.equalsIgnoreCase(httpMethod) && patchMethod.equalsIgnoreCase(overrideMethod)) { - containerRequestContext.setMethod(patchMethod); - } + String overrideMethod = containerRequestContext.getHeaderString(AAIHeaderProperties.HTTP_METHOD_OVERRIDE); + String httpMethod = containerRequestContext.getMethod(); + + if (HttpMethod.POST.equalsIgnoreCase(httpMethod) && patchMethod.equalsIgnoreCase(overrideMethod)) { + containerRequestContext.setMethod(patchMethod); + } } - + } diff --git a/aai-resources/src/main/java/org/onap/aai/interceptors/pre/OneWaySslAuthorization.java b/aai-resources/src/main/java/org/onap/aai/interceptors/pre/OneWaySslAuthorization.java index a6c5ed9..bc7390e 100644 --- a/aai-resources/src/main/java/org/onap/aai/interceptors/pre/OneWaySslAuthorization.java +++ b/aai-resources/src/main/java/org/onap/aai/interceptors/pre/OneWaySslAuthorization.java @@ -17,15 +17,13 @@ * limitations under the License. * ============LICENSE_END========================================================= */ + package org.onap.aai.interceptors.pre; -import org.onap.aai.Profiles; -import org.onap.aai.exceptions.AAIException; -import org.onap.aai.interceptors.AAIContainerFilter; -import org.onap.aai.logging.ErrorLogHelper; -import org.onap.aai.service.AuthorizationService; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.annotation.Profile; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; import javax.annotation.Priority; import javax.ws.rs.container.ContainerRequestContext; @@ -33,10 +31,14 @@ import javax.ws.rs.container.ContainerRequestFilter; import javax.ws.rs.container.PreMatching; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; -import java.util.Optional; + +import org.onap.aai.Profiles; +import org.onap.aai.exceptions.AAIException; +import org.onap.aai.interceptors.AAIContainerFilter; +import org.onap.aai.logging.ErrorLogHelper; +import org.onap.aai.service.AuthorizationService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Profile; @Profile(Profiles.ONE_WAY_SSL) @PreMatching @@ -47,17 +49,16 @@ public class OneWaySslAuthorization extends AAIContainerFilter implements Contai private AuthorizationService authorizationService; @Override - public void filter(ContainerRequestContext containerRequestContext) throws IOException - { + public void filter(ContainerRequestContext containerRequestContext) throws IOException { - if(containerRequestContext.getUriInfo().getRequestUri().getPath().matches("^.*/util/echo$")){ + if (containerRequestContext.getUriInfo().getRequestUri().getPath().matches("^.*/util/echo$")) { return; } String basicAuth = containerRequestContext.getHeaderString("Authorization"); List acceptHeaderValues = containerRequestContext.getAcceptableMediaTypes(); - if(basicAuth == null || !basicAuth.startsWith("Basic ")){ + if (basicAuth == null || !basicAuth.startsWith("Basic ")) { Optional responseOptional = errorResponse("AAI_3300", acceptHeaderValues); containerRequestContext.abortWith(responseOptional.get()); return; @@ -65,7 +66,7 @@ public class OneWaySslAuthorization extends AAIContainerFilter implements Contai basicAuth = basicAuth.replaceAll("Basic ", ""); - if(!authorizationService.checkIfUserAuthorized(basicAuth)){ + if (!authorizationService.checkIfUserAuthorized(basicAuth)) { Optional responseOptional = errorResponse("AAI_3300", acceptHeaderValues); containerRequestContext.abortWith(responseOptional.get()); return; @@ -76,8 +77,7 @@ public class OneWaySslAuthorization extends AAIContainerFilter implements Contai private Optional errorResponse(String errorCode, List acceptHeaderValues) { AAIException aaie = new AAIException(errorCode); return Optional.of(Response.status(aaie.getErrorObject().getHTTPResponseCode()) - .entity(ErrorLogHelper.getRESTAPIErrorResponse(acceptHeaderValues, aaie, new ArrayList<>())) - .build()); + .entity(ErrorLogHelper.getRESTAPIErrorResponse(acceptHeaderValues, aaie, new ArrayList<>())).build()); } } diff --git a/aai-resources/src/main/java/org/onap/aai/interceptors/pre/RequestHeaderManipulation.java b/aai-resources/src/main/java/org/onap/aai/interceptors/pre/RequestHeaderManipulation.java index 97562d2..b70ff06 100644 --- a/aai-resources/src/main/java/org/onap/aai/interceptors/pre/RequestHeaderManipulation.java +++ b/aai-resources/src/main/java/org/onap/aai/interceptors/pre/RequestHeaderManipulation.java @@ -17,6 +17,7 @@ * limitations under the License. * ============LICENSE_END========================================================= */ + package org.onap.aai.interceptors.pre; import java.io.IOException; @@ -39,27 +40,27 @@ import org.springframework.beans.factory.annotation.Autowired; @Priority(AAIRequestFilterPriority.HEADER_MANIPULATION) public class RequestHeaderManipulation extends AAIContainerFilter implements ContainerRequestFilter { - @Override - public void filter(ContainerRequestContext requestContext) { + @Override + public void filter(ContainerRequestContext requestContext) { + + String uri = requestContext.getUriInfo().getPath(); + this.addRequestContext(uri, requestContext.getHeaders()); - String uri = requestContext.getUriInfo().getPath(); - this.addRequestContext(uri, requestContext.getHeaders()); + } - } - - private void addRequestContext(String uri, MultivaluedMap requestHeaders) { + private void addRequestContext(String uri, MultivaluedMap requestHeaders) { - String rc = ""; + String rc = ""; Matcher match = VersionInterceptor.EXTRACT_VERSION_PATTERN.matcher(uri); if (match.find()) { rc = match.group(1); } - if (requestHeaders.containsKey(AAIHeaderProperties.REQUEST_CONTEXT)) { - requestHeaders.remove(AAIHeaderProperties.REQUEST_CONTEXT); - } - requestHeaders.put(AAIHeaderProperties.REQUEST_CONTEXT, Collections.singletonList(rc)); - } + if (requestHeaders.containsKey(AAIHeaderProperties.REQUEST_CONTEXT)) { + requestHeaders.remove(AAIHeaderProperties.REQUEST_CONTEXT); + } + requestHeaders.put(AAIHeaderProperties.REQUEST_CONTEXT, Collections.singletonList(rc)); + } } diff --git a/aai-resources/src/main/java/org/onap/aai/interceptors/pre/RequestModification.java b/aai-resources/src/main/java/org/onap/aai/interceptors/pre/RequestModification.java index 797f9c9..d40fdbb 100644 --- a/aai-resources/src/main/java/org/onap/aai/interceptors/pre/RequestModification.java +++ b/aai-resources/src/main/java/org/onap/aai/interceptors/pre/RequestModification.java @@ -17,6 +17,7 @@ * limitations under the License. * ============LICENSE_END========================================================= */ + package org.onap.aai.interceptors.pre; import java.io.IOException; @@ -39,38 +40,38 @@ import org.onap.aai.interceptors.AAIContainerFilter; @Priority(AAIRequestFilterPriority.REQUEST_MODIFICATION) public class RequestModification extends AAIContainerFilter implements ContainerRequestFilter { - @Override - public void filter(ContainerRequestContext requestContext) throws IOException { + @Override + public void filter(ContainerRequestContext requestContext) throws IOException { + + this.cleanDME2QueryParams(requestContext); - this.cleanDME2QueryParams(requestContext); + } - } - - private void cleanDME2QueryParams(ContainerRequestContext request) { - UriBuilder builder = request.getUriInfo().getRequestUriBuilder(); - MultivaluedMap queries = request.getUriInfo().getQueryParameters(); + private void cleanDME2QueryParams(ContainerRequestContext request) { + UriBuilder builder = request.getUriInfo().getRequestUriBuilder(); + MultivaluedMap queries = request.getUriInfo().getQueryParameters(); - String[] blacklist = { "version", "envContext", "routeOffer" }; - Set blacklistSet = Arrays.stream(blacklist).collect(Collectors.toSet()); + String[] blacklist = {"version", "envContext", "routeOffer"}; + Set blacklistSet = Arrays.stream(blacklist).collect(Collectors.toSet()); - boolean remove = true; + boolean remove = true; - for (String param : blacklistSet) { - if (!queries.containsKey(param)) { - remove = false; - break; - } - } + for (String param : blacklistSet) { + if (!queries.containsKey(param)) { + remove = false; + break; + } + } - if (remove) { - for (Map.Entry> query : queries.entrySet()) { - String key = query.getKey(); - if (blacklistSet.contains(key)) { - builder.replaceQueryParam(key); - } - } - } - request.setRequestUri(builder.build()); - } + if (remove) { + for (Map.Entry> query : queries.entrySet()) { + String key = query.getKey(); + if (blacklistSet.contains(key)) { + builder.replaceQueryParam(key); + } + } + } + request.setRequestUri(builder.build()); + } } diff --git a/aai-resources/src/main/java/org/onap/aai/interceptors/pre/RequestTransactionLogging.java b/aai-resources/src/main/java/org/onap/aai/interceptors/pre/RequestTransactionLogging.java index 54f2695..14c1f01 100644 --- a/aai-resources/src/main/java/org/onap/aai/interceptors/pre/RequestTransactionLogging.java +++ b/aai-resources/src/main/java/org/onap/aai/interceptors/pre/RequestTransactionLogging.java @@ -17,15 +17,18 @@ * limitations under the License. * ============LICENSE_END========================================================= */ + package org.onap.aai.interceptors.pre; +import com.google.gson.JsonObject; + import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; +import java.security.SecureRandom; import java.util.Random; import java.util.UUID; -import java.security.SecureRandom; import javax.annotation.Priority; import javax.servlet.http.HttpServletRequest; @@ -45,103 +48,104 @@ import org.onap.aai.util.AAIConfig; import org.onap.aai.util.AAIConstants; import org.onap.aai.util.HbaseSaltPrefixer; import org.springframework.beans.factory.annotation.Autowired; - -import com.google.gson.JsonObject; import org.springframework.util.StringUtils; @PreMatching @Priority(AAIRequestFilterPriority.REQUEST_TRANS_LOGGING) public class RequestTransactionLogging extends AAIContainerFilter implements ContainerRequestFilter { - @Autowired - private HttpServletRequest httpServletRequest; - - private static final String DEFAULT_CONTENT_TYPE = MediaType.APPLICATION_JSON; - private static final String DEFAULT_RESPONSE_TYPE = MediaType.APPLICATION_XML; - - private static final String CONTENT_TYPE = "Content-Type"; - private static final String ACCEPT = "Accept"; - private static final String TEXT_PLAIN = "text/plain"; - private static final String WILDCARD = "*/*"; - private static final String APPLICATION_JSON = "application/json"; - - @Override - public void filter(ContainerRequestContext requestContext) throws IOException { - - String currentTimeStamp = genDate(); - String fullId = this.getAAITxIdToHeader(currentTimeStamp); - this.addToRequestContext(requestContext, AAIHeaderProperties.AAI_TX_ID, fullId); - this.addToRequestContext(requestContext, AAIHeaderProperties.AAI_REQUEST, this.getRequest(requestContext, fullId)); - this.addToRequestContext(requestContext, AAIHeaderProperties.AAI_REQUEST_TS, currentTimeStamp); - this.addDefaultContentType(requestContext); - } - - private void addToRequestContext(ContainerRequestContext requestContext, String name, String aaiTxIdToHeader) { - requestContext.setProperty(name, aaiTxIdToHeader); - } - - private void addDefaultContentType(ContainerRequestContext requestContext) { - - String contentType = requestContext.getHeaderString(CONTENT_TYPE); - String acceptType = requestContext.getHeaderString(ACCEPT); - - if(contentType == null || contentType.contains(TEXT_PLAIN)){ - requestContext.getHeaders().putSingle(CONTENT_TYPE, DEFAULT_CONTENT_TYPE); - } - - if(WILDCARD.equals(acceptType) || StringUtils.isEmpty(acceptType) || acceptType.contains(TEXT_PLAIN)){ - UriInfo uriInfo = requestContext.getUriInfo(); - if(uriInfo != null){ - MultivaluedMap queryParameters = uriInfo.getQueryParameters(); - if(queryParameters != null && queryParameters.containsKey("format")){ - // Add application/json as the default header if request contains query parameter format - // Since clients are assuming the default response to be application json for when format is specified - requestContext.getHeaders().putSingle(ACCEPT, APPLICATION_JSON); - } else { - requestContext.getHeaders().putSingle(ACCEPT, DEFAULT_RESPONSE_TYPE); - } - } else { - requestContext.getHeaders().putSingle(ACCEPT, DEFAULT_RESPONSE_TYPE); - } - } - } - - private String getAAITxIdToHeader(String currentTimeStamp) { - String txId = UUID.randomUUID().toString(); - try { - Random rand = new SecureRandom(); - int number = rand.nextInt(99999); - txId = HbaseSaltPrefixer.getInstance().prependSalt(AAIConfig.get(AAIConstants.AAI_NODENAME) + "-" - + currentTimeStamp + "-" + number ); //new Random(System.currentTimeMillis()).nextInt(99999) - } catch (AAIException e) { - } - - return txId; - } - - private String getRequest(ContainerRequestContext requestContext, String fullId) { - - JsonObject request = new JsonObject(); - request.addProperty("ID", fullId); - request.addProperty("Http-Method", requestContext.getMethod()); - request.addProperty(CONTENT_TYPE, httpServletRequest.getContentType()); - request.addProperty("Headers", requestContext.getHeaders().toString()); - - ByteArrayOutputStream out = new ByteArrayOutputStream(); - InputStream in = requestContext.getEntityStream(); - - try { - if (in.available() > 0) { - ReaderWriter.writeTo(in, out); - byte[] requestEntity = out.toByteArray(); - request.addProperty("Payload", new String(requestEntity, "UTF-8")); - requestContext.setEntityStream(new ByteArrayInputStream(requestEntity)); - } - } catch (IOException ex) { - throw new ContainerException(ex); - } - - return request.toString(); - } + @Autowired + private HttpServletRequest httpServletRequest; + + private static final String DEFAULT_CONTENT_TYPE = MediaType.APPLICATION_JSON; + private static final String DEFAULT_RESPONSE_TYPE = MediaType.APPLICATION_XML; + + private static final String CONTENT_TYPE = "Content-Type"; + private static final String ACCEPT = "Accept"; + private static final String TEXT_PLAIN = "text/plain"; + private static final String WILDCARD = "*/*"; + private static final String APPLICATION_JSON = "application/json"; + + @Override + public void filter(ContainerRequestContext requestContext) throws IOException { + + String currentTimeStamp = genDate(); + String fullId = this.getAAITxIdToHeader(currentTimeStamp); + this.addToRequestContext(requestContext, AAIHeaderProperties.AAI_TX_ID, fullId); + this.addToRequestContext(requestContext, AAIHeaderProperties.AAI_REQUEST, + this.getRequest(requestContext, fullId)); + this.addToRequestContext(requestContext, AAIHeaderProperties.AAI_REQUEST_TS, currentTimeStamp); + this.addDefaultContentType(requestContext); + } + + private void addToRequestContext(ContainerRequestContext requestContext, String name, String aaiTxIdToHeader) { + requestContext.setProperty(name, aaiTxIdToHeader); + } + + private void addDefaultContentType(ContainerRequestContext requestContext) { + + String contentType = requestContext.getHeaderString(CONTENT_TYPE); + String acceptType = requestContext.getHeaderString(ACCEPT); + + if (contentType == null || contentType.contains(TEXT_PLAIN)) { + requestContext.getHeaders().putSingle(CONTENT_TYPE, DEFAULT_CONTENT_TYPE); + } + + if (WILDCARD.equals(acceptType) || StringUtils.isEmpty(acceptType) || acceptType.contains(TEXT_PLAIN)) { + UriInfo uriInfo = requestContext.getUriInfo(); + if (uriInfo != null) { + MultivaluedMap queryParameters = uriInfo.getQueryParameters(); + if (queryParameters != null && queryParameters.containsKey("format")) { + // Add application/json as the default header if request contains query parameter format + // Since clients are assuming the default response to be application json for when format is + // specified + requestContext.getHeaders().putSingle(ACCEPT, APPLICATION_JSON); + } else { + requestContext.getHeaders().putSingle(ACCEPT, DEFAULT_RESPONSE_TYPE); + } + } else { + requestContext.getHeaders().putSingle(ACCEPT, DEFAULT_RESPONSE_TYPE); + } + } + } + + private String getAAITxIdToHeader(String currentTimeStamp) { + String txId = UUID.randomUUID().toString(); + try { + Random rand = new SecureRandom(); + int number = rand.nextInt(99999); + txId = HbaseSaltPrefixer.getInstance() + .prependSalt(AAIConfig.get(AAIConstants.AAI_NODENAME) + "-" + currentTimeStamp + "-" + number); // new + // Random(System.currentTimeMillis()).nextInt(99999) + } catch (AAIException e) { + } + + return txId; + } + + private String getRequest(ContainerRequestContext requestContext, String fullId) { + + JsonObject request = new JsonObject(); + request.addProperty("ID", fullId); + request.addProperty("Http-Method", requestContext.getMethod()); + request.addProperty(CONTENT_TYPE, httpServletRequest.getContentType()); + request.addProperty("Headers", requestContext.getHeaders().toString()); + + ByteArrayOutputStream out = new ByteArrayOutputStream(); + InputStream in = requestContext.getEntityStream(); + + try { + if (in.available() > 0) { + ReaderWriter.writeTo(in, out); + byte[] requestEntity = out.toByteArray(); + request.addProperty("Payload", new String(requestEntity, "UTF-8")); + requestContext.setEntityStream(new ByteArrayInputStream(requestEntity)); + } + } catch (IOException ex) { + throw new ContainerException(ex); + } + + return request.toString(); + } } diff --git a/aai-resources/src/main/java/org/onap/aai/interceptors/pre/RetiredInterceptor.java b/aai-resources/src/main/java/org/onap/aai/interceptors/pre/RetiredInterceptor.java index 643793d..80741f8 100644 --- a/aai-resources/src/main/java/org/onap/aai/interceptors/pre/RetiredInterceptor.java +++ b/aai-resources/src/main/java/org/onap/aai/interceptors/pre/RetiredInterceptor.java @@ -17,8 +17,21 @@ * limitations under the License. * ============LICENSE_END========================================================= */ + package org.onap.aai.interceptors.pre; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import javax.annotation.Priority; +import javax.ws.rs.container.ContainerRequestContext; +import javax.ws.rs.container.ContainerRequestFilter; +import javax.ws.rs.container.PreMatching; +import javax.ws.rs.core.Response; + import org.onap.aai.exceptions.AAIException; import org.onap.aai.interceptors.AAIContainerFilter; import org.onap.aai.logging.ErrorLogHelper; @@ -27,17 +40,6 @@ import org.onap.aai.util.AAIConfig; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; -import javax.annotation.Priority; -import javax.ws.rs.container.ContainerRequestContext; -import javax.ws.rs.container.ContainerRequestFilter; -import javax.ws.rs.container.PreMatching; -import javax.ws.rs.core.Response; -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - // Can cache this so if the uri was already cached then it won't run the string // matching each time but only does it for the first time @@ -52,13 +54,14 @@ public class RetiredInterceptor extends AAIContainerFilter implements ContainerR private String basePath; @Autowired - public RetiredInterceptor(RetiredService retiredService, @Value("${schema.uri.base.path}") String basePath){ + public RetiredInterceptor(RetiredService retiredService, @Value("${schema.uri.base.path}") String basePath) { this.retiredService = retiredService; this.basePath = basePath; - if(!basePath.endsWith("/")){ + if (!basePath.endsWith("/")) { this.basePath = basePath + "/"; } } + @Override public void filter(ContainerRequestContext containerRequestContext) throws IOException { @@ -68,8 +71,7 @@ public class RetiredInterceptor extends AAIContainerFilter implements ContainerR List retiredAllVersionList = retiredService.getRetiredAllVersionList(); - - if(checkIfUriRetired(containerRequestContext, retiredAllVersionList, version, requestURI, "")){ + if (checkIfUriRetired(containerRequestContext, retiredAllVersionList, version, requestURI, "")) { return; } @@ -78,18 +80,14 @@ public class RetiredInterceptor extends AAIContainerFilter implements ContainerR checkIfUriRetired(containerRequestContext, retiredVersionList, version, requestURI); } - public boolean checkIfUriRetired(ContainerRequestContext containerRequestContext, - List retiredPatterns, - String version, - String requestURI, - String message){ - + public boolean checkIfUriRetired(ContainerRequestContext containerRequestContext, List retiredPatterns, + String version, String requestURI, String message) { - for(Pattern retiredPattern : retiredPatterns){ - if(retiredPattern.matcher(requestURI).matches()){ + for (Pattern retiredPattern : retiredPatterns) { + if (retiredPattern.matcher(requestURI).matches()) { AAIException e; - if(message == null){ + if (message == null) { e = new AAIException("AAI_3007"); } else { e = new AAIException("AAI_3015"); @@ -99,24 +97,18 @@ public class RetiredInterceptor extends AAIContainerFilter implements ContainerR if (templateVars.isEmpty()) { templateVars.add("PUT"); - if(requestURI != null){ + if (requestURI != null) { requestURI = requestURI.replaceAll(basePath, ""); } templateVars.add(requestURI); - if(message == null){ + if (message == null) { templateVars.add(version); templateVars.add(AAIConfig.get("aai.default.api.version", "")); } } - Response response = Response - .status(e.getErrorObject().getHTTPResponseCode()) - .entity( - ErrorLogHelper - .getRESTAPIErrorResponse( - containerRequestContext.getAcceptableMediaTypes(), e, templateVars - ) - ) + Response response = Response.status(e.getErrorObject().getHTTPResponseCode()).entity(ErrorLogHelper + .getRESTAPIErrorResponse(containerRequestContext.getAcceptableMediaTypes(), e, templateVars)) .build(); containerRequestContext.abortWith(response); @@ -128,10 +120,8 @@ public class RetiredInterceptor extends AAIContainerFilter implements ContainerR return false; } - public boolean checkIfUriRetired(ContainerRequestContext containerRequestContext, - List retiredPatterns, - String version, - String requestURI){ + public boolean checkIfUriRetired(ContainerRequestContext containerRequestContext, List retiredPatterns, + String version, String requestURI) { return checkIfUriRetired(containerRequestContext, retiredPatterns, version, requestURI, null); } @@ -139,7 +129,7 @@ public class RetiredInterceptor extends AAIContainerFilter implements ContainerR Matcher versionMatcher = VERSION_PATTERN.matcher(requestURI); String version = null; - if(versionMatcher.find()){ + if (versionMatcher.find()) { version = versionMatcher.group(0); } return version; diff --git a/aai-resources/src/main/java/org/onap/aai/interceptors/pre/VersionInterceptor.java b/aai-resources/src/main/java/org/onap/aai/interceptors/pre/VersionInterceptor.java index f3c5768..5d21141 100644 --- a/aai-resources/src/main/java/org/onap/aai/interceptors/pre/VersionInterceptor.java +++ b/aai-resources/src/main/java/org/onap/aai/interceptors/pre/VersionInterceptor.java @@ -17,20 +17,9 @@ * limitations under the License. * ============LICENSE_END========================================================= */ -package org.onap.aai.interceptors.pre; -import org.onap.aai.exceptions.AAIException; -import org.onap.aai.interceptors.AAIContainerFilter; -import org.onap.aai.logging.ErrorLogHelper; -import org.onap.aai.setup.SchemaVersion; -import org.onap.aai.setup.SchemaVersions; -import org.springframework.beans.factory.annotation.Autowired; +package org.onap.aai.interceptors.pre; -import javax.annotation.Priority; -import javax.ws.rs.container.ContainerRequestContext; -import javax.ws.rs.container.ContainerRequestFilter; -import javax.ws.rs.container.PreMatching; -import javax.ws.rs.core.Response; import java.net.URI; import java.util.ArrayList; import java.util.Set; @@ -38,6 +27,19 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.stream.Collectors; +import javax.annotation.Priority; +import javax.ws.rs.container.ContainerRequestContext; +import javax.ws.rs.container.ContainerRequestFilter; +import javax.ws.rs.container.PreMatching; +import javax.ws.rs.core.Response; + +import org.onap.aai.exceptions.AAIException; +import org.onap.aai.interceptors.AAIContainerFilter; +import org.onap.aai.logging.ErrorLogHelper; +import org.onap.aai.setup.SchemaVersion; +import org.onap.aai.setup.SchemaVersions; +import org.springframework.beans.factory.annotation.Autowired; + @PreMatching @Priority(AAIRequestFilterPriority.VERSION) public class VersionInterceptor extends AAIContainerFilter implements ContainerRequestFilter { @@ -49,12 +51,10 @@ public class VersionInterceptor extends AAIContainerFilter implements ContainerR private final SchemaVersions schemaVersions; @Autowired - public VersionInterceptor(SchemaVersions schemaVersions){ + public VersionInterceptor(SchemaVersions schemaVersions) { this.schemaVersions = schemaVersions; - allowedVersions = schemaVersions.getVersions() - .stream() - .map(SchemaVersion::toString) - .collect(Collectors.toSet()); + allowedVersions = + schemaVersions.getVersions().stream().map(SchemaVersion::toString).collect(Collectors.toSet()); } @@ -65,19 +65,19 @@ public class VersionInterceptor extends AAIContainerFilter implements ContainerR if (uri.startsWith("search") || uri.startsWith("util/echo") || uri.startsWith("tools")) { return; - } + } Matcher matcher = EXTRACT_VERSION_PATTERN.matcher(uri); String version = null; - if(matcher.matches()){ + if (matcher.matches()) { version = matcher.group(1); } else { requestContext.abortWith(createInvalidVersionResponse("AAI_3017", requestContext, version)); return; } - if(!allowedVersions.contains(version)){ + if (!allowedVersions.contains(version)) { requestContext.abortWith(createInvalidVersionResponse("AAI_3016", requestContext, version)); } } @@ -94,9 +94,6 @@ public class VersionInterceptor extends AAIContainerFilter implements ContainerR String entity = ErrorLogHelper.getRESTAPIErrorResponse(context.getAcceptableMediaTypes(), e, templateVars); - return Response - .status(e.getErrorObject().getHTTPResponseCode()) - .entity(entity) - .build(); + return Response.status(e.getErrorObject().getHTTPResponseCode()).entity(entity).build(); } } diff --git a/aai-resources/src/main/java/org/onap/aai/interceptors/pre/VersionLatestInterceptor.java b/aai-resources/src/main/java/org/onap/aai/interceptors/pre/VersionLatestInterceptor.java index 61008b6..5d68c8a 100644 --- a/aai-resources/src/main/java/org/onap/aai/interceptors/pre/VersionLatestInterceptor.java +++ b/aai-resources/src/main/java/org/onap/aai/interceptors/pre/VersionLatestInterceptor.java @@ -17,17 +17,19 @@ * limitations under the License. * ============LICENSE_END========================================================= */ + package org.onap.aai.interceptors.pre; -import org.onap.aai.interceptors.AAIContainerFilter; -import org.onap.aai.setup.SchemaVersions; -import org.springframework.beans.factory.annotation.Autowired; +import java.net.URI; import javax.annotation.Priority; import javax.ws.rs.container.ContainerRequestContext; import javax.ws.rs.container.ContainerRequestFilter; import javax.ws.rs.container.PreMatching; -import java.net.URI; + +import org.onap.aai.interceptors.AAIContainerFilter; +import org.onap.aai.setup.SchemaVersions; +import org.springframework.beans.factory.annotation.Autowired; @PreMatching @Priority(AAIRequestFilterPriority.LATEST) @@ -36,7 +38,7 @@ public class VersionLatestInterceptor extends AAIContainerFilter implements Cont private final SchemaVersions schemaVersions; @Autowired - public VersionLatestInterceptor(SchemaVersions schemaVersions){ + public VersionLatestInterceptor(SchemaVersions schemaVersions) { this.schemaVersions = schemaVersions; } @@ -45,8 +47,8 @@ public class VersionLatestInterceptor extends AAIContainerFilter implements Cont String uri = requestContext.getUriInfo().getPath(); - if(uri.startsWith("latest")){ - String absolutePath = requestContext.getUriInfo().getAbsolutePath().toString(); + if (uri.startsWith("latest")) { + String absolutePath = requestContext.getUriInfo().getAbsolutePath().toString(); String latest = absolutePath.replaceFirst("latest", schemaVersions.getDefaultVersion().toString()); requestContext.setRequestUri(URI.create(latest)); return; diff --git a/aai-resources/src/main/java/org/onap/aai/rest/BulkAddConsumer.java b/aai-resources/src/main/java/org/onap/aai/rest/BulkAddConsumer.java index e28cce9..3287dd1 100644 --- a/aai-resources/src/main/java/org/onap/aai/rest/BulkAddConsumer.java +++ b/aai-resources/src/main/java/org/onap/aai/rest/BulkAddConsumer.java @@ -17,32 +17,34 @@ * limitations under the License. * ============LICENSE_END========================================================= */ + package org.onap.aai.rest; +import io.micrometer.core.annotation.Timed; + import javax.ws.rs.Path; -import io.micrometer.core.annotation.Timed; import org.onap.aai.restcore.HttpMethod; @Path("{version: v[1-9][0-9]*|latest}/bulkadd") @Timed public class BulkAddConsumer extends BulkConsumer { - @Override - protected boolean functionAllowed(HttpMethod method) { - - return method.equals(HttpMethod.PUT); - - } - - @Override - protected String getModule(){ - return "bulk add"; - } - - @Override - protected boolean enableResourceVersion() { - return true; - } + @Override + protected boolean functionAllowed(HttpMethod method) { + + return method.equals(HttpMethod.PUT); + + } + + @Override + protected String getModule() { + return "bulk add"; + } + + @Override + protected boolean enableResourceVersion() { + return true; + } } diff --git a/aai-resources/src/main/java/org/onap/aai/rest/BulkConsumer.java b/aai-resources/src/main/java/org/onap/aai/rest/BulkConsumer.java index a2f83b0..9d90a46 100644 --- a/aai-resources/src/main/java/org/onap/aai/rest/BulkConsumer.java +++ b/aai-resources/src/main/java/org/onap/aai/rest/BulkConsumer.java @@ -17,9 +17,25 @@ * limitations under the License. * ============LICENSE_END========================================================= */ + package org.onap.aai.rest; import com.google.gson.*; + +import java.io.UnsupportedEncodingException; +import java.net.URI; +import java.util.*; +import java.util.Map.Entry; +import java.util.stream.Collectors; + +import javax.servlet.http.HttpServletRequest; +import javax.ws.rs.Consumes; +import javax.ws.rs.PUT; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.core.*; +import javax.ws.rs.core.Response.Status; + import org.javatuples.Pair; import org.onap.aai.config.SpringContextAware; import org.onap.aai.exceptions.AAIException; @@ -44,19 +60,6 @@ import org.onap.aai.util.AAIConstants; import org.springframework.web.util.UriComponents; import org.springframework.web.util.UriComponentsBuilder; -import javax.servlet.http.HttpServletRequest; -import javax.ws.rs.Consumes; -import javax.ws.rs.PUT; -import javax.ws.rs.PathParam; -import javax.ws.rs.Produces; -import javax.ws.rs.core.*; -import javax.ws.rs.core.Response.Status; -import java.io.UnsupportedEncodingException; -import java.net.URI; -import java.util.*; -import java.util.Map.Entry; -import java.util.stream.Collectors; - /** * The Class BulkAddConsumer. */ @@ -65,504 +68,527 @@ import java.util.stream.Collectors; * multiple objects with one request. It may take * one or more transaction objects containing one or more * objects to add. - * The transactions are independent of each other - + * The transactions are independent of each other - * if one fails, its effects are rolled back, but the others' aren't. * Within a single transaction, if adding one object fails, all the others' * changes are rolled back. */ public abstract class BulkConsumer extends RESTAPI { - private static final String BULK_PATCH_METHOD = "patch"; - private static final String BULK_DELETE_METHOD = "delete"; - private static final String BULK_PUT_METHOD = "put"; - private static final String TARGET_ENTITY = "aai-resources"; - - /** The introspector factory type. */ - private ModelType introspectorFactoryType = ModelType.MOXY; - - /** The query style. */ - private QueryStyle queryStyle = QueryStyle.TRAVERSAL_URI; - - /** - * Bulk add. - * - * @param content the content - * @param versionParam the version param - * @param uri the uri - * @param headers the headers - * @param info the info - * @param req the req - * @return the response - */ - @PUT - @Consumes({ MediaType.APPLICATION_JSON}) - @Produces({ MediaType.APPLICATION_JSON}) - public Response bulkProcessor(String content, @PathParam("version")String versionParam, @Context HttpHeaders headers, @Context UriInfo info, @Context HttpServletRequest req){ - - String transId = headers.getRequestHeaders().getFirst("X-TransactionId"); - String sourceOfTruth = headers.getRequestHeaders().getFirst("X-FromAppId"); - String outputMediaType = getMediaType(headers.getAcceptableMediaTypes()); - SchemaVersion version = new SchemaVersion(versionParam); - Response response = null; - - try { - - /* A Response will be generated for each object in each transaction. + private static final String BULK_PATCH_METHOD = "patch"; + private static final String BULK_DELETE_METHOD = "delete"; + private static final String BULK_PUT_METHOD = "put"; + private static final String TARGET_ENTITY = "aai-resources"; + + /** The introspector factory type. */ + private ModelType introspectorFactoryType = ModelType.MOXY; + + /** The query style. */ + private QueryStyle queryStyle = QueryStyle.TRAVERSAL_URI; + + /** + * Bulk add. + * + * @param content the content + * @param versionParam the version param + * @param uri the uri + * @param headers the headers + * @param info the info + * @param req the req + * @return the response + */ + @PUT + @Consumes({MediaType.APPLICATION_JSON}) + @Produces({MediaType.APPLICATION_JSON}) + public Response bulkProcessor(String content, @PathParam("version") String versionParam, + @Context HttpHeaders headers, @Context UriInfo info, @Context HttpServletRequest req) { + + String transId = headers.getRequestHeaders().getFirst("X-TransactionId"); + String sourceOfTruth = headers.getRequestHeaders().getFirst("X-FromAppId"); + String outputMediaType = getMediaType(headers.getAcceptableMediaTypes()); + SchemaVersion version = new SchemaVersion(versionParam); + Response response = null; + + try { + + /* + * A Response will be generated for each object in each transaction. * To keep track of what came from where to give organized feedback to the client, * we keep responses from a given transaction together in one list (hence all being a list of lists) * and BulkOperationResponse each response with its matching URI (which will be null if there wasn't one). */ List> allResponses = new ArrayList<>(); - JsonArray transactions = getTransactions(content, headers); - - for (int i = 0; i < transactions.size(); i++){ - HttpEntry resourceHttpEntry = SpringContextAware.getBean("traversalUriHttpEntry", HttpEntry.class); - resourceHttpEntry.setHttpEntryProperties(version); - Loader loader = resourceHttpEntry.getLoader(); - TransactionalGraphEngine dbEngine = resourceHttpEntry.getDbEngine(); - URI thisUri = null; - List bulkOperations = new ArrayList<>(); - HttpMethod method = null; - JsonElement transObj = new JsonObject(); - try { - transObj = transactions.get(i); - if (!transObj.isJsonObject()) { - throw new AAIException("AAI_6111", "input payload does not follow bulk interface"); - } - - fillBulkOperationsObjectFromTransaction(bulkOperations, transObj.getAsJsonObject(), loader, dbEngine, outputMediaType); - if (bulkOperations.isEmpty()) { - //case where user sends a validly formatted transactions object but - //which has no actual things in it for A&AI to do anything with - //assuming we should count this as a user error - throw new AAIException("AAI_6118", "payload had no objects to operate on"); - } - - List requests = new ArrayList<>(); - for (BulkOperation bulkOperation : bulkOperations){ - thisUri = bulkOperation.getUri(); - method = bulkOperation.getHttpMethod(); - QueryParser uriQuery = dbEngine.getQueryBuilder().createQueryFromURI(thisUri); - DBRequest request = new DBRequest.Builder(method, thisUri, uriQuery, bulkOperation.getIntrospector(), headers, bulkOperation.getUriInfo(), transId).rawRequestContent(bulkOperation.getRawReq()).build(); - requests.add(request); - } - - Pair>> results = resourceHttpEntry.process(requests, sourceOfTruth, this.enableResourceVersion()); - List responses = BulkOperationResponse.processPairList(method, results.getValue1()); - allResponses.add(responses); - if (results.getValue0()) { //everything was processed without error - dbEngine.commit(); - } else { //something failed - dbEngine.rollback(); - } - } catch (Exception e) { - /* While httpEntry.process handles its exceptions, exceptions thrown in earlier helpers - * bubbles up to here. As we want to tie error messages to the URI of the object that caused - * them, we catch here, generate a Response, bundle it with that URI, and move on. - */ - if (!bulkOperations.isEmpty()) { //failed somewhere in the middle of bulkOperation-filling - BulkOperation lastBulkOperation = bulkOperations.get(bulkOperations.size()-1); //last one in there was the problem - if (lastBulkOperation.getIntrospector() == null){ - //failed out before thisUri could be set but after bulkOperations started being filled - thisUri = lastBulkOperation.getUri(); - method = lastBulkOperation.getHttpMethod(); - } - } //else failed out on empty payload so bulkOperations never filled (or failed out even earlier than bulkOperations-filling) - - if (method == null) { - List methods = transObj.getAsJsonObject().entrySet().stream().map(Entry::getKey).collect(Collectors.toCollection(ArrayList::new)); - - if (methods.contains(BULK_PUT_METHOD)) { - method = HttpMethod.PUT; - } else if (methods.contains(BULK_DELETE_METHOD)) { - method = HttpMethod.DELETE; - } else if (methods.contains(BULK_PATCH_METHOD)) { - method = HttpMethod.MERGE_PATCH; - } else { - method = HttpMethod.PUT; - } - } - - addExceptionCaseFailureResponse(allResponses, e, i, thisUri, headers, info, method); - dbEngine.rollback(); - continue; /* if an exception gets thrown within a transaction we want to keep going to - the next transaction, not break out of the whole request */ - } - } - - String returnPayload = generateResponsePayload(allResponses); - - //unless a top level error gets thrown, we want to 201 bc the client wanted a "fire and forget" kind of setup - response = Response - .status(Status.CREATED) - .entity(returnPayload) - .build(); - } catch (AAIException e) { //these catches needed for handling top level errors in payload parsing where the whole request must fail out - response = consumerExceptionResponseGenerator(headers, info, HttpMethod.PUT, e); - } catch(JsonSyntaxException e) { - AAIException ex = new AAIException("AAI_6111"); - response = consumerExceptionResponseGenerator(headers, info, HttpMethod.PUT, ex); - } catch (Exception e ) { - AAIException ex = new AAIException("AAI_4000", e); - response = consumerExceptionResponseGenerator(headers, info, HttpMethod.PUT, ex); - } - - return response; - } - - - /** - * Gets the transactions. - * - * @param content - input JSON payload string - * @return JsonArray - the array of transactions - * @throws AAIException the AAI exception - * @throws JsonSyntaxException Parses and breaks the single payload into an array of individual transaction - * bodies to be processed. - */ - private JsonArray getTransactions(String content, HttpHeaders headers) throws AAIException, JsonSyntaxException { - JsonParser parser = new JsonParser(); - - JsonObject input = parser.parse(content).getAsJsonObject(); - String module = getModule(); - - if (!(input.has("transactions"))) { - throw new AAIException("AAI_6118", String.format("input payload does not follow %s interface - missing \"transactions\"", module)); - } - JsonElement transactionsObj = input.get("transactions"); - - if (!(transactionsObj.isJsonArray())){ - throw new AAIException("AAI_6111", String.format("input payload does not follow %s interface", module)); - } - JsonArray transactions = transactionsObj.getAsJsonArray(); - validateRequest(transactions, headers); - return transactions; - } - - /** - * Fill object bulkOperations from transaction. - * - * @param bulkOperations the bulkOperations - * @param transaction - JSON body containing the objects to be added - * each object must have a URI and an object body - * @param loader the loader - * @param dbEngine the db engine - * @param inputMediaType the input media type - * @return list of bulkOperations containing each introspector-wrapped object and its given URI - * @throws AAIException the AAI exception - * @throws JsonSyntaxException the json syntax exception - * @throws UnsupportedEncodingException Walks through the given transaction and unmarshals each object in it, then bundles each - * with its URI. - */ - private void fillBulkOperationsObjectFromTransaction(List bulkOperations, - JsonObject transaction, Loader loader, TransactionalGraphEngine dbEngine, String inputMediaType) - throws AAIException, JsonSyntaxException, UnsupportedEncodingException { - - - if (transaction.has(BULK_PUT_METHOD) && this.functionAllowed(HttpMethod.PUT)) { - populateBulkOperations(bulkOperations, transaction, loader, dbEngine, inputMediaType, HttpMethod.PUT); - } else if (transaction.has(BULK_DELETE_METHOD) && this.functionAllowed(HttpMethod.DELETE)) { - populateBulkOperations(bulkOperations, transaction, loader, dbEngine, inputMediaType, HttpMethod.DELETE); - } else if (transaction.has(BULK_PATCH_METHOD) && this.functionAllowed(HttpMethod.MERGE_PATCH)) { - populateBulkOperations(bulkOperations, transaction, loader, dbEngine, inputMediaType, HttpMethod.MERGE_PATCH); - } else { - String msg = "input payload does not follow bulk %s interface - missing %s"; - String type = "process"; - String operations = "put delete or patch"; - - if (this instanceof BulkAddConsumer) { - type = "add"; - operations = BULK_PUT_METHOD; - } - throw new AAIException("AAI_6118", String.format(msg, type, operations)); - } - - - - } - - - - private void populateBulkOperations(List bulkOperations, JsonObject item, Loader loader, TransactionalGraphEngine dbEngine, String inputMediaType, HttpMethod method) throws AAIException, JsonSyntaxException, UnsupportedEncodingException{ - String module = getModule(); - for (int i=0; i> allResponses){ - JsonObject ret = new JsonObject(); - JsonArray retArr = new JsonArray(); - - for(List responses : allResponses){ - JsonObject tResp = new JsonObject(); - JsonArray tArrResp = new JsonArray(); - HttpMethod method = HttpMethod.PUT; - - for (BulkOperationResponse r : responses) { - - JsonObject indPayload = new JsonObject(); - method = r.getHttpMethod(); - - URI origURI = r.getUri(); - if (origURI != null) { - indPayload.addProperty("uri", origURI.getPath()); - } else { - indPayload.addProperty("uri", (String)null); - } - - JsonObject body = new JsonObject(); - - int rStatus = r.getResponse().getStatus(); - String rContents = null; - - rContents = (String)r.getResponse().getEntity(); - - body.addProperty(Integer.toString(rStatus), rContents); - indPayload.add("body", body); - - tArrResp.add(indPayload); - } - - tResp.add(this.mapHttpMethodToBulkMethod(method), tArrResp); - retArr.add(tResp); - } - ret.add("transaction", retArr); - Gson gson = new GsonBuilder().serializeNulls().create(); - return gson.toJson(ret); - } - - private String mapHttpMethodToBulkMethod(HttpMethod method) { - if (HttpMethod.PUT.equals(method) || HttpMethod.PUT_EDGE.equals(method)) { - return BULK_PUT_METHOD; - } else if (HttpMethod.DELETE.equals(method) || HttpMethod.DELETE_EDGE.equals(method)) { - return BULK_DELETE_METHOD; - } else if (HttpMethod.MERGE_PATCH.equals(method)) { - return BULK_PATCH_METHOD; - } else { - return ""; - } - } - - - /** - * Adds the exception case failure response. - * - * @param allResponses the all responses - * @param e the e - * @param index - index of which transaction was being processed when the exception was thrown - * @param thisUri the this uri - * @param headers the headers - * @param info the info - * @param templateAction the template action - * @throws ErrorObjectNotFoundException - */ - private void addExceptionCaseFailureResponse(List> allResponses, Exception e, int index, URI thisUri, HttpHeaders headers, UriInfo info, HttpMethod templateAction) { - AAIException ex = null; - - if (!(e instanceof AAIException)){ - ex = new AAIException("AAI_4000", e); - } else { - ex = (AAIException)e; - } - - if (allResponses.size() != (index+1)) { - //index+1 bc if all transactions thus far have had a response list added - //the size will be one more than the current index (since those are offset by 1) - - //this transaction doesn't have a response list yet, so create one - Response failResp = consumerExceptionResponseGenerator(headers, info, templateAction, ex); - BulkOperationResponse uriResp = new BulkOperationResponse(templateAction, thisUri, failResp); - List transRespList = new ArrayList<>(); - transRespList.add(uriResp); - allResponses.add(transRespList); - } else { - //this transaction already has a response list, so add this failure response to it - Response failResp = consumerExceptionResponseGenerator(headers, info, templateAction, ex); - BulkOperationResponse uriResp = new BulkOperationResponse(templateAction, thisUri, failResp); - List tResps = allResponses.get(index); - tResps.add(uriResp); - } - } - - /** - * Pulls the config value for the limit of operations allowed in a bulk add/process request - * - * @throws AAIException - */ - private int getPayLoadLimit() throws AAIException{ - return Integer.parseInt(AAIConfig.get(AAIConstants.AAI_BULKCONSUMER_LIMIT)); - } - - /** - * Validates the amount of operations in a request payload is allowed - * - * @param transactions - a JsonArray of all the transactions in the request payload - * @throws AAIException - */ - private void validateRequest(JsonArray transactions, HttpHeaders headers) throws AAIException{ - String overrideLimit = headers.getRequestHeaders().getFirst("X-OverrideLimit"); - boolean isOverride = overrideLimit != null && !AAIConfig.get(AAIConstants.AAI_BULKCONSUMER_OVERRIDE_LIMIT).equals("false") - && overrideLimit.equals(AAIConfig.get(AAIConstants.AAI_BULKCONSUMER_OVERRIDE_LIMIT)); - if (transactions.size() == 0) { - //case where user sends a validly formatted transactions object but - //which has no actual things in it for A&AI to do anything with - //assuming we should count this as a user error - throw new AAIException("AAI_6118", "payload had no objects to operate on"); - }else if(!isOverride && transactions.size() > getPayLoadLimit()) { - throw new AAIException("AAI_6147", String.format("Payload limit of %s reached, please reduce payload.", getPayLoadLimit())); - } - if(!isOverride) { - int operationCount = 0; - int payLoadLimit = getPayLoadLimit(); - for (int i = 0; i < transactions.size(); i++) { - Set> entrySet = transactions.get(i).getAsJsonObject().entrySet(); - Iterator> it = entrySet.iterator(); - while (it.hasNext()) { - Map.Entry element = it.next(); - if (element.getValue() instanceof JsonArray) { - operationCount += ((JsonArray) element.getValue()).size(); - } else { - operationCount++; - } - } - if (operationCount > payLoadLimit) { - throw new AAIException("AAI_6147", String.format("Payload limit of %s reached, please reduce payload.", payLoadLimit)); - } - } - } - } - - protected abstract String getModule(); - - protected abstract boolean functionAllowed(HttpMethod method); - - protected abstract boolean enableResourceVersion(); + JsonArray transactions = getTransactions(content, headers); + + for (int i = 0; i < transactions.size(); i++) { + HttpEntry resourceHttpEntry = SpringContextAware.getBean("traversalUriHttpEntry", HttpEntry.class); + resourceHttpEntry.setHttpEntryProperties(version); + Loader loader = resourceHttpEntry.getLoader(); + TransactionalGraphEngine dbEngine = resourceHttpEntry.getDbEngine(); + URI thisUri = null; + List bulkOperations = new ArrayList<>(); + HttpMethod method = null; + JsonElement transObj = new JsonObject(); + try { + transObj = transactions.get(i); + if (!transObj.isJsonObject()) { + throw new AAIException("AAI_6111", "input payload does not follow bulk interface"); + } + + fillBulkOperationsObjectFromTransaction(bulkOperations, transObj.getAsJsonObject(), loader, + dbEngine, outputMediaType); + if (bulkOperations.isEmpty()) { + // case where user sends a validly formatted transactions object but + // which has no actual things in it for A&AI to do anything with + // assuming we should count this as a user error + throw new AAIException("AAI_6118", "payload had no objects to operate on"); + } + + List requests = new ArrayList<>(); + for (BulkOperation bulkOperation : bulkOperations) { + thisUri = bulkOperation.getUri(); + method = bulkOperation.getHttpMethod(); + QueryParser uriQuery = dbEngine.getQueryBuilder().createQueryFromURI(thisUri); + DBRequest request = new DBRequest.Builder(method, thisUri, uriQuery, + bulkOperation.getIntrospector(), headers, bulkOperation.getUriInfo(), transId) + .rawRequestContent(bulkOperation.getRawReq()).build(); + requests.add(request); + } + + Pair>> results = + resourceHttpEntry.process(requests, sourceOfTruth, this.enableResourceVersion()); + List responses = + BulkOperationResponse.processPairList(method, results.getValue1()); + allResponses.add(responses); + if (results.getValue0()) { // everything was processed without error + dbEngine.commit(); + } else { // something failed + dbEngine.rollback(); + } + } catch (Exception e) { + /* + * While httpEntry.process handles its exceptions, exceptions thrown in earlier helpers + * bubbles up to here. As we want to tie error messages to the URI of the object that caused + * them, we catch here, generate a Response, bundle it with that URI, and move on. + */ + if (!bulkOperations.isEmpty()) { // failed somewhere in the middle of bulkOperation-filling + BulkOperation lastBulkOperation = bulkOperations.get(bulkOperations.size() - 1); // last one in + // there was + // the problem + if (lastBulkOperation.getIntrospector() == null) { + // failed out before thisUri could be set but after bulkOperations started being filled + thisUri = lastBulkOperation.getUri(); + method = lastBulkOperation.getHttpMethod(); + } + } // else failed out on empty payload so bulkOperations never filled (or failed out even earlier + // than bulkOperations-filling) + + if (method == null) { + List methods = transObj.getAsJsonObject().entrySet().stream().map(Entry::getKey) + .collect(Collectors.toCollection(ArrayList::new)); + + if (methods.contains(BULK_PUT_METHOD)) { + method = HttpMethod.PUT; + } else if (methods.contains(BULK_DELETE_METHOD)) { + method = HttpMethod.DELETE; + } else if (methods.contains(BULK_PATCH_METHOD)) { + method = HttpMethod.MERGE_PATCH; + } else { + method = HttpMethod.PUT; + } + } + + addExceptionCaseFailureResponse(allResponses, e, i, thisUri, headers, info, method); + dbEngine.rollback(); + continue; /* + * if an exception gets thrown within a transaction we want to keep going to + * the next transaction, not break out of the whole request + */ + } + } + + String returnPayload = generateResponsePayload(allResponses); + + // unless a top level error gets thrown, we want to 201 bc the client wanted a "fire and forget" kind of + // setup + response = Response.status(Status.CREATED).entity(returnPayload).build(); + } catch (AAIException e) { // these catches needed for handling top level errors in payload parsing where the + // whole request must fail out + response = consumerExceptionResponseGenerator(headers, info, HttpMethod.PUT, e); + } catch (JsonSyntaxException e) { + AAIException ex = new AAIException("AAI_6111"); + response = consumerExceptionResponseGenerator(headers, info, HttpMethod.PUT, ex); + } catch (Exception e) { + AAIException ex = new AAIException("AAI_4000", e); + response = consumerExceptionResponseGenerator(headers, info, HttpMethod.PUT, ex); + } + + return response; + } + + /** + * Gets the transactions. + * + * @param content - input JSON payload string + * @return JsonArray - the array of transactions + * @throws AAIException the AAI exception + * @throws JsonSyntaxException Parses and breaks the single payload into an array of individual transaction + * bodies to be processed. + */ + private JsonArray getTransactions(String content, HttpHeaders headers) throws AAIException, JsonSyntaxException { + JsonParser parser = new JsonParser(); + + JsonObject input = parser.parse(content).getAsJsonObject(); + String module = getModule(); + + if (!(input.has("transactions"))) { + throw new AAIException("AAI_6118", + String.format("input payload does not follow %s interface - missing \"transactions\"", module)); + } + JsonElement transactionsObj = input.get("transactions"); + + if (!(transactionsObj.isJsonArray())) { + throw new AAIException("AAI_6111", String.format("input payload does not follow %s interface", module)); + } + JsonArray transactions = transactionsObj.getAsJsonArray(); + validateRequest(transactions, headers); + return transactions; + } + + /** + * Fill object bulkOperations from transaction. + * + * @param bulkOperations the bulkOperations + * @param transaction - JSON body containing the objects to be added + * each object must have a URI and an object body + * @param loader the loader + * @param dbEngine the db engine + * @param inputMediaType the input media type + * @return list of bulkOperations containing each introspector-wrapped object and its given URI + * @throws AAIException the AAI exception + * @throws JsonSyntaxException the json syntax exception + * @throws UnsupportedEncodingException Walks through the given transaction and unmarshals each object in it, then + * bundles each + * with its URI. + */ + private void fillBulkOperationsObjectFromTransaction(List bulkOperations, JsonObject transaction, + Loader loader, TransactionalGraphEngine dbEngine, String inputMediaType) + throws AAIException, JsonSyntaxException, UnsupportedEncodingException { + + if (transaction.has(BULK_PUT_METHOD) && this.functionAllowed(HttpMethod.PUT)) { + populateBulkOperations(bulkOperations, transaction, loader, dbEngine, inputMediaType, HttpMethod.PUT); + } else if (transaction.has(BULK_DELETE_METHOD) && this.functionAllowed(HttpMethod.DELETE)) { + populateBulkOperations(bulkOperations, transaction, loader, dbEngine, inputMediaType, HttpMethod.DELETE); + } else if (transaction.has(BULK_PATCH_METHOD) && this.functionAllowed(HttpMethod.MERGE_PATCH)) { + populateBulkOperations(bulkOperations, transaction, loader, dbEngine, inputMediaType, + HttpMethod.MERGE_PATCH); + } else { + String msg = "input payload does not follow bulk %s interface - missing %s"; + String type = "process"; + String operations = "put delete or patch"; + + if (this instanceof BulkAddConsumer) { + type = "add"; + operations = BULK_PUT_METHOD; + } + throw new AAIException("AAI_6118", String.format(msg, type, operations)); + } + + } + + private void populateBulkOperations(List bulkOperations, JsonObject item, Loader loader, + TransactionalGraphEngine dbEngine, String inputMediaType, HttpMethod method) + throws AAIException, JsonSyntaxException, UnsupportedEncodingException { + String module = getModule(); + for (int i = 0; i < item.size(); i++) { + BulkOperation bulkOperation = new BulkOperation(); + try { + + if (!(item.isJsonObject())) { + throw new AAIException("AAI_6111", + String.format("input payload does not follow %s interface", module)); + } + + JsonElement actionElement = null; + + if (item.has(BULK_PUT_METHOD)) { + actionElement = item.get(BULK_PUT_METHOD); + } else if (item.has(BULK_PATCH_METHOD)) { + actionElement = item.get(BULK_PATCH_METHOD); + } else if (item.has(BULK_DELETE_METHOD)) { + actionElement = item.get(BULK_DELETE_METHOD); + } + + if ((actionElement == null) || !actionElement.isJsonArray()) { + throw new AAIException("AAI_6111", + String.format("input payload does not follow %s interface", module)); + } + + JsonArray httpArray = actionElement.getAsJsonArray(); + for (int j = 0; j < httpArray.size(); ++j) { + + bulkOperation = new BulkOperation(); + bulkOperation.setHttpMethod(method); + + JsonObject it = httpArray.get(j).getAsJsonObject(); + JsonElement itemURIfield = it.get("uri"); + if (itemURIfield == null) { + throw new AAIException("AAI_6118", "must include object uri"); + } + + UriComponents uriComponents = + UriComponentsBuilder.fromUriString(itemURIfield.getAsString()).build(); + if (uriComponents.getPath() != null + && uriComponents.getPath().endsWith("/relationship-list/relationship")) { + if (method.equals(HttpMethod.PUT)) { + bulkOperation.setHttpMethod(HttpMethod.PUT_EDGE); + } else if (method.equals(HttpMethod.DELETE)) { + bulkOperation.setHttpMethod(HttpMethod.DELETE_EDGE); + } + } else { + bulkOperation.setHttpMethod(method); + } + + URI uri = UriBuilder.fromPath(uriComponents.getPath()).build(); + + /* + * adding the uri as soon as we have one (valid or not) lets us + * keep any errors with their corresponding uris for client feedback + */ + bulkOperation.setUri(uri); + + bulkOperation.addUriInfoQueryParams(uriComponents.getQueryParams()); + + if (!ValidateEncoding.getInstance().validate(uri)) { + throw new AAIException("AAI_3008", "uri=" + uri.getPath()); + } + + JsonElement bodyObj = new JsonObject(); + if (!bulkOperation.getHttpMethod().equals(HttpMethod.DELETE)) { + if (!(it.has("body"))) { + throw new AAIException("AAI_6118", String + .format("input payload does not follow %s interface - missing \"body\"", module)); + } + bodyObj = it.get("body"); + if (!(bodyObj.isJsonObject())) { + throw new AAIException("AAI_6111", + String.format("input payload does not follow %s interface", module)); + } + } + Gson gson = new GsonBuilder().serializeNulls().create(); + + String bodyStr = gson.toJson(bodyObj); + bulkOperation.setRawReq(bodyStr); + + if (bulkOperation.getHttpMethod().equals(HttpMethod.PUT_EDGE) + || bulkOperation.getHttpMethod().equals(HttpMethod.DELETE_EDGE)) { + Introspector obj; + try { + obj = loader.unmarshal("relationship", bodyStr, + org.onap.aai.restcore.MediaType.getEnum(inputMediaType)); + } catch (AAIUnmarshallingException e) { + throw new AAIException("AAI_3000", "object could not be unmarshalled:" + bodyStr); + + } + + bulkOperation.setIntrospector(obj); + + } else { + QueryParser uriQuery = dbEngine.getQueryBuilder().createQueryFromURI(uri); + String objName = uriQuery.getResultType(); + + Introspector obj; + + if (bulkOperation.getHttpMethod().equals(HttpMethod.DELETE)) { + obj = loader.introspectorFromName(objName); + } else { + try { + obj = loader.unmarshal(objName, bodyStr, + org.onap.aai.restcore.MediaType.getEnum(inputMediaType)); + } catch (AAIUnmarshallingException e) { + throw new AAIException("AAI_3000", "object could not be unmarshalled:" + bodyStr); + + } + this.validateIntrospector(obj, loader, uri, bulkOperation.getHttpMethod()); + + } + + bulkOperation.setIntrospector(obj); + } + bulkOperations.add(bulkOperation); + } + + } catch (AAIException e) { + // even if bulkOperation doesn't have a uri or body, this way we keep all information associated with + // this error together + // even if both are null, that indicates how the input was messed up, so still useful to carry around + // like this + bulkOperations.add(bulkOperation); + throw e; // rethrow so the right response is generated on the level above + } + } + } + + /** + * Generate response payload. + * + * @param allResponses - the list of the lists of responses from every action in every transaction requested + * @return A json string of similar format to the bulk add interface which for each response includes + * the original URI and a body with the status code of the response and the error message. + * + * Creates the payload for a single unified response from all responses generated + */ + private String generateResponsePayload(List> allResponses) { + JsonObject ret = new JsonObject(); + JsonArray retArr = new JsonArray(); + + for (List responses : allResponses) { + JsonObject tResp = new JsonObject(); + JsonArray tArrResp = new JsonArray(); + HttpMethod method = HttpMethod.PUT; + + for (BulkOperationResponse r : responses) { + + JsonObject indPayload = new JsonObject(); + method = r.getHttpMethod(); + + URI origURI = r.getUri(); + if (origURI != null) { + indPayload.addProperty("uri", origURI.getPath()); + } else { + indPayload.addProperty("uri", (String) null); + } + + JsonObject body = new JsonObject(); + + int rStatus = r.getResponse().getStatus(); + String rContents = null; + + rContents = (String) r.getResponse().getEntity(); + + body.addProperty(Integer.toString(rStatus), rContents); + indPayload.add("body", body); + + tArrResp.add(indPayload); + } + + tResp.add(this.mapHttpMethodToBulkMethod(method), tArrResp); + retArr.add(tResp); + } + ret.add("transaction", retArr); + Gson gson = new GsonBuilder().serializeNulls().create(); + return gson.toJson(ret); + } + + private String mapHttpMethodToBulkMethod(HttpMethod method) { + if (HttpMethod.PUT.equals(method) || HttpMethod.PUT_EDGE.equals(method)) { + return BULK_PUT_METHOD; + } else if (HttpMethod.DELETE.equals(method) || HttpMethod.DELETE_EDGE.equals(method)) { + return BULK_DELETE_METHOD; + } else if (HttpMethod.MERGE_PATCH.equals(method)) { + return BULK_PATCH_METHOD; + } else { + return ""; + } + } + + /** + * Adds the exception case failure response. + * + * @param allResponses the all responses + * @param e the e + * @param index - index of which transaction was being processed when the exception was thrown + * @param thisUri the this uri + * @param headers the headers + * @param info the info + * @param templateAction the template action + * @throws ErrorObjectNotFoundException + */ + private void addExceptionCaseFailureResponse(List> allResponses, Exception e, int index, + URI thisUri, HttpHeaders headers, UriInfo info, HttpMethod templateAction) { + AAIException ex = null; + + if (!(e instanceof AAIException)) { + ex = new AAIException("AAI_4000", e); + } else { + ex = (AAIException) e; + } + + if (allResponses.size() != (index + 1)) { + // index+1 bc if all transactions thus far have had a response list added + // the size will be one more than the current index (since those are offset by 1) + + // this transaction doesn't have a response list yet, so create one + Response failResp = consumerExceptionResponseGenerator(headers, info, templateAction, ex); + BulkOperationResponse uriResp = new BulkOperationResponse(templateAction, thisUri, failResp); + List transRespList = new ArrayList<>(); + transRespList.add(uriResp); + allResponses.add(transRespList); + } else { + // this transaction already has a response list, so add this failure response to it + Response failResp = consumerExceptionResponseGenerator(headers, info, templateAction, ex); + BulkOperationResponse uriResp = new BulkOperationResponse(templateAction, thisUri, failResp); + List tResps = allResponses.get(index); + tResps.add(uriResp); + } + } + + /** + * Pulls the config value for the limit of operations allowed in a bulk add/process request + * + * @throws AAIException + */ + private int getPayLoadLimit() throws AAIException { + return Integer.parseInt(AAIConfig.get(AAIConstants.AAI_BULKCONSUMER_LIMIT)); + } + + /** + * Validates the amount of operations in a request payload is allowed + * + * @param transactions - a JsonArray of all the transactions in the request payload + * @throws AAIException + */ + private void validateRequest(JsonArray transactions, HttpHeaders headers) throws AAIException { + String overrideLimit = headers.getRequestHeaders().getFirst("X-OverrideLimit"); + boolean isOverride = + overrideLimit != null && !AAIConfig.get(AAIConstants.AAI_BULKCONSUMER_OVERRIDE_LIMIT).equals("false") + && overrideLimit.equals(AAIConfig.get(AAIConstants.AAI_BULKCONSUMER_OVERRIDE_LIMIT)); + if (transactions.size() == 0) { + // case where user sends a validly formatted transactions object but + // which has no actual things in it for A&AI to do anything with + // assuming we should count this as a user error + throw new AAIException("AAI_6118", "payload had no objects to operate on"); + } else if (!isOverride && transactions.size() > getPayLoadLimit()) { + throw new AAIException("AAI_6147", + String.format("Payload limit of %s reached, please reduce payload.", getPayLoadLimit())); + } + if (!isOverride) { + int operationCount = 0; + int payLoadLimit = getPayLoadLimit(); + for (int i = 0; i < transactions.size(); i++) { + Set> entrySet = transactions.get(i).getAsJsonObject().entrySet(); + Iterator> it = entrySet.iterator(); + while (it.hasNext()) { + Map.Entry element = it.next(); + if (element.getValue() instanceof JsonArray) { + operationCount += ((JsonArray) element.getValue()).size(); + } else { + operationCount++; + } + } + if (operationCount > payLoadLimit) { + throw new AAIException("AAI_6147", + String.format("Payload limit of %s reached, please reduce payload.", payLoadLimit)); + } + } + } + } + + protected abstract String getModule(); + + protected abstract boolean functionAllowed(HttpMethod method); + + protected abstract boolean enableResourceVersion(); } diff --git a/aai-resources/src/main/java/org/onap/aai/rest/BulkProcessConsumer.java b/aai-resources/src/main/java/org/onap/aai/rest/BulkProcessConsumer.java index 1a03656..b281681 100644 --- a/aai-resources/src/main/java/org/onap/aai/rest/BulkProcessConsumer.java +++ b/aai-resources/src/main/java/org/onap/aai/rest/BulkProcessConsumer.java @@ -17,32 +17,35 @@ * limitations under the License. * ============LICENSE_END========================================================= */ + package org.onap.aai.rest; +import io.micrometer.core.annotation.Timed; + import javax.ws.rs.Path; -import io.micrometer.core.annotation.Timed; import org.onap.aai.restcore.HttpMethod; @Path("{version: v[1-9][0-9]*|latest}/bulkprocess") @Timed public class BulkProcessConsumer extends BulkConsumer { - @Override - protected boolean functionAllowed(HttpMethod method) { - - return method.equals(HttpMethod.PUT) || method.equals(HttpMethod.DELETE) || method.equals(HttpMethod.MERGE_PATCH); - } - - @Override - protected String getModule(){ - return "bulk process"; - } - - @Override - protected boolean enableResourceVersion() { - // TODO Auto-generated method stub - return true; - } + @Override + protected boolean functionAllowed(HttpMethod method) { + + return method.equals(HttpMethod.PUT) || method.equals(HttpMethod.DELETE) + || method.equals(HttpMethod.MERGE_PATCH); + } + + @Override + protected String getModule() { + return "bulk process"; + } + + @Override + protected boolean enableResourceVersion() { + // TODO Auto-generated method stub + return true; + } } diff --git a/aai-resources/src/main/java/org/onap/aai/rest/ExampleConsumer.java b/aai-resources/src/main/java/org/onap/aai/rest/ExampleConsumer.java index 8541844..b0d61af 100644 --- a/aai-resources/src/main/java/org/onap/aai/rest/ExampleConsumer.java +++ b/aai-resources/src/main/java/org/onap/aai/rest/ExampleConsumer.java @@ -17,8 +17,11 @@ * limitations under the License. * ============LICENSE_END========================================================= */ + package org.onap.aai.rest; +import io.micrometer.core.annotation.Timed; + import javax.servlet.http.HttpServletRequest; import javax.ws.rs.GET; import javax.ws.rs.Path; @@ -31,7 +34,6 @@ import javax.ws.rs.core.Response; import javax.ws.rs.core.Response.Status; import javax.ws.rs.core.UriInfo; -import io.micrometer.core.annotation.Timed; import org.onap.aai.config.SpringContextAware; import org.onap.aai.exceptions.AAIException; import org.onap.aai.introspection.Introspector; @@ -39,10 +41,10 @@ import org.onap.aai.introspection.Loader; import org.onap.aai.introspection.LoaderFactory; import org.onap.aai.introspection.MarshallerProperties; import org.onap.aai.introspection.ModelType; -import org.onap.aai.setup.SchemaVersion; import org.onap.aai.introspection.generator.CreateExample; import org.onap.aai.restcore.HttpMethod; import org.onap.aai.restcore.RESTAPI; +import org.onap.aai.setup.SchemaVersion; /** * The Class ExampleConsumer. @@ -51,56 +53,52 @@ import org.onap.aai.restcore.RESTAPI; @Timed public class ExampleConsumer extends RESTAPI { - - /** - * Gets the example. - * - * @param versionParam the version param - * @param type the type - * @param headers the headers - * @param info the info - * @param req the req - * @return the example - */ - @GET - @Path("/{objectType: [^\\/]+}") - @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) - public Response getExample(@PathParam("version")String versionParam, @PathParam("objectType")String type, @Context HttpHeaders headers, @Context UriInfo info, @Context HttpServletRequest req) { - - Status status = Status.INTERNAL_SERVER_ERROR; - Response response = null; + /** + * Gets the example. + * + * @param versionParam the version param + * @param type the type + * @param headers the headers + * @param info the info + * @param req the req + * @return the example + */ + @GET + @Path("/{objectType: [^\\/]+}") + @Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML}) + public Response getExample(@PathParam("version") String versionParam, @PathParam("objectType") String type, + @Context HttpHeaders headers, @Context UriInfo info, @Context HttpServletRequest req) { + + Status status = Status.INTERNAL_SERVER_ERROR; + Response response = null; + + try { + String mediaType = getMediaType(headers.getAcceptableMediaTypes()); + org.onap.aai.restcore.MediaType outputMediaType = org.onap.aai.restcore.MediaType.getEnum(mediaType); + + SchemaVersion version = new SchemaVersion(versionParam); + Loader loader = + SpringContextAware.getBean(LoaderFactory.class).createLoaderForVersion(ModelType.MOXY, version); + + CreateExample example = new CreateExample(loader, type); + + Introspector obj = example.getExampleObject(); + String result = ""; + if (obj != null) { + status = Status.OK; + MarshallerProperties properties = new MarshallerProperties.Builder(outputMediaType).build(); + result = obj.marshal(properties); + } else { - try { - String mediaType = getMediaType(headers.getAcceptableMediaTypes()); - org.onap.aai.restcore.MediaType outputMediaType = org.onap.aai.restcore.MediaType.getEnum(mediaType); - - SchemaVersion version = new SchemaVersion(versionParam); - Loader loader = SpringContextAware.getBean( LoaderFactory.class).createLoaderForVersion(ModelType.MOXY, version); - - CreateExample example = new CreateExample(loader, type); - - Introspector obj = example.getExampleObject(); - String result = ""; - if (obj != null) { - status = Status.OK; - MarshallerProperties properties = - new MarshallerProperties.Builder(outputMediaType).build(); - result = obj.marshal(properties); - } else { - - } - response = Response - .ok(obj) - .entity(result) - .status(status) - .type(outputMediaType.toString()).build(); - } catch (AAIException e) { - //TODO check that the details here are sensible - response = consumerExceptionResponseGenerator(headers, info, HttpMethod.GET, e); - } catch (Exception e) { - AAIException ex = new AAIException("AAI_4000", e); - response = consumerExceptionResponseGenerator(headers, info, HttpMethod.GET, ex); - } - return response; - } + } + response = Response.ok(obj).entity(result).status(status).type(outputMediaType.toString()).build(); + } catch (AAIException e) { + // TODO check that the details here are sensible + response = consumerExceptionResponseGenerator(headers, info, HttpMethod.GET, e); + } catch (Exception e) { + AAIException ex = new AAIException("AAI_4000", e); + response = consumerExceptionResponseGenerator(headers, info, HttpMethod.GET, ex); + } + return response; + } } diff --git a/aai-resources/src/main/java/org/onap/aai/rest/ExceptionHandler.java b/aai-resources/src/main/java/org/onap/aai/rest/ExceptionHandler.java index 4b3515b..ed57a7a 100644 --- a/aai-resources/src/main/java/org/onap/aai/rest/ExceptionHandler.java +++ b/aai-resources/src/main/java/org/onap/aai/rest/ExceptionHandler.java @@ -17,8 +17,13 @@ * limitations under the License. * ============LICENSE_END========================================================= */ + package org.onap.aai.rest; +import com.fasterxml.jackson.core.JsonParseException; +import com.fasterxml.jackson.databind.JsonMappingException; +import com.sun.istack.SAXParseException2; + import java.util.ArrayList; import java.util.List; @@ -33,9 +38,6 @@ import javax.ws.rs.ext.Provider; import org.onap.aai.exceptions.AAIException; import org.onap.aai.logging.ErrorLogHelper; -import com.fasterxml.jackson.core.JsonParseException; -import com.fasterxml.jackson.databind.JsonMappingException; -import com.sun.istack.SAXParseException2; /** * The Class ExceptionHandler. @@ -45,84 +47,80 @@ public class ExceptionHandler implements ExceptionMapper { @Context private HttpServletRequest request; - + @Context private HttpHeaders headers; - + /** - * @{inheritDoc} - */ + * @{inheritDoc} + */ @Override public Response toResponse(Exception exception) { - Response response = null; - ArrayList templateVars = new ArrayList(); + Response response = null; + ArrayList templateVars = new ArrayList(); - //the general case is that cxf will give us a WebApplicationException - //with a linked exception - if (exception instanceof WebApplicationException) { - WebApplicationException e = (WebApplicationException) exception; - if (e.getCause() != null) { - if (e.getCause() instanceof SAXParseException2) { - templateVars.add("UnmarshalException"); - AAIException ex = new AAIException("AAI_4007", exception); - response = Response - .status(400) - .entity(ErrorLogHelper.getRESTAPIErrorResponse(headers.getAcceptableMediaTypes(), ex, templateVars)) - .build(); - } - } - } else if (exception instanceof JsonParseException) { - //jackson does it differently so we get the direct JsonParseException - templateVars.add("JsonParseException"); - AAIException ex = new AAIException("AAI_4007", exception); - response = Response - .status(400) - .entity(ErrorLogHelper.getRESTAPIErrorResponse(headers.getAcceptableMediaTypes(), ex, templateVars)) - .build(); + // the general case is that cxf will give us a WebApplicationException + // with a linked exception + if (exception instanceof WebApplicationException) { + WebApplicationException e = (WebApplicationException) exception; + if (e.getCause() != null) { + if (e.getCause() instanceof SAXParseException2) { + templateVars.add("UnmarshalException"); + AAIException ex = new AAIException("AAI_4007", exception); + response = Response + .status(400).entity(ErrorLogHelper + .getRESTAPIErrorResponse(headers.getAcceptableMediaTypes(), ex, templateVars)) + .build(); + } + } + } else if (exception instanceof JsonParseException) { + // jackson does it differently so we get the direct JsonParseException + templateVars.add("JsonParseException"); + AAIException ex = new AAIException("AAI_4007", exception); + response = Response.status(400) + .entity(ErrorLogHelper.getRESTAPIErrorResponse(headers.getAcceptableMediaTypes(), ex, templateVars)) + .build(); } else if (exception instanceof JsonMappingException) { - //jackson does it differently so we get the direct JsonParseException - templateVars.add("JsonMappingException"); - AAIException ex = new AAIException("AAI_4007", exception); - response = Response - .status(400) - .entity(ErrorLogHelper.getRESTAPIErrorResponse(headers.getAcceptableMediaTypes(), ex, templateVars)) - .build(); - } - - // it didn't get set above, we wrap a general fault here - if (response == null) { - - Exception actual_e = exception; - if (exception instanceof WebApplicationException) { - WebApplicationException e = (WebApplicationException) exception; - response = e.getResponse(); - } else { - templateVars.add(request.getMethod()); - templateVars.add("unknown"); - AAIException ex = new AAIException("AAI_4000", actual_e); - List mediaTypes = headers.getAcceptableMediaTypes(); - int setError = 0; + // jackson does it differently so we get the direct JsonParseException + templateVars.add("JsonMappingException"); + AAIException ex = new AAIException("AAI_4007", exception); + response = Response.status(400) + .entity(ErrorLogHelper.getRESTAPIErrorResponse(headers.getAcceptableMediaTypes(), ex, templateVars)) + .build(); + } + + // it didn't get set above, we wrap a general fault here + if (response == null) { + + Exception actual_e = exception; + if (exception instanceof WebApplicationException) { + WebApplicationException e = (WebApplicationException) exception; + response = e.getResponse(); + } else { + templateVars.add(request.getMethod()); + templateVars.add("unknown"); + AAIException ex = new AAIException("AAI_4000", actual_e); + List mediaTypes = headers.getAcceptableMediaTypes(); + int setError = 0; - for (MediaType mediaType : mediaTypes) { - if (MediaType.APPLICATION_XML_TYPE.isCompatible(mediaType)) { - response = Response - .status(400) - .type(MediaType.APPLICATION_XML_TYPE) - .entity(ErrorLogHelper.getRESTAPIErrorResponse(headers.getAcceptableMediaTypes(), ex, templateVars)) - .build(); - setError = 1; - } - } - if (setError == 0) { - response = Response - .status(400) - .type(MediaType.APPLICATION_JSON_TYPE) - .entity(ErrorLogHelper.getRESTAPIErrorResponse(headers.getAcceptableMediaTypes(), ex, templateVars)) - .build(); - } - } - } - return response; + for (MediaType mediaType : mediaTypes) { + if (MediaType.APPLICATION_XML_TYPE.isCompatible(mediaType)) { + response = Response + .status(400).type(MediaType.APPLICATION_XML_TYPE).entity(ErrorLogHelper + .getRESTAPIErrorResponse(headers.getAcceptableMediaTypes(), ex, templateVars)) + .build(); + setError = 1; + } + } + if (setError == 0) { + response = Response + .status(400).type(MediaType.APPLICATION_JSON_TYPE).entity(ErrorLogHelper + .getRESTAPIErrorResponse(headers.getAcceptableMediaTypes(), ex, templateVars)) + .build(); + } + } + } + return response; } } diff --git a/aai-resources/src/main/java/org/onap/aai/rest/LegacyMoxyConsumer.java b/aai-resources/src/main/java/org/onap/aai/rest/LegacyMoxyConsumer.java index 3881b09..f429bf7 100644 --- a/aai-resources/src/main/java/org/onap/aai/rest/LegacyMoxyConsumer.java +++ b/aai-resources/src/main/java/org/onap/aai/rest/LegacyMoxyConsumer.java @@ -17,10 +17,22 @@ * limitations under the License. * ============LICENSE_END========================================================= */ + package org.onap.aai.rest; import io.micrometer.core.annotation.Timed; import io.swagger.jaxrs.PATCH; + +import java.io.UnsupportedEncodingException; +import java.net.URI; +import java.security.Principal; +import java.util.*; +import java.util.stream.Collectors; + +import javax.servlet.http.HttpServletRequest; +import javax.ws.rs.*; +import javax.ws.rs.core.*; + import org.apache.commons.lang3.ObjectUtils; import org.javatuples.Pair; import org.keycloak.adapters.springsecurity.account.SimpleKeycloakAccount; @@ -45,15 +57,6 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Controller; -import javax.servlet.http.HttpServletRequest; -import javax.ws.rs.*; -import javax.ws.rs.core.*; -import java.io.UnsupportedEncodingException; -import java.net.URI; -import java.security.Principal; -import java.util.*; -import java.util.stream.Collectors; - /** * The Class LegacyMoxyConsumer. */ @@ -62,614 +65,643 @@ import java.util.stream.Collectors; @Timed public class LegacyMoxyConsumer extends RESTAPI { - private static final Logger logger = LoggerFactory.getLogger(LegacyMoxyConsumer.class.getName()); - - /** - * - * @param content - * @param versionParam - * @param uri - * @param headers - * @param info - * @param req - * @return - */ - @PUT - @Path("/{uri: .+}") - @Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) - @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) - public Response update (String content, @PathParam("version")String versionParam, @PathParam("uri") @Encoded String uri, @Context HttpHeaders headers, @Context UriInfo info, @Context HttpServletRequest req) { - Set roles = getRoles(req.getUserPrincipal(), req.getMethod()); - MediaType mediaType = headers.getMediaType(); - return this.handleWrites(mediaType, HttpMethod.PUT, content, versionParam, uri, headers, info, roles); - } - - /** - * Update relationship. - * - * @param content the content - * @param versionParam the version param - * @param uri the uri - * @param headers the headers - * @param info the info - * @param req the req - * @return the response - */ - @PUT - @Path("/{uri: .+}/relationship-list/relationship") - @Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) - @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) - public Response updateRelationship (String content, @PathParam("version")String versionParam, @PathParam("uri") @Encoded String uri, @Context HttpHeaders headers, @Context UriInfo info, @Context HttpServletRequest req) { - - String sourceOfTruth = headers.getRequestHeaders().getFirst("X-FromAppId"); - String transId = headers.getRequestHeaders().getFirst("X-TransactionId"); - MediaType inputMediaType = headers.getMediaType(); - Response response; - Loader loader; - TransactionalGraphEngine dbEngine = null; - boolean success = true; - - try { - validateRequest(info); - SchemaVersion version = new SchemaVersion(versionParam); - - HttpEntry traversalUriHttpEntry = SpringContextAware.getBean("traversalUriHttpEntry", HttpEntry.class); - traversalUriHttpEntry.setHttpEntryProperties(version); - loader = traversalUriHttpEntry.getLoader(); - dbEngine = traversalUriHttpEntry.getDbEngine(); - - URI uriObject = UriBuilder.fromPath(uri).build(); - this.validateURI(uriObject); - - QueryParser uriQuery = dbEngine.getQueryBuilder().createQueryFromURI(uriObject); - - Introspector wrappedEntity = loader.unmarshal("relationship", content, org.onap.aai.restcore.MediaType.getEnum(this.getInputMediaType(inputMediaType))); - - DBRequest request = new DBRequest.Builder(HttpMethod.PUT_EDGE, uriObject, uriQuery, wrappedEntity, headers, info, transId).build(); - List requests = new ArrayList<>(); - requests.add(request); - Pair>> responsesTuple = traversalUriHttpEntry.process(requests, sourceOfTruth); - - response = responsesTuple.getValue1().get(0).getValue1(); - success = responsesTuple.getValue0(); - - } catch (AAIException e) { - response = consumerExceptionResponseGenerator(headers, info, HttpMethod.PUT, e); - success = false; - } catch (Exception e) { - AAIException aaiException = new AAIException("AAI_4000", e); - response = consumerExceptionResponseGenerator(headers, info, HttpMethod.PUT, aaiException); - success = false; - } finally { - if (dbEngine != null) { - if (success) { - dbEngine.commit(); - } else { - dbEngine.rollback(); - } - } - - } - - return response; - } - - /** - * Patch. - * - * @param content the content - * @param versionParam the version param - * @param uri the uri - * @param headers the headers - * @param info the info - * @param req the req - * @return the response - */ - @PATCH - @Path("/{uri: .+}") - @Consumes({ "application/merge-patch+json" }) - @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) - public Response patch (String content, @PathParam("version")String versionParam, @PathParam("uri") @Encoded String uri, @Context HttpHeaders headers, @Context UriInfo info, @Context HttpServletRequest req) { - Set roles = getRoles(req.getUserPrincipal(), req.getMethod()); - MediaType mediaType = MediaType.APPLICATION_JSON_TYPE; - return this.handleWrites(mediaType, HttpMethod.MERGE_PATCH, content, versionParam, uri, headers, info, roles); - - } - - /** - * Gets the legacy. - * - * @param content the content - * @param versionParam the version param - * @param uri the uri - * @param depthParam the depth param - * @param cleanUp the clean up - * @param headers the headers - * @param info the info - * @param req the req - * @return the legacy - */ - @GET - @Path("/{uri: .+}") - @Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) - @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) - public Response getLegacy (String content, @DefaultValue("-1") @QueryParam("resultIndex") String resultIndex, @DefaultValue("-1") @QueryParam("resultSize") String resultSize, @PathParam("version")String versionParam, @PathParam("uri") @Encoded String uri, @DefaultValue("all") @QueryParam("depth") String depthParam, @DefaultValue("false") @QueryParam("cleanup") String cleanUp, @Context HttpHeaders headers, @Context UriInfo info, @Context HttpServletRequest req) { - Set roles = getRoles(req.getUserPrincipal(), req.getMethod()); - - return runner(AAIConstants.AAI_CRUD_TIMEOUT_ENABLED, - AAIConstants.AAI_CRUD_TIMEOUT_APP, - AAIConstants.AAI_CRUD_TIMEOUT_LIMIT, - headers, - info, - HttpMethod.GET, - new AaiCallable() { - @Override - public Response process() { - return getLegacy(content, versionParam, uri, depthParam, cleanUp, headers, info, req, new HashSet(), resultIndex, resultSize, roles); - } - } - ); - } + private static final Logger logger = LoggerFactory.getLogger(LegacyMoxyConsumer.class.getName()); /** - * This method exists as a workaround for filtering out undesired query params while routing between REST consumers - * - * @param content - * @param versionParam - * @param uri - * @param depthParam - * @param cleanUp - * @param headers - * @param info - * @param req - * @param removeQueryParams - * @return - */ - public Response getLegacy(String content, String versionParam, String uri, String depthParam, String cleanUp, HttpHeaders headers, UriInfo info, HttpServletRequest req, Set removeQueryParams, String resultIndex, String resultSize, Set roles) { - String sourceOfTruth = headers.getRequestHeaders().getFirst("X-FromAppId"); - String transId = headers.getRequestHeaders().getFirst("X-TransactionId"); - Response response; - TransactionalGraphEngine dbEngine = null; - Loader loader; - - try { - validateRequest(info); - SchemaVersion version = new SchemaVersion(versionParam); - - final HttpEntry traversalUriHttpEntry = SpringContextAware.getBean("traversalUriHttpEntry", HttpEntry.class); - String serverBase = req.getRequestURL().toString().replaceAll("/(v[0-9]+|latest)/.*", "/"); - traversalUriHttpEntry.setHttpEntryProperties(version, serverBase); - dbEngine = traversalUriHttpEntry.getDbEngine(); - loader = traversalUriHttpEntry.getLoader(); - MultivaluedMap params = info.getQueryParameters(); - - params = removeNonFilterableParams(params); - - uri = uri.split("\\?")[0]; - - URI uriObject = UriBuilder.fromPath(uri).build(); - - QueryParser uriQuery = dbEngine.getQueryBuilder().createQueryFromURI(uriObject, params); - - String objType = ""; - if (!uriQuery.getContainerType().equals("")) { - objType = uriQuery.getContainerType(); - } else { - objType = uriQuery.getResultType(); - } - Introspector obj = loader.introspectorFromName(objType); - DBRequest request = - new DBRequest.Builder(HttpMethod.GET, uriObject, uriQuery, obj, headers, info, transId).build(); - List requests = new ArrayList<>(); - requests.add(request); - if (resultIndex != null && !"-1".equals(resultIndex) && resultSize != null && !"-1".equals(resultSize)) { - traversalUriHttpEntry.setPaginationIndex(Integer.parseInt(resultIndex)); - traversalUriHttpEntry.setPaginationBucket(Integer.parseInt(resultSize)); - } - Pair>> responsesTuple = traversalUriHttpEntry.process(requests, sourceOfTruth, roles); - - response = responsesTuple.getValue1().get(0).getValue1(); - - } catch (AAIException e) { - response = consumerExceptionResponseGenerator(headers, info, HttpMethod.GET, e); - } catch (Exception e ) { - AAIException ex = new AAIException("AAI_4000", e); - - response = consumerExceptionResponseGenerator(headers, info, HttpMethod.GET, ex); - } finally { - if (dbEngine != null) { - if (cleanUp.equals("true")) { - dbEngine.commit(); - } else { - dbEngine.rollback(); - } - } - } - - return response; - } - - private MultivaluedMap removeNonFilterableParams(MultivaluedMap params) { - - String[] toRemove = { "depth", "cleanup", "nodes-only", "format", "resultIndex", "resultSize", "skip-related-to"}; - Set toRemoveSet = Arrays.stream(toRemove).collect(Collectors.toSet()); - - MultivaluedMap cleanedParams = new MultivaluedHashMap<>(); - params.keySet().forEach(k -> { - if (!toRemoveSet.contains(k)) { - cleanedParams.addAll(k, params.get(k)); - } - }); - - return cleanedParams; - } - /** - * Delete. - * - * @param versionParam the version param - * @param uri the uri - * @param headers the headers - * @param info the info - * @param resourceVersion the resource version - * @param req the req - * @return the response - */ - @DELETE - @Path("/{uri: .+}") - @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) - public Response delete (@PathParam("version")String versionParam, @PathParam("uri") @Encoded String uri, @Context HttpHeaders headers, @Context UriInfo info, @QueryParam("resource-version")String resourceVersion, @Context HttpServletRequest req) { - - Set roles = getRoles(req.getUserPrincipal(), req.getMethod()); - String outputMediaType = getMediaType(headers.getAcceptableMediaTypes()); - String sourceOfTruth = headers.getRequestHeaders().getFirst("X-FromAppId"); - String transId = headers.getRequestHeaders().getFirst("X-TransactionId"); - - TransactionalGraphEngine dbEngine = null; - Response response; - - boolean success = true; - - try { - - validateRequest(info); - SchemaVersion version = new SchemaVersion(versionParam); - - HttpEntry traversalUriHttpEntry = SpringContextAware.getBean("traversalUriHttpEntry", HttpEntry.class); - traversalUriHttpEntry.setHttpEntryProperties(version); - dbEngine = traversalUriHttpEntry.getDbEngine(); - Loader loader = traversalUriHttpEntry.getLoader(); - - URI uriObject = UriBuilder.fromPath(uri).build(); - - QueryParser uriQuery = dbEngine.getQueryBuilder().createQueryFromURI(uriObject); - String objType = uriQuery.getResultType(); - Introspector obj = loader.introspectorFromName(objType); - - DBRequest request = new DBRequest.Builder(HttpMethod.DELETE, uriObject, uriQuery, obj, headers, info, transId).build(); - List requests = new ArrayList<>(); - requests.add(request); - Pair>> responsesTuple = traversalUriHttpEntry.process(requests, sourceOfTruth, roles); - - response = responsesTuple.getValue1().get(0).getValue1(); - success = responsesTuple.getValue0(); - - } catch (AAIException e) { - response = consumerExceptionResponseGenerator(headers, info, HttpMethod.DELETE, e); - success = false; - } catch (Exception e) { - AAIException ex = new AAIException("AAI_4000", e); - response = consumerExceptionResponseGenerator(headers, info, HttpMethod.DELETE, ex); - success = false; - } finally { - if (dbEngine != null) { - if (success) { - dbEngine.commit(); - } else { - dbEngine.rollback(); - } - } - } - - return response; - } - - /** - * This whole method does nothing because the body is being dropped while fielding the request. - * - * @param content the content - * @param versionParam the version param - * @param uri the uri - * @param headers the headers - * @param info the info - * @param req the req - * @return the response - */ - @DELETE - @Path("/{uri: .+}/relationship-list/relationship") - @Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) - @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) - public Response deleteRelationship (String content, @PathParam("version")String versionParam, @PathParam("uri") @Encoded String uri, @Context HttpHeaders headers, @Context UriInfo info, @Context HttpServletRequest req) { - - MediaType inputMediaType = headers.getMediaType(); - String sourceOfTruth = headers.getRequestHeaders().getFirst("X-FromAppId"); - String transId = headers.getRequestHeaders().getFirst("X-TransactionId"); - Loader loader; - TransactionalGraphEngine dbEngine = null; - Response response; - - boolean success = true; - - try { - this.validateRequest(info); - SchemaVersion version = new SchemaVersion(versionParam); - - HttpEntry traversalUriHttpEntry = SpringContextAware.getBean("traversalUriHttpEntry", HttpEntry.class); - traversalUriHttpEntry.setHttpEntryProperties(version); - loader = traversalUriHttpEntry.getLoader(); - dbEngine = traversalUriHttpEntry.getDbEngine(); - - if (content.equals("")) { - throw new AAIException("AAI_3102", "You must supply a relationship"); - } - URI uriObject = UriBuilder.fromPath(uri).build(); - this.validateURI(uriObject); - - QueryParser uriQuery = dbEngine.getQueryBuilder().createQueryFromURI(uriObject); - - Introspector wrappedEntity = loader.unmarshal("relationship", content, org.onap.aai.restcore.MediaType.getEnum(this.getInputMediaType(inputMediaType))); - - DBRequest request = new DBRequest.Builder(HttpMethod.DELETE_EDGE, uriObject, uriQuery, wrappedEntity, headers, info, transId).build(); - List requests = new ArrayList<>(); - requests.add(request); - Pair>> responsesTuple = traversalUriHttpEntry.process(requests, sourceOfTruth); - - response = responsesTuple.getValue1().get(0).getValue1(); - success = responsesTuple.getValue0(); - } catch (AAIException e) { - response = consumerExceptionResponseGenerator(headers, info, HttpMethod.DELETE, e); - success = false; - } catch (Exception e) { - AAIException ex = new AAIException("AAI_4000", e); - response = consumerExceptionResponseGenerator(headers, info, HttpMethod.DELETE, ex); - success = false; - } finally { - if (dbEngine != null) { - if (success) { - dbEngine.commit(); - } else { - dbEngine.rollback(); - } - } - } - - return response; - } - - @GET - @Path("/{uri: .+}/relationship-list") - @Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) - @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) - public Response getRelationshipList (@DefaultValue("-1") @QueryParam("resultIndex") String resultIndex, @DefaultValue("-1") @QueryParam("resultSize") String resultSize, @PathParam("version")String versionParam, @PathParam("uri") @Encoded String uri, @DefaultValue("false") @QueryParam("cleanup") String cleanUp, @Context HttpHeaders headers, @Context HttpServletRequest req,@Context UriInfo info) { - return runner(AAIConstants.AAI_CRUD_TIMEOUT_ENABLED, - AAIConstants.AAI_CRUD_TIMEOUT_APP, - AAIConstants.AAI_CRUD_TIMEOUT_LIMIT, - headers, - info, - HttpMethod.GET, - new AaiCallable() { - @Override - public Response process() { - return getRelationshipList(versionParam, req, uri, cleanUp, headers, info, resultIndex, resultSize); - } - } - ); - } - - /** - * - * @param versionParam - * @param uri - * @param cleanUp - * @param headers - * @param info - * @return - */ - public Response getRelationshipList(String versionParam, HttpServletRequest req, String uri, String cleanUp, HttpHeaders headers, UriInfo info, String resultIndex, String resultSize) { - String sourceOfTruth = headers.getRequestHeaders().getFirst("X-FromAppId"); - String transId = headers.getRequestHeaders().getFirst("X-TransactionId"); - Response response = null; - TransactionalGraphEngine dbEngine = null; - Loader loader = null; - - try { - validateRequest(info); - SchemaVersion version = new SchemaVersion(versionParam); - - final HttpEntry traversalUriHttpEntry = SpringContextAware.getBean("traversalUriHttpEntry", HttpEntry.class); - String serverBase = req.getRequestURL().toString().replaceAll("/(v[0-9]+|latest)/.*", "/"); - traversalUriHttpEntry.setHttpEntryProperties(version, serverBase); - dbEngine = traversalUriHttpEntry.getDbEngine(); - loader = traversalUriHttpEntry.getLoader(); - MultivaluedMap params = info.getQueryParameters(); - - params = removeNonFilterableParams(params); - - uri = uri.split("\\?")[0]; - - URI uriObject = UriBuilder.fromPath(uri).build(); - - QueryParser uriQuery = dbEngine.getQueryBuilder().createQueryFromURI(uriObject, params); - - String objType = ""; - if (!uriQuery.getContainerType().equals("")) { - objType = uriQuery.getContainerType(); - } else { - objType = uriQuery.getResultType(); - } - Introspector obj = loader.introspectorFromName(objType); - DBRequest request = - new DBRequest.Builder(HttpMethod.GET_RELATIONSHIP, uriObject, uriQuery, obj, headers, info, transId).build(); - List requests = new ArrayList<>(); - requests.add(request); - if (resultIndex != null && !"-1".equals(resultIndex) && resultSize != null && !"-1".equals(resultSize)) { - traversalUriHttpEntry.setPaginationIndex(Integer.parseInt(resultIndex)); - traversalUriHttpEntry.setPaginationBucket(Integer.parseInt(resultSize)); - } - Pair>> responsesTuple = traversalUriHttpEntry.process(requests, sourceOfTruth); - - response = responsesTuple.getValue1().get(0).getValue1(); - } catch (AAIException e) { - response = consumerExceptionResponseGenerator(headers, info, HttpMethod.GET_RELATIONSHIP, e); - } catch (Exception e ) { - AAIException ex = new AAIException("AAI_4000", e); - - response = consumerExceptionResponseGenerator(headers, info, HttpMethod.GET_RELATIONSHIP, ex); - } finally { - if (dbEngine != null) { - if (cleanUp.equals("true")) { - dbEngine.commit(); - } else { - dbEngine.rollback(); - } - } - } - return response; - } - - /** - * Validate request. - * - * @param info the info - * @throws AAIException the AAI exception - * @throws UnsupportedEncodingException the unsupported encoding exception - */ - private void validateRequest(UriInfo info) throws AAIException, UnsupportedEncodingException { - - if (!ValidateEncoding.getInstance().validate(info)) { - throw new AAIException("AAI_3008", "uri=" + getPath(info)); - } - } - - /** - * Gets the path. - * - * @param info the info - * @return the path - */ - private String getPath(UriInfo info) { - String path = info.getPath(false); - MultivaluedMap map = info.getQueryParameters(false); - String params = "?"; - List parmList = new ArrayList<>(); - for (String key : map.keySet()) { - for (String value : map.get(key)) { - parmList.add(key + "=" + value); - } - } - String queryParams = String.join("&", parmList); - if (!map.isEmpty()) { - path += params + queryParams; - } - - return path; - - } - - /** - * Handle writes. - * - * @param mediaType the media type - * @param method the method - * @param content the content - * @param versionParam the version param - * @param uri the uri - * @param headers the headers - * @param info the info - * @return the response - */ - private Response handleWrites(MediaType mediaType, HttpMethod method, String content, String versionParam, String uri, HttpHeaders headers, UriInfo info, Set roles) { - - Response response; - TransactionalGraphEngine dbEngine = null; - Loader loader; - SchemaVersion version; - String sourceOfTruth = headers.getRequestHeaders().getFirst("X-FromAppId"); - String transId = headers.getRequestHeaders().getFirst("X-TransactionId"); - boolean success = true; - - try { - validateRequest(info); - - version = new SchemaVersion(versionParam); - - HttpEntry traversalUriHttpEntry = SpringContextAware.getBean("traversalUriHttpEntry", HttpEntry.class); - traversalUriHttpEntry.setHttpEntryProperties(version); - loader = traversalUriHttpEntry.getLoader(); - dbEngine = traversalUriHttpEntry.getDbEngine(); - URI uriObject = UriBuilder.fromPath(uri).build(); - this.validateURI(uriObject); - QueryParser uriQuery = dbEngine.getQueryBuilder().createQueryFromURI(uriObject); - String objName = uriQuery.getResultType(); - if (content.length() == 0) { - if (mediaType.toString().contains(MediaType.APPLICATION_JSON)) { - content = "{}"; - } else { - content = ""; - } - } - Introspector obj = loader.unmarshal(objName, content, org.onap.aai.restcore.MediaType.getEnum(this.getInputMediaType(mediaType))); - if (obj == null) { - throw new AAIException("AAI_3000", "object could not be unmarshalled:" + content); - } - - if (mediaType.toString().contains(MediaType.APPLICATION_XML) && !content.equals("") && isEmptyObject(obj)) { - throw new AAIInvalidXMLNamespace(content); - } - - this.validateIntrospector(obj, loader, uriObject, method); - - DBRequest request = - new DBRequest.Builder(method, uriObject, uriQuery, obj, headers, info, transId) - .rawRequestContent(content).build(); - List requests = new ArrayList<>(); - requests.add(request); - Pair>> responsesTuple = traversalUriHttpEntry.process(requests, sourceOfTruth, roles); - - response = responsesTuple.getValue1().get(0).getValue1(); - success = responsesTuple.getValue0(); - } catch (AAIException e) { - response = consumerExceptionResponseGenerator(headers, info, method, e); - success = false; - } catch (Exception e ) { - AAIException ex = new AAIException("AAI_4000", e); - response = consumerExceptionResponseGenerator(headers, info, method, ex); - success = false; - } finally { - if (dbEngine != null) { - if (success) { - dbEngine.commit(); - } else { - dbEngine.rollback(); - } - } - } - - return response; - } - - private void validateURI(URI uri) throws AAIException { - if (hasRelatedTo(uri)) { - throw new AAIException("AAI_3010"); - } - } - private boolean hasRelatedTo(URI uri) { - - return uri.toString().contains("/" + RestTokens.COUSIN + "/"); - } - - protected boolean isEmptyObject(Introspector obj) { - return "{}".equals(obj.marshal(false)); - } + * + * @param content + * @param versionParam + * @param uri + * @param headers + * @param info + * @param req + * @return + */ + @PUT + @Path("/{uri: .+}") + @Consumes({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML}) + @Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML}) + public Response update(String content, @PathParam("version") String versionParam, + @PathParam("uri") @Encoded String uri, @Context HttpHeaders headers, @Context UriInfo info, + @Context HttpServletRequest req) { + Set roles = getRoles(req.getUserPrincipal(), req.getMethod()); + MediaType mediaType = headers.getMediaType(); + return this.handleWrites(mediaType, HttpMethod.PUT, content, versionParam, uri, headers, info, roles); + } + + /** + * Update relationship. + * + * @param content the content + * @param versionParam the version param + * @param uri the uri + * @param headers the headers + * @param info the info + * @param req the req + * @return the response + */ + @PUT + @Path("/{uri: .+}/relationship-list/relationship") + @Consumes({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML}) + @Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML}) + public Response updateRelationship(String content, @PathParam("version") String versionParam, + @PathParam("uri") @Encoded String uri, @Context HttpHeaders headers, @Context UriInfo info, + @Context HttpServletRequest req) { + + String sourceOfTruth = headers.getRequestHeaders().getFirst("X-FromAppId"); + String transId = headers.getRequestHeaders().getFirst("X-TransactionId"); + MediaType inputMediaType = headers.getMediaType(); + Response response; + Loader loader; + TransactionalGraphEngine dbEngine = null; + boolean success = true; + + try { + validateRequest(info); + SchemaVersion version = new SchemaVersion(versionParam); + + HttpEntry traversalUriHttpEntry = SpringContextAware.getBean("traversalUriHttpEntry", HttpEntry.class); + traversalUriHttpEntry.setHttpEntryProperties(version); + loader = traversalUriHttpEntry.getLoader(); + dbEngine = traversalUriHttpEntry.getDbEngine(); + + URI uriObject = UriBuilder.fromPath(uri).build(); + this.validateURI(uriObject); + + QueryParser uriQuery = dbEngine.getQueryBuilder().createQueryFromURI(uriObject); + + Introspector wrappedEntity = loader.unmarshal("relationship", content, + org.onap.aai.restcore.MediaType.getEnum(this.getInputMediaType(inputMediaType))); + + DBRequest request = new DBRequest.Builder(HttpMethod.PUT_EDGE, uriObject, uriQuery, wrappedEntity, headers, + info, transId).build(); + List requests = new ArrayList<>(); + requests.add(request); + Pair>> responsesTuple = + traversalUriHttpEntry.process(requests, sourceOfTruth); + + response = responsesTuple.getValue1().get(0).getValue1(); + success = responsesTuple.getValue0(); + + } catch (AAIException e) { + response = consumerExceptionResponseGenerator(headers, info, HttpMethod.PUT, e); + success = false; + } catch (Exception e) { + AAIException aaiException = new AAIException("AAI_4000", e); + response = consumerExceptionResponseGenerator(headers, info, HttpMethod.PUT, aaiException); + success = false; + } finally { + if (dbEngine != null) { + if (success) { + dbEngine.commit(); + } else { + dbEngine.rollback(); + } + } + + } + + return response; + } + + /** + * Patch. + * + * @param content the content + * @param versionParam the version param + * @param uri the uri + * @param headers the headers + * @param info the info + * @param req the req + * @return the response + */ + @PATCH + @Path("/{uri: .+}") + @Consumes({"application/merge-patch+json"}) + @Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML}) + public Response patch(String content, @PathParam("version") String versionParam, + @PathParam("uri") @Encoded String uri, @Context HttpHeaders headers, @Context UriInfo info, + @Context HttpServletRequest req) { + Set roles = getRoles(req.getUserPrincipal(), req.getMethod()); + MediaType mediaType = MediaType.APPLICATION_JSON_TYPE; + return this.handleWrites(mediaType, HttpMethod.MERGE_PATCH, content, versionParam, uri, headers, info, roles); + + } + + /** + * Gets the legacy. + * + * @param content the content + * @param versionParam the version param + * @param uri the uri + * @param depthParam the depth param + * @param cleanUp the clean up + * @param headers the headers + * @param info the info + * @param req the req + * @return the legacy + */ + @GET + @Path("/{uri: .+}") + @Consumes({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML}) + @Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML}) + public Response getLegacy(String content, @DefaultValue("-1") @QueryParam("resultIndex") String resultIndex, + @DefaultValue("-1") @QueryParam("resultSize") String resultSize, @PathParam("version") String versionParam, + @PathParam("uri") @Encoded String uri, @DefaultValue("all") @QueryParam("depth") String depthParam, + @DefaultValue("false") @QueryParam("cleanup") String cleanUp, @Context HttpHeaders headers, + @Context UriInfo info, @Context HttpServletRequest req) { + Set roles = getRoles(req.getUserPrincipal(), req.getMethod()); + + return runner(AAIConstants.AAI_CRUD_TIMEOUT_ENABLED, AAIConstants.AAI_CRUD_TIMEOUT_APP, + AAIConstants.AAI_CRUD_TIMEOUT_LIMIT, headers, info, HttpMethod.GET, new AaiCallable() { + @Override + public Response process() { + return getLegacy(content, versionParam, uri, depthParam, cleanUp, headers, info, req, + new HashSet(), resultIndex, resultSize, roles); + } + }); + } + + /** + * This method exists as a workaround for filtering out undesired query params while routing between REST consumers + * + * @param content + * @param versionParam + * @param uri + * @param depthParam + * @param cleanUp + * @param headers + * @param info + * @param req + * @param removeQueryParams + * @return + */ + public Response getLegacy(String content, String versionParam, String uri, String depthParam, String cleanUp, + HttpHeaders headers, UriInfo info, HttpServletRequest req, Set removeQueryParams, + String resultIndex, String resultSize, Set roles) { + String sourceOfTruth = headers.getRequestHeaders().getFirst("X-FromAppId"); + String transId = headers.getRequestHeaders().getFirst("X-TransactionId"); + Response response; + TransactionalGraphEngine dbEngine = null; + Loader loader; + + try { + validateRequest(info); + SchemaVersion version = new SchemaVersion(versionParam); + + final HttpEntry traversalUriHttpEntry = + SpringContextAware.getBean("traversalUriHttpEntry", HttpEntry.class); + String serverBase = req.getRequestURL().toString().replaceAll("/(v[0-9]+|latest)/.*", "/"); + traversalUriHttpEntry.setHttpEntryProperties(version, serverBase); + dbEngine = traversalUriHttpEntry.getDbEngine(); + loader = traversalUriHttpEntry.getLoader(); + MultivaluedMap params = info.getQueryParameters(); + + params = removeNonFilterableParams(params); + + uri = uri.split("\\?")[0]; + + URI uriObject = UriBuilder.fromPath(uri).build(); + + QueryParser uriQuery = dbEngine.getQueryBuilder().createQueryFromURI(uriObject, params); + + String objType = ""; + if (!uriQuery.getContainerType().equals("")) { + objType = uriQuery.getContainerType(); + } else { + objType = uriQuery.getResultType(); + } + Introspector obj = loader.introspectorFromName(objType); + DBRequest request = + new DBRequest.Builder(HttpMethod.GET, uriObject, uriQuery, obj, headers, info, transId).build(); + List requests = new ArrayList<>(); + requests.add(request); + if (resultIndex != null && !"-1".equals(resultIndex) && resultSize != null && !"-1".equals(resultSize)) { + traversalUriHttpEntry.setPaginationIndex(Integer.parseInt(resultIndex)); + traversalUriHttpEntry.setPaginationBucket(Integer.parseInt(resultSize)); + } + Pair>> responsesTuple = + traversalUriHttpEntry.process(requests, sourceOfTruth, roles); + + response = responsesTuple.getValue1().get(0).getValue1(); + + } catch (AAIException e) { + response = consumerExceptionResponseGenerator(headers, info, HttpMethod.GET, e); + } catch (Exception e) { + AAIException ex = new AAIException("AAI_4000", e); + + response = consumerExceptionResponseGenerator(headers, info, HttpMethod.GET, ex); + } finally { + if (dbEngine != null) { + if (cleanUp.equals("true")) { + dbEngine.commit(); + } else { + dbEngine.rollback(); + } + } + } + + return response; + } + + private MultivaluedMap removeNonFilterableParams(MultivaluedMap params) { + + String[] toRemove = + {"depth", "cleanup", "nodes-only", "format", "resultIndex", "resultSize", "skip-related-to"}; + Set toRemoveSet = Arrays.stream(toRemove).collect(Collectors.toSet()); + + MultivaluedMap cleanedParams = new MultivaluedHashMap<>(); + params.keySet().forEach(k -> { + if (!toRemoveSet.contains(k)) { + cleanedParams.addAll(k, params.get(k)); + } + }); + + return cleanedParams; + } + + /** + * Delete. + * + * @param versionParam the version param + * @param uri the uri + * @param headers the headers + * @param info the info + * @param resourceVersion the resource version + * @param req the req + * @return the response + */ + @DELETE + @Path("/{uri: .+}") + @Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML}) + public Response delete(@PathParam("version") String versionParam, @PathParam("uri") @Encoded String uri, + @Context HttpHeaders headers, @Context UriInfo info, @QueryParam("resource-version") String resourceVersion, + @Context HttpServletRequest req) { + + Set roles = getRoles(req.getUserPrincipal(), req.getMethod()); + String outputMediaType = getMediaType(headers.getAcceptableMediaTypes()); + String sourceOfTruth = headers.getRequestHeaders().getFirst("X-FromAppId"); + String transId = headers.getRequestHeaders().getFirst("X-TransactionId"); + + TransactionalGraphEngine dbEngine = null; + Response response; + + boolean success = true; + + try { + + validateRequest(info); + SchemaVersion version = new SchemaVersion(versionParam); + + HttpEntry traversalUriHttpEntry = SpringContextAware.getBean("traversalUriHttpEntry", HttpEntry.class); + traversalUriHttpEntry.setHttpEntryProperties(version); + dbEngine = traversalUriHttpEntry.getDbEngine(); + Loader loader = traversalUriHttpEntry.getLoader(); + + URI uriObject = UriBuilder.fromPath(uri).build(); + + QueryParser uriQuery = dbEngine.getQueryBuilder().createQueryFromURI(uriObject); + String objType = uriQuery.getResultType(); + Introspector obj = loader.introspectorFromName(objType); + + DBRequest request = + new DBRequest.Builder(HttpMethod.DELETE, uriObject, uriQuery, obj, headers, info, transId).build(); + List requests = new ArrayList<>(); + requests.add(request); + Pair>> responsesTuple = + traversalUriHttpEntry.process(requests, sourceOfTruth, roles); + + response = responsesTuple.getValue1().get(0).getValue1(); + success = responsesTuple.getValue0(); + + } catch (AAIException e) { + response = consumerExceptionResponseGenerator(headers, info, HttpMethod.DELETE, e); + success = false; + } catch (Exception e) { + AAIException ex = new AAIException("AAI_4000", e); + response = consumerExceptionResponseGenerator(headers, info, HttpMethod.DELETE, ex); + success = false; + } finally { + if (dbEngine != null) { + if (success) { + dbEngine.commit(); + } else { + dbEngine.rollback(); + } + } + } + + return response; + } + + /** + * This whole method does nothing because the body is being dropped while fielding the request. + * + * @param content the content + * @param versionParam the version param + * @param uri the uri + * @param headers the headers + * @param info the info + * @param req the req + * @return the response + */ + @DELETE + @Path("/{uri: .+}/relationship-list/relationship") + @Consumes({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML}) + @Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML}) + public Response deleteRelationship(String content, @PathParam("version") String versionParam, + @PathParam("uri") @Encoded String uri, @Context HttpHeaders headers, @Context UriInfo info, + @Context HttpServletRequest req) { + + MediaType inputMediaType = headers.getMediaType(); + String sourceOfTruth = headers.getRequestHeaders().getFirst("X-FromAppId"); + String transId = headers.getRequestHeaders().getFirst("X-TransactionId"); + Loader loader; + TransactionalGraphEngine dbEngine = null; + Response response; + + boolean success = true; + + try { + this.validateRequest(info); + SchemaVersion version = new SchemaVersion(versionParam); + + HttpEntry traversalUriHttpEntry = SpringContextAware.getBean("traversalUriHttpEntry", HttpEntry.class); + traversalUriHttpEntry.setHttpEntryProperties(version); + loader = traversalUriHttpEntry.getLoader(); + dbEngine = traversalUriHttpEntry.getDbEngine(); + + if (content.equals("")) { + throw new AAIException("AAI_3102", "You must supply a relationship"); + } + URI uriObject = UriBuilder.fromPath(uri).build(); + this.validateURI(uriObject); + + QueryParser uriQuery = dbEngine.getQueryBuilder().createQueryFromURI(uriObject); + + Introspector wrappedEntity = loader.unmarshal("relationship", content, + org.onap.aai.restcore.MediaType.getEnum(this.getInputMediaType(inputMediaType))); + + DBRequest request = new DBRequest.Builder(HttpMethod.DELETE_EDGE, uriObject, uriQuery, wrappedEntity, + headers, info, transId).build(); + List requests = new ArrayList<>(); + requests.add(request); + Pair>> responsesTuple = + traversalUriHttpEntry.process(requests, sourceOfTruth); + + response = responsesTuple.getValue1().get(0).getValue1(); + success = responsesTuple.getValue0(); + } catch (AAIException e) { + response = consumerExceptionResponseGenerator(headers, info, HttpMethod.DELETE, e); + success = false; + } catch (Exception e) { + AAIException ex = new AAIException("AAI_4000", e); + response = consumerExceptionResponseGenerator(headers, info, HttpMethod.DELETE, ex); + success = false; + } finally { + if (dbEngine != null) { + if (success) { + dbEngine.commit(); + } else { + dbEngine.rollback(); + } + } + } + + return response; + } + + @GET + @Path("/{uri: .+}/relationship-list") + @Consumes({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML}) + @Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML}) + public Response getRelationshipList(@DefaultValue("-1") @QueryParam("resultIndex") String resultIndex, + @DefaultValue("-1") @QueryParam("resultSize") String resultSize, @PathParam("version") String versionParam, + @PathParam("uri") @Encoded String uri, @DefaultValue("false") @QueryParam("cleanup") String cleanUp, + @Context HttpHeaders headers, @Context HttpServletRequest req, @Context UriInfo info) { + return runner(AAIConstants.AAI_CRUD_TIMEOUT_ENABLED, AAIConstants.AAI_CRUD_TIMEOUT_APP, + AAIConstants.AAI_CRUD_TIMEOUT_LIMIT, headers, info, HttpMethod.GET, new AaiCallable() { + @Override + public Response process() { + return getRelationshipList(versionParam, req, uri, cleanUp, headers, info, resultIndex, + resultSize); + } + }); + } + + /** + * + * @param versionParam + * @param uri + * @param cleanUp + * @param headers + * @param info + * @return + */ + public Response getRelationshipList(String versionParam, HttpServletRequest req, String uri, String cleanUp, + HttpHeaders headers, UriInfo info, String resultIndex, String resultSize) { + String sourceOfTruth = headers.getRequestHeaders().getFirst("X-FromAppId"); + String transId = headers.getRequestHeaders().getFirst("X-TransactionId"); + Response response = null; + TransactionalGraphEngine dbEngine = null; + Loader loader = null; + + try { + validateRequest(info); + SchemaVersion version = new SchemaVersion(versionParam); + + final HttpEntry traversalUriHttpEntry = + SpringContextAware.getBean("traversalUriHttpEntry", HttpEntry.class); + String serverBase = req.getRequestURL().toString().replaceAll("/(v[0-9]+|latest)/.*", "/"); + traversalUriHttpEntry.setHttpEntryProperties(version, serverBase); + dbEngine = traversalUriHttpEntry.getDbEngine(); + loader = traversalUriHttpEntry.getLoader(); + MultivaluedMap params = info.getQueryParameters(); + + params = removeNonFilterableParams(params); + + uri = uri.split("\\?")[0]; + + URI uriObject = UriBuilder.fromPath(uri).build(); + + QueryParser uriQuery = dbEngine.getQueryBuilder().createQueryFromURI(uriObject, params); + + String objType = ""; + if (!uriQuery.getContainerType().equals("")) { + objType = uriQuery.getContainerType(); + } else { + objType = uriQuery.getResultType(); + } + Introspector obj = loader.introspectorFromName(objType); + DBRequest request = + new DBRequest.Builder(HttpMethod.GET_RELATIONSHIP, uriObject, uriQuery, obj, headers, info, transId) + .build(); + List requests = new ArrayList<>(); + requests.add(request); + if (resultIndex != null && !"-1".equals(resultIndex) && resultSize != null && !"-1".equals(resultSize)) { + traversalUriHttpEntry.setPaginationIndex(Integer.parseInt(resultIndex)); + traversalUriHttpEntry.setPaginationBucket(Integer.parseInt(resultSize)); + } + Pair>> responsesTuple = + traversalUriHttpEntry.process(requests, sourceOfTruth); + + response = responsesTuple.getValue1().get(0).getValue1(); + } catch (AAIException e) { + response = consumerExceptionResponseGenerator(headers, info, HttpMethod.GET_RELATIONSHIP, e); + } catch (Exception e) { + AAIException ex = new AAIException("AAI_4000", e); + + response = consumerExceptionResponseGenerator(headers, info, HttpMethod.GET_RELATIONSHIP, ex); + } finally { + if (dbEngine != null) { + if (cleanUp.equals("true")) { + dbEngine.commit(); + } else { + dbEngine.rollback(); + } + } + } + return response; + } + + /** + * Validate request. + * + * @param info the info + * @throws AAIException the AAI exception + * @throws UnsupportedEncodingException the unsupported encoding exception + */ + private void validateRequest(UriInfo info) throws AAIException, UnsupportedEncodingException { + + if (!ValidateEncoding.getInstance().validate(info)) { + throw new AAIException("AAI_3008", "uri=" + getPath(info)); + } + } + + /** + * Gets the path. + * + * @param info the info + * @return the path + */ + private String getPath(UriInfo info) { + String path = info.getPath(false); + MultivaluedMap map = info.getQueryParameters(false); + String params = "?"; + List parmList = new ArrayList<>(); + for (String key : map.keySet()) { + for (String value : map.get(key)) { + parmList.add(key + "=" + value); + } + } + String queryParams = String.join("&", parmList); + if (!map.isEmpty()) { + path += params + queryParams; + } + + return path; + + } + + /** + * Handle writes. + * + * @param mediaType the media type + * @param method the method + * @param content the content + * @param versionParam the version param + * @param uri the uri + * @param headers the headers + * @param info the info + * @return the response + */ + private Response handleWrites(MediaType mediaType, HttpMethod method, String content, String versionParam, + String uri, HttpHeaders headers, UriInfo info, Set roles) { + + Response response; + TransactionalGraphEngine dbEngine = null; + Loader loader; + SchemaVersion version; + String sourceOfTruth = headers.getRequestHeaders().getFirst("X-FromAppId"); + String transId = headers.getRequestHeaders().getFirst("X-TransactionId"); + boolean success = true; + + try { + validateRequest(info); + + version = new SchemaVersion(versionParam); + + HttpEntry traversalUriHttpEntry = SpringContextAware.getBean("traversalUriHttpEntry", HttpEntry.class); + traversalUriHttpEntry.setHttpEntryProperties(version); + loader = traversalUriHttpEntry.getLoader(); + dbEngine = traversalUriHttpEntry.getDbEngine(); + URI uriObject = UriBuilder.fromPath(uri).build(); + this.validateURI(uriObject); + QueryParser uriQuery = dbEngine.getQueryBuilder().createQueryFromURI(uriObject); + String objName = uriQuery.getResultType(); + if (content.length() == 0) { + if (mediaType.toString().contains(MediaType.APPLICATION_JSON)) { + content = "{}"; + } else { + content = ""; + } + } + Introspector obj = loader.unmarshal(objName, content, + org.onap.aai.restcore.MediaType.getEnum(this.getInputMediaType(mediaType))); + if (obj == null) { + throw new AAIException("AAI_3000", "object could not be unmarshalled:" + content); + } + + if (mediaType.toString().contains(MediaType.APPLICATION_XML) && !content.equals("") + && isEmptyObject(obj)) { + throw new AAIInvalidXMLNamespace(content); + } + + this.validateIntrospector(obj, loader, uriObject, method); + + DBRequest request = new DBRequest.Builder(method, uriObject, uriQuery, obj, headers, info, transId) + .rawRequestContent(content).build(); + List requests = new ArrayList<>(); + requests.add(request); + Pair>> responsesTuple = + traversalUriHttpEntry.process(requests, sourceOfTruth, roles); + + response = responsesTuple.getValue1().get(0).getValue1(); + success = responsesTuple.getValue0(); + } catch (AAIException e) { + response = consumerExceptionResponseGenerator(headers, info, method, e); + success = false; + } catch (Exception e) { + AAIException ex = new AAIException("AAI_4000", e); + response = consumerExceptionResponseGenerator(headers, info, method, ex); + success = false; + } finally { + if (dbEngine != null) { + if (success) { + dbEngine.commit(); + } else { + dbEngine.rollback(); + } + } + } + + return response; + } + + private void validateURI(URI uri) throws AAIException { + if (hasRelatedTo(uri)) { + throw new AAIException("AAI_3010"); + } + } + + private boolean hasRelatedTo(URI uri) { + + return uri.toString().contains("/" + RestTokens.COUSIN + "/"); + } + + protected boolean isEmptyObject(Introspector obj) { + return "{}".equals(obj.marshal(false)); + } private Set getRoles(Principal userPrincipal, String method) { KeycloakAuthenticationToken token = (KeycloakAuthenticationToken) userPrincipal; @@ -682,20 +714,17 @@ public class LegacyMoxyConsumer extends RESTAPI { } // When the request is not a GET, we need to exclude ReadOnly access roles if (isNotGetRequest(method)) { - return getExcludedReadOnlyAccessRoles(account); - } + return getExcludedReadOnlyAccessRoles(account); + } return account.getRoles(); } - private Set getExcludedReadOnlyAccessRoles(SimpleKeycloakAccount account) { - return account.getRoles() - .stream() - .filter(role -> !role.endsWith(OwnerCheck.READ_ONLY_SUFFIX)) - .collect(Collectors.toSet()); - } + private Set getExcludedReadOnlyAccessRoles(SimpleKeycloakAccount account) { + return account.getRoles().stream().filter(role -> !role.endsWith(OwnerCheck.READ_ONLY_SUFFIX)) + .collect(Collectors.toSet()); + } - private boolean isNotGetRequest(String method) { - return !Action.GET.name().equalsIgnoreCase(method); - } + private boolean isNotGetRequest(String method) { + return !Action.GET.name().equalsIgnoreCase(method); + } } - diff --git a/aai-resources/src/main/java/org/onap/aai/rest/URLFromVertexIdConsumer.java b/aai-resources/src/main/java/org/onap/aai/rest/URLFromVertexIdConsumer.java index acaec5e..b57181e 100644 --- a/aai-resources/src/main/java/org/onap/aai/rest/URLFromVertexIdConsumer.java +++ b/aai-resources/src/main/java/org/onap/aai/rest/URLFromVertexIdConsumer.java @@ -17,9 +17,22 @@ * limitations under the License. * ============LICENSE_END========================================================= */ + package org.onap.aai.rest; import io.micrometer.core.annotation.Timed; + +import java.net.URI; +import java.util.Iterator; + +import javax.servlet.http.HttpServletRequest; +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.core.*; +import javax.ws.rs.core.Response.Status; + import org.apache.tinkerpop.gremlin.structure.Vertex; import org.onap.aai.config.SpringContextAware; import org.onap.aai.exceptions.AAIException; @@ -32,78 +45,70 @@ import org.onap.aai.serialization.engines.TransactionalGraphEngine; import org.onap.aai.setup.SchemaVersion; import org.onap.aai.util.AAIConfig; -import javax.servlet.http.HttpServletRequest; -import javax.ws.rs.GET; -import javax.ws.rs.Path; -import javax.ws.rs.PathParam; -import javax.ws.rs.Produces; -import javax.ws.rs.core.*; -import javax.ws.rs.core.Response.Status; -import java.net.URI; -import java.util.Iterator; - /** * The Class URLFromVertexIdConsumer. */ @Path("{version: v[1-9][0-9]*|latest}/generateurl") @Timed public class URLFromVertexIdConsumer extends RESTAPI { - private ModelType introspectorFactoryType = ModelType.MOXY; + private ModelType introspectorFactoryType = ModelType.MOXY; + + private final String ID_ENDPOINT = "/id/{vertexid: \\d+}"; + + /** + * Generate url from vertex id. + * + * @param content the content + * @param versionParam the version param + * @param vertexid the vertexid + * @param headers the headers + * @param info the info + * @param req the req + * @return the response + */ + @GET + @Path(ID_ENDPOINT) + @Produces({MediaType.WILDCARD}) + public Response generateUrlFromVertexId(String content, @PathParam("version") String versionParam, + @PathParam("vertexid") long vertexid, @Context HttpHeaders headers, @Context UriInfo info, + @Context HttpServletRequest req) { + + String sourceOfTruth = headers.getRequestHeaders().getFirst("X-FromAppId"); + + SchemaVersion version = new SchemaVersion(versionParam); + StringBuilder result = new StringBuilder(); + Response response; + TransactionalGraphEngine dbEngine = null; + try { + HttpEntry resourceHttpEntry = SpringContextAware.getBean("traversalUriHttpEntry", HttpEntry.class); + String serverBase = req.getRequestURL().toString().replaceAll("/(v[0-9]+|latest)/.*", "/"); + resourceHttpEntry.setHttpEntryProperties(version, serverBase); + dbEngine = resourceHttpEntry.getDbEngine(); - private final String ID_ENDPOINT = "/id/{vertexid: \\d+}"; - - /** - * Generate url from vertex id. - * - * @param content the content - * @param versionParam the version param - * @param vertexid the vertexid - * @param headers the headers - * @param info the info - * @param req the req - * @return the response - */ - @GET - @Path(ID_ENDPOINT) - @Produces({ MediaType.WILDCARD }) - public Response generateUrlFromVertexId(String content, @PathParam("version")String versionParam, @PathParam("vertexid")long vertexid, @Context HttpHeaders headers, @Context UriInfo info, @Context HttpServletRequest req) { - - String sourceOfTruth = headers.getRequestHeaders().getFirst("X-FromAppId"); + DBSerializer serializer = new DBSerializer(version, dbEngine, introspectorFactoryType, sourceOfTruth); - SchemaVersion version = new SchemaVersion(versionParam); - StringBuilder result = new StringBuilder(); - Response response; - TransactionalGraphEngine dbEngine = null; - try { - HttpEntry resourceHttpEntry = SpringContextAware.getBean("traversalUriHttpEntry", HttpEntry.class); - String serverBase = req.getRequestURL().toString().replaceAll("/(v[0-9]+|latest)/.*", "/"); - resourceHttpEntry.setHttpEntryProperties(version, serverBase); - dbEngine = resourceHttpEntry.getDbEngine(); - - DBSerializer serializer = new DBSerializer(version, dbEngine, introspectorFactoryType, sourceOfTruth); + Iterator thisVertex = dbEngine.asAdmin().getTraversalSource().V(vertexid); - Iterator thisVertex = dbEngine.asAdmin().getTraversalSource().V(vertexid); - - if (!thisVertex.hasNext()) { - throw new AAIException("AAI_6114", "no node at that vertex id"); - } - URI uri = serializer.getURIForVertex(thisVertex.next()); + if (!thisVertex.hasNext()) { + throw new AAIException("AAI_6114", "no node at that vertex id"); + } + URI uri = serializer.getURIForVertex(thisVertex.next()); - result.append(uri.getRawPath()); - result.insert(0, version); - result.insert(0, serverBase); - response = Response.ok().entity(result.toString()).status(Status.OK).type(MediaType.TEXT_PLAIN).build(); - } catch (AAIException e) { - //TODO check that the details here are sensible - response = consumerExceptionResponseGenerator(headers, info, HttpMethod.GET, e); - } catch (Exception e) { - AAIException ex = new AAIException("AAI_4000", e); - response = consumerExceptionResponseGenerator(headers, info, HttpMethod.GET, ex); - } finally { //to close the janusgraph transaction (I think) - if (dbEngine != null) { - dbEngine.rollback(); - } - } - return response; - } + result.append(uri.getRawPath()); + result.insert(0, version); + result.insert(0, serverBase); + response = Response.ok().entity(result.toString()).status(Status.OK).type(MediaType.TEXT_PLAIN).build(); + } catch (AAIException e) { + // TODO check that the details here are sensible + response = consumerExceptionResponseGenerator(headers, info, HttpMethod.GET, e); + } catch (Exception e) { + AAIException ex = new AAIException("AAI_4000", e); + response = consumerExceptionResponseGenerator(headers, info, HttpMethod.GET, ex); + } finally { // to close the janusgraph transaction (I think) + if (dbEngine != null) { + dbEngine.rollback(); + } + } + return response; + } } diff --git a/aai-resources/src/main/java/org/onap/aai/rest/VertexIdConsumer.java b/aai-resources/src/main/java/org/onap/aai/rest/VertexIdConsumer.java index 61853e3..a7b353e 100644 --- a/aai-resources/src/main/java/org/onap/aai/rest/VertexIdConsumer.java +++ b/aai-resources/src/main/java/org/onap/aai/rest/VertexIdConsumer.java @@ -17,9 +17,20 @@ * limitations under the License. * ============LICENSE_END========================================================= */ + package org.onap.aai.rest; import io.micrometer.core.annotation.Timed; + +import java.net.URI; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import javax.servlet.http.HttpServletRequest; +import javax.ws.rs.*; +import javax.ws.rs.core.*; + import org.apache.tinkerpop.gremlin.structure.Vertex; import org.javatuples.Pair; import org.onap.aai.config.SpringContextAware; @@ -37,14 +48,6 @@ import org.onap.aai.restcore.RESTAPI; import org.onap.aai.serialization.engines.TransactionalGraphEngine; import org.onap.aai.setup.SchemaVersion; -import javax.servlet.http.HttpServletRequest; -import javax.ws.rs.*; -import javax.ws.rs.core.*; -import java.net.URI; -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; - /** * The Class VertexIdConsumer. */ @@ -52,76 +55,80 @@ import java.util.List; @Timed public class VertexIdConsumer extends RESTAPI { - private ModelType introspectorFactoryType = ModelType.MOXY; - - private final String ID_ENDPOINT = "/id/{vertexid: \\d+}"; - - private HttpEntry resourceHttpEntry; - - /** - * Gets the by vertex id. - * - * @param content the content - * @param versionParam the version param - * @param vertexid the vertexid - * @param depthParam the depth param - * @param headers the headers - * @param info the info - * @param req the req - * @return the by vertex id - */ - @GET - @Path(ID_ENDPOINT) - @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) - public Response getByVertexId(String content, @PathParam("version")String versionParam, @PathParam("vertexid")long vertexid, @DefaultValue("all") @QueryParam("depth") String depthParam, @Context HttpHeaders headers, @Context UriInfo info, @Context HttpServletRequest req) { - - String outputMediaType = getMediaType(headers.getAcceptableMediaTypes()); - String sourceOfTruth = headers.getRequestHeaders().getFirst("X-FromAppId"); - String transId = headers.getRequestHeaders().getFirst("X-TransactionId"); - SchemaVersion version = new SchemaVersion(versionParam); - Response response = null; - TransactionalGraphEngine dbEngine = null; - try { - resourceHttpEntry = SpringContextAware.getBean("traversalUriHttpEntry", HttpEntry.class); - resourceHttpEntry.setHttpEntryProperties(version); - dbEngine = resourceHttpEntry.getDbEngine(); - Loader loader = resourceHttpEntry.getLoader(); - - - //get type of the object represented by the given id - Vertex thisVertex = null; - Iterator itr = dbEngine.asAdmin().getTraversalSource().V(vertexid); - - if (!itr.hasNext()) { - throw new AAIException("AAI_6114", "no node at that vertex id"); - } - thisVertex = itr.next(); - String objName = thisVertex.property(AAIProperties.NODE_TYPE).orElse(null); - - QueryParser query = dbEngine.getQueryBuilder(thisVertex).createQueryFromObjectName(objName); - - Introspector obj = loader.introspectorFromName(query.getResultType()); - - URI uriObject = UriBuilder.fromPath(info.getPath()).build(); - - DBRequest request = - new DBRequest.Builder(HttpMethod.GET, uriObject, query, obj, headers, info, transId) - .customMarshaller(new MarshallerProperties.Builder(org.onap.aai.restcore.MediaType.getEnum(outputMediaType)).includeRoot(true).build()).build(); - - List requests = new ArrayList<>(); - requests.add(request); - Pair>> responsesTuple = resourceHttpEntry.process(requests, sourceOfTruth); - response = responsesTuple.getValue1().get(0).getValue1(); - } catch (AAIException e){ - response = consumerExceptionResponseGenerator(headers, info, HttpMethod.GET, e); - } catch (Exception e) { - AAIException ex = new AAIException("AAI_4000", e); - response = consumerExceptionResponseGenerator(headers, info, HttpMethod.GET, ex); - } finally { //to close the janusgraph transaction (I think) - if (dbEngine != null) { - dbEngine.rollback(); - } - } - return response; - } + private ModelType introspectorFactoryType = ModelType.MOXY; + + private final String ID_ENDPOINT = "/id/{vertexid: \\d+}"; + + private HttpEntry resourceHttpEntry; + + /** + * Gets the by vertex id. + * + * @param content the content + * @param versionParam the version param + * @param vertexid the vertexid + * @param depthParam the depth param + * @param headers the headers + * @param info the info + * @param req the req + * @return the by vertex id + */ + @GET + @Path(ID_ENDPOINT) + @Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML}) + public Response getByVertexId(String content, @PathParam("version") String versionParam, + @PathParam("vertexid") long vertexid, @DefaultValue("all") @QueryParam("depth") String depthParam, + @Context HttpHeaders headers, @Context UriInfo info, @Context HttpServletRequest req) { + + String outputMediaType = getMediaType(headers.getAcceptableMediaTypes()); + String sourceOfTruth = headers.getRequestHeaders().getFirst("X-FromAppId"); + String transId = headers.getRequestHeaders().getFirst("X-TransactionId"); + SchemaVersion version = new SchemaVersion(versionParam); + Response response = null; + TransactionalGraphEngine dbEngine = null; + try { + resourceHttpEntry = SpringContextAware.getBean("traversalUriHttpEntry", HttpEntry.class); + resourceHttpEntry.setHttpEntryProperties(version); + dbEngine = resourceHttpEntry.getDbEngine(); + Loader loader = resourceHttpEntry.getLoader(); + + // get type of the object represented by the given id + Vertex thisVertex = null; + Iterator itr = dbEngine.asAdmin().getTraversalSource().V(vertexid); + + if (!itr.hasNext()) { + throw new AAIException("AAI_6114", "no node at that vertex id"); + } + thisVertex = itr.next(); + String objName = thisVertex.property(AAIProperties.NODE_TYPE).orElse(null); + + QueryParser query = dbEngine.getQueryBuilder(thisVertex).createQueryFromObjectName(objName); + + Introspector obj = loader.introspectorFromName(query.getResultType()); + + URI uriObject = UriBuilder.fromPath(info.getPath()).build(); + + DBRequest request = + new DBRequest.Builder(HttpMethod.GET, uriObject, query, obj, headers, info, transId) + .customMarshaller(new MarshallerProperties.Builder( + org.onap.aai.restcore.MediaType.getEnum(outputMediaType)).includeRoot(true).build()) + .build(); + + List requests = new ArrayList<>(); + requests.add(request); + Pair>> responsesTuple = + resourceHttpEntry.process(requests, sourceOfTruth); + response = responsesTuple.getValue1().get(0).getValue1(); + } catch (AAIException e) { + response = consumerExceptionResponseGenerator(headers, info, HttpMethod.GET, e); + } catch (Exception e) { + AAIException ex = new AAIException("AAI_4000", e); + response = consumerExceptionResponseGenerator(headers, info, HttpMethod.GET, ex); + } finally { // to close the janusgraph transaction (I think) + if (dbEngine != null) { + dbEngine.rollback(); + } + } + return response; + } } diff --git a/aai-resources/src/main/java/org/onap/aai/rest/bulk/BulkOperation.java b/aai-resources/src/main/java/org/onap/aai/rest/bulk/BulkOperation.java index 82a706f..de31b5a 100644 --- a/aai-resources/src/main/java/org/onap/aai/rest/bulk/BulkOperation.java +++ b/aai-resources/src/main/java/org/onap/aai/rest/bulk/BulkOperation.java @@ -17,6 +17,7 @@ * limitations under the License. * ============LICENSE_END========================================================= */ + package org.onap.aai.rest.bulk; import java.net.URI; @@ -32,70 +33,70 @@ import org.springframework.util.MultiValueMap; public class BulkOperation { - private URI uri = null; - private QueryParser uriQuery = null; - private Introspector introspector = null; - private HttpMethod httpMethod = null; - private String rawReq = ""; - private UriInfo uriInfo = new BulkUriInfo(); - - public UriInfo getUriInfo() { - return uriInfo; - } - - public String getRawReq() { - return rawReq; - } - - public void setRawReq(String rawReq) { - this.rawReq = rawReq; - } - - public URI getUri() { - return uri; - } - - public void setUri(URI uri) { - this.uri = uri; - } - - public QueryParser getUriQuery() { - return uriQuery; - } - - public void setUriQuery(QueryParser uriQuery) { - this.uriQuery = uriQuery; - } - - public Introspector getIntrospector() { - return introspector; - } - - public void setIntrospector(Introspector introspector) { - this.introspector = introspector; - } - - public HttpMethod getHttpMethod() { - return httpMethod; - } - - public void setHttpMethod(HttpMethod httpMethod) { - this.httpMethod = httpMethod; - } - - public void addUriInfoQueryParams(MultiValueMap queryParams) { - - BulkUriInfo bui = new BulkUriInfo(); - - for (Entry> entry : queryParams.entrySet()) { - bui.addParams(entry.getKey(), entry.getValue()); - } - - this.uriInfo = bui; - } - - public void addUriInfo(UriInfo uriInfo){ - this.uriInfo = uriInfo; - } + private URI uri = null; + private QueryParser uriQuery = null; + private Introspector introspector = null; + private HttpMethod httpMethod = null; + private String rawReq = ""; + private UriInfo uriInfo = new BulkUriInfo(); + + public UriInfo getUriInfo() { + return uriInfo; + } + + public String getRawReq() { + return rawReq; + } + + public void setRawReq(String rawReq) { + this.rawReq = rawReq; + } + + public URI getUri() { + return uri; + } + + public void setUri(URI uri) { + this.uri = uri; + } + + public QueryParser getUriQuery() { + return uriQuery; + } + + public void setUriQuery(QueryParser uriQuery) { + this.uriQuery = uriQuery; + } + + public Introspector getIntrospector() { + return introspector; + } + + public void setIntrospector(Introspector introspector) { + this.introspector = introspector; + } + + public HttpMethod getHttpMethod() { + return httpMethod; + } + + public void setHttpMethod(HttpMethod httpMethod) { + this.httpMethod = httpMethod; + } + + public void addUriInfoQueryParams(MultiValueMap queryParams) { + + BulkUriInfo bui = new BulkUriInfo(); + + for (Entry> entry : queryParams.entrySet()) { + bui.addParams(entry.getKey(), entry.getValue()); + } + + this.uriInfo = bui; + } + + public void addUriInfo(UriInfo uriInfo) { + this.uriInfo = uriInfo; + } } diff --git a/aai-resources/src/main/java/org/onap/aai/rest/bulk/BulkOperationResponse.java b/aai-resources/src/main/java/org/onap/aai/rest/bulk/BulkOperationResponse.java index 130ab1c..b621d50 100644 --- a/aai-resources/src/main/java/org/onap/aai/rest/bulk/BulkOperationResponse.java +++ b/aai-resources/src/main/java/org/onap/aai/rest/bulk/BulkOperationResponse.java @@ -17,6 +17,7 @@ * limitations under the License. * ============LICENSE_END========================================================= */ + package org.onap.aai.rest.bulk; import java.net.URI; @@ -29,61 +30,62 @@ import org.javatuples.Pair; import org.onap.aai.restcore.HttpMethod; public class BulkOperationResponse { - - private URI uri = null; - private Response response = null; - private HttpMethod httpMethod = null; - - private BulkOperationResponse() { - - } - - private BulkOperationResponse(HttpMethod httpMethod, Pair pair) { - this.httpMethod = httpMethod; - this.response = pair.getValue1(); - this.uri = pair.getValue0(); - } - - public BulkOperationResponse(HttpMethod httpMethod, URI uri, Response response) { - this.httpMethod = httpMethod; - this.response = response; - this.uri = uri; - } - - public URI getUri() { - return uri; - } - - public void setUri(URI uri) { - this.uri = uri; - } - - public Response getResponse() { - return response; - } - - public void setResponse(Response response) { - this.response = response; - } - - public HttpMethod getHttpMethod() { - return httpMethod; - } - - public void setHttpMethod(HttpMethod httpMethod) { - this.httpMethod = httpMethod; - } - - public static List processPairList(HttpMethod httpMethod, List> pairList) { - - List borList = new ArrayList<>(); - BulkOperationResponse bor; - - for (Pair pair: pairList) { - bor = new BulkOperationResponse(httpMethod, pair); - borList.add(bor); - } - - return borList; - } + + private URI uri = null; + private Response response = null; + private HttpMethod httpMethod = null; + + private BulkOperationResponse() { + + } + + private BulkOperationResponse(HttpMethod httpMethod, Pair pair) { + this.httpMethod = httpMethod; + this.response = pair.getValue1(); + this.uri = pair.getValue0(); + } + + public BulkOperationResponse(HttpMethod httpMethod, URI uri, Response response) { + this.httpMethod = httpMethod; + this.response = response; + this.uri = uri; + } + + public URI getUri() { + return uri; + } + + public void setUri(URI uri) { + this.uri = uri; + } + + public Response getResponse() { + return response; + } + + public void setResponse(Response response) { + this.response = response; + } + + public HttpMethod getHttpMethod() { + return httpMethod; + } + + public void setHttpMethod(HttpMethod httpMethod) { + this.httpMethod = httpMethod; + } + + public static List processPairList(HttpMethod httpMethod, + List> pairList) { + + List borList = new ArrayList<>(); + BulkOperationResponse bor; + + for (Pair pair : pairList) { + bor = new BulkOperationResponse(httpMethod, pair); + borList.add(bor); + } + + return borList; + } } diff --git a/aai-resources/src/main/java/org/onap/aai/rest/bulk/BulkSingleTransactionConsumer.java b/aai-resources/src/main/java/org/onap/aai/rest/bulk/BulkSingleTransactionConsumer.java index a5e5d7c..cc1e912 100644 --- a/aai-resources/src/main/java/org/onap/aai/rest/bulk/BulkSingleTransactionConsumer.java +++ b/aai-resources/src/main/java/org/onap/aai/rest/bulk/BulkSingleTransactionConsumer.java @@ -17,13 +17,24 @@ * limitations under the License. * ============LICENSE_END========================================================= */ + package org.onap.aai.rest.bulk; import com.google.gson.Gson; import com.google.gson.GsonBuilder; import com.google.gson.JsonArray; import com.google.gson.JsonParser; + import io.micrometer.core.annotation.Timed; + +import java.io.UnsupportedEncodingException; +import java.net.URI; +import java.util.*; + +import javax.servlet.http.HttpServletRequest; +import javax.ws.rs.*; +import javax.ws.rs.core.*; + import org.javatuples.Pair; import org.onap.aai.config.SpringContextAware; import org.onap.aai.exceptions.AAIException; @@ -48,422 +59,413 @@ import org.slf4j.LoggerFactory; import org.springframework.web.util.UriComponents; import org.springframework.web.util.UriComponentsBuilder; -import javax.servlet.http.HttpServletRequest; -import javax.ws.rs.*; -import javax.ws.rs.core.*; -import java.io.UnsupportedEncodingException; -import java.net.URI; -import java.util.*; - @Path(value = "{version: v[1-9][0-9]*|latest}/bulk/single-transaction") @Timed public class BulkSingleTransactionConsumer extends RESTAPI { - private static final Set validOperations = Collections.unmodifiableSet(new HashSet<>(Arrays.asList("put", "patch", "delete"))); - private static final JsonParser parser = new JsonParser(); - private int allowedOperationCount = 30; - - private static final Logger LOGGER = LoggerFactory.getLogger(BulkSingleTransactionConsumer.class); - - private final String uriPrefix; - - public BulkSingleTransactionConsumer() { - uriPrefix = SpringContextAware.getApplicationContext().getEnvironment().getProperty("schema.uri.base.path", ""); - } - - public BulkSingleTransactionConsumer(String uriPrefix) { - this.uriPrefix = uriPrefix; - } - - @POST - @Consumes(value = javax.ws.rs.core.MediaType.APPLICATION_JSON) - @Produces(value = javax.ws.rs.core.MediaType.APPLICATION_JSON) - public Response process(String content, @PathParam(value = "version")String versionParam, @Context HttpHeaders headers, @Context UriInfo info, @Context HttpServletRequest req){ - - String transId = headers.getRequestHeaders().getFirst("X-TransactionId"); - String sourceOfTruth = headers.getRequestHeaders().getFirst("X-FromAppId"); - SchemaVersion version = new SchemaVersion(versionParam); - - boolean success = true; - - TransactionalGraphEngine dbEngine = null; - TransactionResponse transactionResponse; - Response response; - - try { - - // unmarshall the payload. - Gson gson = new Gson(); - Transaction transaction; - try { - transaction = gson.fromJson(content, Transaction.class); - } catch (Exception e) { - throw new AAIException("AAI_6111", "Input payload does not follow bulk/single-transaction interface"); - } - - //set the operation count limit - setOperationCount(headers); - //validate - validate(transaction); - - //generate bulkoperations - List bulkOperations = generateBulkOperations(transaction); - - //init http entry - HttpEntry resourceHttpEntry = SpringContextAware.getBean("traversalUriHttpEntry", HttpEntry.class); - resourceHttpEntry.setHttpEntryProperties(version); - Loader loader = resourceHttpEntry.getLoader(); - dbEngine = resourceHttpEntry.getDbEngine(); - - //populate uri query - populateUriQuery(bulkOperations, dbEngine); - - //populate introspector for operations - populateIntrospectors(bulkOperations, loader); - - //generate db process from bulk operation - List dbRequests = bulkOperationToDbRequests(headers, transId, bulkOperations); - - //process db requests - Pair>> results = resourceHttpEntry.process(dbRequests, sourceOfTruth, this.enableResourceVersion()); - - //commit/rollback based on results - success = results.getValue0(); - - if (success) { //process result of db requests if all are successful - transactionResponse = buildTransactionResponse(transaction, results.getValue1()); - response = Response - .status(Response.Status.CREATED) - .entity(new GsonBuilder().serializeNulls().create().toJson(transactionResponse)) - .build(); - } else { - response = getErrorResponseForFirstFailure(transaction, results.getValue1(), info, javax.ws.rs.HttpMethod.POST, headers); - - } - - } catch (AAIException e) { - response = consumerExceptionResponseGenerator(headers, info, javax.ws.rs.HttpMethod.POST, e); - success = false; - } finally { - if (dbEngine != null) { - if(success){ - dbEngine.commit(); - LOGGER.info("Successfully committed the transaction to the database"); - } else { - dbEngine.rollback(); - LOGGER.info("Rolled back the transaction due to failure"); - } - } - } - - return response; - } - - private Response getErrorResponseForFirstFailure(Transaction transaction, List> results, UriInfo info, String action, HttpHeaders headers) throws AAIException { - final String failureInResponse = "Operation %s with action (%s) on uri (%s) failed with status code (%s), error code (%s) and msg (%s)"; - for (int i = 0; i < transaction.getOperations().size(); i++) { - if (!Response.Status.Family.familyOf(results.get(i).getValue1().getStatus()).equals(Response.Status.Family.SUCCESSFUL)) { - final JsonArray vars = parser.parse(results.get(i).getValue1().getEntity().toString()).getAsJsonObject() - .getAsJsonObject("requestError") - .getAsJsonObject("serviceException") - .getAsJsonArray("variables"); - StringBuilder sb = new StringBuilder(); - for (int j = 2; j < vars.size() - 1; j++) { - if (j != 2) { - sb.append(": "); - } - sb.append(vars.get(j).getAsString()); - } - final AAIException e = new AAIException("AAI_3000", - String.format( - failureInResponse, - i, - vars.get(0).getAsString(), - vars.get(1).getAsString(), - results.get(i).getValue1().getStatus(), - vars.get(vars.size()-1).getAsString(), - sb.toString() - )); - ArrayList templateVars = new ArrayList<>(); - templateVars.add(action); //GET, PUT, etc - templateVars.add(info.getPath()); - return Response - .status(results.get(i).getValue1().getStatus()) - .entity(ErrorLogHelper.getRESTAPIErrorResponseWithLogging(headers.getAcceptableMediaTypes(), e, templateVars)) - .build(); - } - } - LOGGER.error("Transaction Process reported failure, none found."); - throw new AAIException("AAI_3000", "Transaction Process reported failure, none found."); - } - - - /** - * Builds the response - * @param transaction the input transactions - * @param results the response of all of he operations - * @return TansactionResponse obj representing the result of the transaction - * @throws AAIException thrown if there is a failure in the result. Msg contains the details of the first failure. - */ - private TransactionResponse buildTransactionResponse(Transaction transaction, List> results) throws AAIException { - TransactionResponse transactionResponse = new TransactionResponse(); - transactionResponse.setOperationResponses(new ArrayList<>(transaction.getOperations().size())); - final String failureInResponse = "Operation %s failed with status code (%s) and msg (%s)"; - for (int i = 0; i < transaction.getOperations().size(); i++) { - if (!Response.Status.Family.familyOf(results.get(i).getValue1().getStatus()) - .equals(Response.Status.Family.SUCCESSFUL)) { - throw new AAIException("AAI_3000", - String.format( - failureInResponse, - i, - results.get(i).getValue1().getStatus(), - results.get(i).getValue1().getEntity())); - } - OperationResponse operationResponse = new OperationResponse(); - operationResponse.setResponseStatusCode(results.get(i).getValue1().getStatus()); - operationResponse.setAction(transaction.getOperations().get(i).getAction()); - operationResponse.setUri(transaction.getOperations().get(i).getUri()); - operationResponse.setBody(results.get(i).getValue1().getEntity()); - transactionResponse.getOperationResponsess().add(i, operationResponse); - } - return transactionResponse; - } - - /** - * Generate one DBRequest per BulkOperation - * @param headers request headers - * @param transId transaction id - * @param bulkOperations operations to convert - * @return One DBRequest per BulkOperation - * @throws AAIException thrown if there are any issues with the transform - */ - private List bulkOperationToDbRequests(@Context HttpHeaders headers, String transId, List bulkOperations) throws AAIException { - List requests = new ArrayList<>(); - for (int i = 0; i < bulkOperations.size(); i++) { - try { - BulkOperation bulkOperation = bulkOperations.get(i); - DBRequest request = new DBRequest.Builder( - bulkOperation.getHttpMethod(), - bulkOperation.getUri(), - bulkOperation.getUriQuery(), - bulkOperation.getIntrospector(), - headers, - bulkOperation.getUriInfo(), - transId - ).rawRequestContent(bulkOperation.getRawReq()).build(); - requests.add(request); - } catch (Exception e) { - throw new AAIException("AAI_3000", "Error with operation " + i + ": " +e.getMessage()); - } - } - return requests; - } - - /** - * Sets the uriquery for each bulk operation - * @param bulkOperations operations to generate queries for - * @param dbEngine engine for query builder generation - * @throws AAIException thrown for issues with generating uri query - */ - private void populateUriQuery(List bulkOperations, TransactionalGraphEngine dbEngine) throws AAIException { - for (int i = 0; i < bulkOperations.size(); i++) { - try { - bulkOperations.get(i).setUriQuery(dbEngine.getQueryBuilder().createQueryFromURI(bulkOperations.get(i).getUri())); - } catch (AAIException e) { - throw new AAIException(e.getCode(), "Error with operation " + i + ": " +e.getMessage()); - } catch (UnsupportedEncodingException e) { - throw new AAIException("AAI_3000", "Error with operation " + i + ": " +e.getMessage()); - } - } - } - - /** - * Sets the introspector for each bulk operation. requires that uriquery is set per operation - * @param bulkOperations operations to generate introspector for - * @param loader Loader for generating introspector - * @throws AAIException thrown for issues with generating introspector - */ - private void populateIntrospectors(List bulkOperations, Loader loader) throws AAIException { - - final String objectUnMarshallMsg = "Body of operation %s could not be unmarshalled: %s"; - Introspector obj; - for (int i = 0; i < bulkOperations.size(); i++) { - BulkOperation bulkOperation = bulkOperations.get(i); - try { - if (bulkOperation.getHttpMethod().equals(HttpMethod.PUT_EDGE) - || bulkOperation.getHttpMethod().equals(HttpMethod.DELETE_EDGE)) { - obj = loader.unmarshal("relationship", bulkOperation.getRawReq(), MediaType.APPLICATION_JSON_TYPE); - bulkOperation.setIntrospector(obj); - } else { - String objName = bulkOperation.getUriQuery().getResultType(); - if (bulkOperation.getHttpMethod().equals(HttpMethod.DELETE)) { - obj = loader.introspectorFromName(objName); - } else { - obj = loader.unmarshal(objName, bulkOperation.getRawReq(), MediaType.APPLICATION_JSON_TYPE); - this.validateIntrospector(obj, loader, bulkOperation.getUri(), bulkOperation.getHttpMethod()); - } - bulkOperation.setIntrospector(obj); - } - } catch (UnsupportedEncodingException e) { - throw new AAIException("AAI_3000", String.format(objectUnMarshallMsg, i, bulkOperation.getRawReq())); - } - } - - } - - /** - * Sets the allowedOperationCount to one of the following - * - Integer.MAX_VALUE if override limit is configured - * - Property in aaiconfig - * - 30 by default - * @param headers request header - */ - private void setOperationCount(HttpHeaders headers) { - try { - String overrideLimit = headers.getRequestHeaders().getFirst("X-OverrideLimit"); - boolean isOverride = overrideLimit != null && !AAIConfig.get(AAIConstants.AAI_BULKCONSUMER_OVERRIDE_LIMIT).equals("false") - && overrideLimit.equals(AAIConfig.get(AAIConstants.AAI_BULKCONSUMER_OVERRIDE_LIMIT)); - if (isOverride) { - allowedOperationCount = Integer.MAX_VALUE; - } else { - allowedOperationCount = AAIConfig.getInt(AAIConstants.AAI_BULKCONSUMER_LIMIT); - } - } catch (AAIException e) { - allowedOperationCount = 30; - } - } - - /** - * Converts the request transaction into a list of bulk operations - * @param transaction transaction to extract bulk operations from - * @return list of bulk operations - */ - private List generateBulkOperations(Transaction transaction) { - List bulkOperations = new ArrayList<>(transaction.getOperations().size()); - - BulkOperation bulkOperation; - for (Operation operation : transaction.getOperations()) { - bulkOperation = new BulkOperation(); - UriComponents uriComponents = UriComponentsBuilder.fromUriString(getUri(operation)).build(); - bulkOperation.setUri(UriBuilder.fromPath(uriComponents.getPath()).build()); - bulkOperation.addUriInfoQueryParams(uriComponents.getQueryParams()); - bulkOperation.setHttpMethod(getHttpMethod(operation.getAction(), bulkOperation.getUri())); - bulkOperation.setRawReq(operation.getBody().toString()); - bulkOperations.add(bulkOperation); - } - - return bulkOperations; - } - - private String getUri(Operation operation) { - String uri = operation.getUri(); - if (uri == null || uri.isEmpty()) { - return uri; - } else if (uri.charAt(0) != '/') { - uri = '/' + uri; - } - return uri.replaceAll("^" + uriPrefix + "/v\\d+", ""); - } - - - /** - * Map action to httpmethod - * @param action action to be mapped - * @param uri uri of the action - * @return HttpMethod thats action/uri maps to - */ - private HttpMethod getHttpMethod(String action, URI uri) { - HttpMethod method = HttpMethod.GET; - switch (action) { - case "put": - method = HttpMethod.PUT; - break; - case "delete": - method = HttpMethod.DELETE; - break; - case "patch": - method = HttpMethod.MERGE_PATCH; - break; - } - if (uri.getPath().endsWith("/relationship-list/relationship")) { - if (method.equals(HttpMethod.PUT)) { - method = HttpMethod.PUT_EDGE; - } else if (method.equals(HttpMethod.DELETE)) { - method = HttpMethod.DELETE_EDGE; - } - } - - return method; - } - - - /** - * For each operation validates: - * - action is provided and correct. - * - uri exists - * - body exists - * @param transaction parsed payload - * @throws AAIException with the violations in the msg - */ - private void validate(Transaction transaction) throws AAIException { - if (transaction == null) { - throw new AAIException("AAI_6111", "input payload does not follow /bulk/single-transaction interface"); - } - - if (transaction.getOperations() == null - || transaction.getOperations().isEmpty()) { - throw new AAIException("AAI_6118", " Payload has no objects to operate on"); - } else if (transaction.getOperations().size() > allowedOperationCount){ - throw new AAIException("AAI_6147", " Allowed limit = " + allowedOperationCount); - } - - final String missingFieldMsgFormat = "Operation %s missing '%s'"; - final String invalidActionMsgFormat = "Operation %s has invalid action '%s'"; - List msgs = new ArrayList<>(); - for (int i = 0; i < transaction.getOperations().size(); i++) { - final Operation operation = transaction.getOperations().get(i); - if (operation.getAction() == null || operation.getAction().isEmpty()) { - msgs.add(String.format(missingFieldMsgFormat, i, "action")); - } else if (!validOperations.contains(operation.getAction())) { - msgs.add(String.format(invalidActionMsgFormat, i, operation.getAction())); - } - if (operation.getUri() == null || operation.getUri().isEmpty()) { - msgs.add(String.format(missingFieldMsgFormat, i, "uri")); - } - if (operation.getBody() == null) { - msgs.add(String.format(missingFieldMsgFormat, i, "body")); - } - } - if (!msgs.isEmpty()) { - throw new AAIException("AAI_6111", "input payload missing required properties. [" + String.join(", ", msgs) + "]"); - } - - } - - protected boolean enableResourceVersion() { - return true; - } - - - /** - * Consumer exception response generator. - * - * @param headers the headers - * @param info the info - * @param action type of request - * @param e the e - * @return the response - */ - protected Response consumerExceptionResponseGenerator(HttpHeaders headers, UriInfo info, String action, AAIException e) { - ArrayList templateVars = new ArrayList<>(); - templateVars.add(action); //GET, PUT, etc - templateVars.add(info.getPath()); - templateVars.addAll(e.getTemplateVars()); - - ErrorLogHelper.logException(e); - return Response - .status(e.getErrorObject().getHTTPResponseCode()) - .entity(ErrorLogHelper.getRESTAPIErrorResponseWithLogging(headers.getAcceptableMediaTypes(), e, templateVars)) - .build(); - } + private static final Set validOperations = + Collections.unmodifiableSet(new HashSet<>(Arrays.asList("put", "patch", "delete"))); + private static final JsonParser parser = new JsonParser(); + private int allowedOperationCount = 30; + + private static final Logger LOGGER = LoggerFactory.getLogger(BulkSingleTransactionConsumer.class); + + private final String uriPrefix; + + public BulkSingleTransactionConsumer() { + uriPrefix = SpringContextAware.getApplicationContext().getEnvironment().getProperty("schema.uri.base.path", ""); + } + + public BulkSingleTransactionConsumer(String uriPrefix) { + this.uriPrefix = uriPrefix; + } + + @POST + @Consumes(value = javax.ws.rs.core.MediaType.APPLICATION_JSON) + @Produces(value = javax.ws.rs.core.MediaType.APPLICATION_JSON) + public Response process(String content, @PathParam(value = "version") String versionParam, + @Context HttpHeaders headers, @Context UriInfo info, @Context HttpServletRequest req) { + + String transId = headers.getRequestHeaders().getFirst("X-TransactionId"); + String sourceOfTruth = headers.getRequestHeaders().getFirst("X-FromAppId"); + SchemaVersion version = new SchemaVersion(versionParam); + + boolean success = true; + + TransactionalGraphEngine dbEngine = null; + TransactionResponse transactionResponse; + Response response; + + try { + + // unmarshall the payload. + Gson gson = new Gson(); + Transaction transaction; + try { + transaction = gson.fromJson(content, Transaction.class); + } catch (Exception e) { + throw new AAIException("AAI_6111", "Input payload does not follow bulk/single-transaction interface"); + } + + // set the operation count limit + setOperationCount(headers); + // validate + validate(transaction); + + // generate bulkoperations + List bulkOperations = generateBulkOperations(transaction); + + // init http entry + HttpEntry resourceHttpEntry = SpringContextAware.getBean("traversalUriHttpEntry", HttpEntry.class); + resourceHttpEntry.setHttpEntryProperties(version); + Loader loader = resourceHttpEntry.getLoader(); + dbEngine = resourceHttpEntry.getDbEngine(); + + // populate uri query + populateUriQuery(bulkOperations, dbEngine); + + // populate introspector for operations + populateIntrospectors(bulkOperations, loader); + + // generate db process from bulk operation + List dbRequests = bulkOperationToDbRequests(headers, transId, bulkOperations); + + // process db requests + Pair>> results = + resourceHttpEntry.process(dbRequests, sourceOfTruth, this.enableResourceVersion()); + + // commit/rollback based on results + success = results.getValue0(); + + if (success) { // process result of db requests if all are successful + transactionResponse = buildTransactionResponse(transaction, results.getValue1()); + response = Response.status(Response.Status.CREATED) + .entity(new GsonBuilder().serializeNulls().create().toJson(transactionResponse)).build(); + } else { + response = getErrorResponseForFirstFailure(transaction, results.getValue1(), info, + javax.ws.rs.HttpMethod.POST, headers); + + } + + } catch (AAIException e) { + response = consumerExceptionResponseGenerator(headers, info, javax.ws.rs.HttpMethod.POST, e); + success = false; + } finally { + if (dbEngine != null) { + if (success) { + dbEngine.commit(); + LOGGER.info("Successfully committed the transaction to the database"); + } else { + dbEngine.rollback(); + LOGGER.info("Rolled back the transaction due to failure"); + } + } + } + + return response; + } + + private Response getErrorResponseForFirstFailure(Transaction transaction, List> results, + UriInfo info, String action, HttpHeaders headers) throws AAIException { + final String failureInResponse = + "Operation %s with action (%s) on uri (%s) failed with status code (%s), error code (%s) and msg (%s)"; + for (int i = 0; i < transaction.getOperations().size(); i++) { + if (!Response.Status.Family.familyOf(results.get(i).getValue1().getStatus()) + .equals(Response.Status.Family.SUCCESSFUL)) { + final JsonArray vars = parser.parse(results.get(i).getValue1().getEntity().toString()).getAsJsonObject() + .getAsJsonObject("requestError").getAsJsonObject("serviceException") + .getAsJsonArray("variables"); + StringBuilder sb = new StringBuilder(); + for (int j = 2; j < vars.size() - 1; j++) { + if (j != 2) { + sb.append(": "); + } + sb.append(vars.get(j).getAsString()); + } + final AAIException e = new AAIException("AAI_3000", + String.format(failureInResponse, i, vars.get(0).getAsString(), vars.get(1).getAsString(), + results.get(i).getValue1().getStatus(), vars.get(vars.size() - 1).getAsString(), + sb.toString())); + ArrayList templateVars = new ArrayList<>(); + templateVars.add(action); // GET, PUT, etc + templateVars.add(info.getPath()); + return Response + .status(results.get(i).getValue1().getStatus()).entity(ErrorLogHelper + .getRESTAPIErrorResponseWithLogging(headers.getAcceptableMediaTypes(), e, templateVars)) + .build(); + } + } + LOGGER.error("Transaction Process reported failure, none found."); + throw new AAIException("AAI_3000", "Transaction Process reported failure, none found."); + } + + /** + * Builds the response + * + * @param transaction the input transactions + * @param results the response of all of he operations + * @return TansactionResponse obj representing the result of the transaction + * @throws AAIException thrown if there is a failure in the result. Msg contains the details of the first failure. + */ + private TransactionResponse buildTransactionResponse(Transaction transaction, List> results) + throws AAIException { + TransactionResponse transactionResponse = new TransactionResponse(); + transactionResponse.setOperationResponses(new ArrayList<>(transaction.getOperations().size())); + final String failureInResponse = "Operation %s failed with status code (%s) and msg (%s)"; + for (int i = 0; i < transaction.getOperations().size(); i++) { + if (!Response.Status.Family.familyOf(results.get(i).getValue1().getStatus()) + .equals(Response.Status.Family.SUCCESSFUL)) { + throw new AAIException("AAI_3000", String.format(failureInResponse, i, + results.get(i).getValue1().getStatus(), results.get(i).getValue1().getEntity())); + } + OperationResponse operationResponse = new OperationResponse(); + operationResponse.setResponseStatusCode(results.get(i).getValue1().getStatus()); + operationResponse.setAction(transaction.getOperations().get(i).getAction()); + operationResponse.setUri(transaction.getOperations().get(i).getUri()); + operationResponse.setBody(results.get(i).getValue1().getEntity()); + transactionResponse.getOperationResponsess().add(i, operationResponse); + } + return transactionResponse; + } + + /** + * Generate one DBRequest per BulkOperation + * + * @param headers request headers + * @param transId transaction id + * @param bulkOperations operations to convert + * @return One DBRequest per BulkOperation + * @throws AAIException thrown if there are any issues with the transform + */ + private List bulkOperationToDbRequests(@Context HttpHeaders headers, String transId, + List bulkOperations) throws AAIException { + List requests = new ArrayList<>(); + for (int i = 0; i < bulkOperations.size(); i++) { + try { + BulkOperation bulkOperation = bulkOperations.get(i); + DBRequest request = new DBRequest.Builder(bulkOperation.getHttpMethod(), bulkOperation.getUri(), + bulkOperation.getUriQuery(), bulkOperation.getIntrospector(), headers, + bulkOperation.getUriInfo(), transId).rawRequestContent(bulkOperation.getRawReq()).build(); + requests.add(request); + } catch (Exception e) { + throw new AAIException("AAI_3000", "Error with operation " + i + ": " + e.getMessage()); + } + } + return requests; + } + + /** + * Sets the uriquery for each bulk operation + * + * @param bulkOperations operations to generate queries for + * @param dbEngine engine for query builder generation + * @throws AAIException thrown for issues with generating uri query + */ + private void populateUriQuery(List bulkOperations, TransactionalGraphEngine dbEngine) + throws AAIException { + for (int i = 0; i < bulkOperations.size(); i++) { + try { + bulkOperations.get(i) + .setUriQuery(dbEngine.getQueryBuilder().createQueryFromURI(bulkOperations.get(i).getUri())); + } catch (AAIException e) { + throw new AAIException(e.getCode(), "Error with operation " + i + ": " + e.getMessage()); + } catch (UnsupportedEncodingException e) { + throw new AAIException("AAI_3000", "Error with operation " + i + ": " + e.getMessage()); + } + } + } + + /** + * Sets the introspector for each bulk operation. requires that uriquery is set per operation + * + * @param bulkOperations operations to generate introspector for + * @param loader Loader for generating introspector + * @throws AAIException thrown for issues with generating introspector + */ + private void populateIntrospectors(List bulkOperations, Loader loader) throws AAIException { + + final String objectUnMarshallMsg = "Body of operation %s could not be unmarshalled: %s"; + Introspector obj; + for (int i = 0; i < bulkOperations.size(); i++) { + BulkOperation bulkOperation = bulkOperations.get(i); + try { + if (bulkOperation.getHttpMethod().equals(HttpMethod.PUT_EDGE) + || bulkOperation.getHttpMethod().equals(HttpMethod.DELETE_EDGE)) { + obj = loader.unmarshal("relationship", bulkOperation.getRawReq(), MediaType.APPLICATION_JSON_TYPE); + bulkOperation.setIntrospector(obj); + } else { + String objName = bulkOperation.getUriQuery().getResultType(); + if (bulkOperation.getHttpMethod().equals(HttpMethod.DELETE)) { + obj = loader.introspectorFromName(objName); + } else { + obj = loader.unmarshal(objName, bulkOperation.getRawReq(), MediaType.APPLICATION_JSON_TYPE); + this.validateIntrospector(obj, loader, bulkOperation.getUri(), bulkOperation.getHttpMethod()); + } + bulkOperation.setIntrospector(obj); + } + } catch (UnsupportedEncodingException e) { + throw new AAIException("AAI_3000", String.format(objectUnMarshallMsg, i, bulkOperation.getRawReq())); + } + } + + } + + /** + * Sets the allowedOperationCount to one of the following + * - Integer.MAX_VALUE if override limit is configured + * - Property in aaiconfig + * - 30 by default + * + * @param headers request header + */ + private void setOperationCount(HttpHeaders headers) { + try { + String overrideLimit = headers.getRequestHeaders().getFirst("X-OverrideLimit"); + boolean isOverride = overrideLimit != null + && !AAIConfig.get(AAIConstants.AAI_BULKCONSUMER_OVERRIDE_LIMIT).equals("false") + && overrideLimit.equals(AAIConfig.get(AAIConstants.AAI_BULKCONSUMER_OVERRIDE_LIMIT)); + if (isOverride) { + allowedOperationCount = Integer.MAX_VALUE; + } else { + allowedOperationCount = AAIConfig.getInt(AAIConstants.AAI_BULKCONSUMER_LIMIT); + } + } catch (AAIException e) { + allowedOperationCount = 30; + } + } + + /** + * Converts the request transaction into a list of bulk operations + * + * @param transaction transaction to extract bulk operations from + * @return list of bulk operations + */ + private List generateBulkOperations(Transaction transaction) { + List bulkOperations = new ArrayList<>(transaction.getOperations().size()); + + BulkOperation bulkOperation; + for (Operation operation : transaction.getOperations()) { + bulkOperation = new BulkOperation(); + UriComponents uriComponents = UriComponentsBuilder.fromUriString(getUri(operation)).build(); + bulkOperation.setUri(UriBuilder.fromPath(uriComponents.getPath()).build()); + bulkOperation.addUriInfoQueryParams(uriComponents.getQueryParams()); + bulkOperation.setHttpMethod(getHttpMethod(operation.getAction(), bulkOperation.getUri())); + bulkOperation.setRawReq(operation.getBody().toString()); + bulkOperations.add(bulkOperation); + } + + return bulkOperations; + } + + private String getUri(Operation operation) { + String uri = operation.getUri(); + if (uri == null || uri.isEmpty()) { + return uri; + } else if (uri.charAt(0) != '/') { + uri = '/' + uri; + } + return uri.replaceAll("^" + uriPrefix + "/v\\d+", ""); + } + + /** + * Map action to httpmethod + * + * @param action action to be mapped + * @param uri uri of the action + * @return HttpMethod thats action/uri maps to + */ + private HttpMethod getHttpMethod(String action, URI uri) { + HttpMethod method = HttpMethod.GET; + switch (action) { + case "put": + method = HttpMethod.PUT; + break; + case "delete": + method = HttpMethod.DELETE; + break; + case "patch": + method = HttpMethod.MERGE_PATCH; + break; + } + if (uri.getPath().endsWith("/relationship-list/relationship")) { + if (method.equals(HttpMethod.PUT)) { + method = HttpMethod.PUT_EDGE; + } else if (method.equals(HttpMethod.DELETE)) { + method = HttpMethod.DELETE_EDGE; + } + } + + return method; + } + + /** + * For each operation validates: + * - action is provided and correct. + * - uri exists + * - body exists + * + * @param transaction parsed payload + * @throws AAIException with the violations in the msg + */ + private void validate(Transaction transaction) throws AAIException { + if (transaction == null) { + throw new AAIException("AAI_6111", "input payload does not follow /bulk/single-transaction interface"); + } + + if (transaction.getOperations() == null || transaction.getOperations().isEmpty()) { + throw new AAIException("AAI_6118", " Payload has no objects to operate on"); + } else if (transaction.getOperations().size() > allowedOperationCount) { + throw new AAIException("AAI_6147", " Allowed limit = " + allowedOperationCount); + } + + final String missingFieldMsgFormat = "Operation %s missing '%s'"; + final String invalidActionMsgFormat = "Operation %s has invalid action '%s'"; + List msgs = new ArrayList<>(); + for (int i = 0; i < transaction.getOperations().size(); i++) { + final Operation operation = transaction.getOperations().get(i); + if (operation.getAction() == null || operation.getAction().isEmpty()) { + msgs.add(String.format(missingFieldMsgFormat, i, "action")); + } else if (!validOperations.contains(operation.getAction())) { + msgs.add(String.format(invalidActionMsgFormat, i, operation.getAction())); + } + if (operation.getUri() == null || operation.getUri().isEmpty()) { + msgs.add(String.format(missingFieldMsgFormat, i, "uri")); + } + if (operation.getBody() == null) { + msgs.add(String.format(missingFieldMsgFormat, i, "body")); + } + } + if (!msgs.isEmpty()) { + throw new AAIException("AAI_6111", + "input payload missing required properties. [" + String.join(", ", msgs) + "]"); + } + + } + + protected boolean enableResourceVersion() { + return true; + } + + /** + * Consumer exception response generator. + * + * @param headers the headers + * @param info the info + * @param action type of request + * @param e the e + * @return the response + */ + protected Response consumerExceptionResponseGenerator(HttpHeaders headers, UriInfo info, String action, + AAIException e) { + ArrayList templateVars = new ArrayList<>(); + templateVars.add(action); // GET, PUT, etc + templateVars.add(info.getPath()); + templateVars.addAll(e.getTemplateVars()); + + ErrorLogHelper.logException(e); + return Response + .status(e.getErrorObject().getHTTPResponseCode()).entity(ErrorLogHelper + .getRESTAPIErrorResponseWithLogging(headers.getAcceptableMediaTypes(), e, templateVars)) + .build(); + } } diff --git a/aai-resources/src/main/java/org/onap/aai/rest/bulk/BulkUriInfo.java b/aai-resources/src/main/java/org/onap/aai/rest/bulk/BulkUriInfo.java index 50b218f..c1e33eb 100644 --- a/aai-resources/src/main/java/org/onap/aai/rest/bulk/BulkUriInfo.java +++ b/aai-resources/src/main/java/org/onap/aai/rest/bulk/BulkUriInfo.java @@ -17,6 +17,7 @@ * limitations under the License. * ============LICENSE_END========================================================= */ + package org.onap.aai.rest.bulk; import java.net.URI; @@ -24,107 +25,106 @@ import java.util.List; import javax.ws.rs.core.*; - public class BulkUriInfo implements UriInfo { - - private MultivaluedMap queryParams= new MultivaluedHashMap<>(); - - @Override - public String getPath() { - return null; - } - - @Override - public String getPath(boolean decode) { - return null; - } - - @Override - public List getPathSegments() { - return null; - } - - @Override - public List getPathSegments(boolean decode) { - return null; - } - - @Override - public URI getRequestUri() { - return null; - } - - @Override - public UriBuilder getRequestUriBuilder() { - return null; - } - - @Override - public URI getAbsolutePath() { - return null; - } - - @Override - public UriBuilder getAbsolutePathBuilder() { - return null; - } - - @Override - public URI getBaseUri() { - return null; - } - - @Override - public UriBuilder getBaseUriBuilder() { - return null; - } - - @Override - public MultivaluedMap getPathParameters() { - return null; - } - - @Override - public MultivaluedMap getPathParameters(boolean decode) { - return null; - } - - @Override - public MultivaluedMap getQueryParameters() { - return this.queryParams; - } - - @Override - public MultivaluedMap getQueryParameters(boolean decode) { - return this.queryParams; - } - - @Override - public List getMatchedURIs() { - return null; - } - - @Override - public List getMatchedURIs(boolean decode) { - return null; - } - - @Override - public List getMatchedResources() { - return null; - } - - @Override - public URI resolve(URI uri) { - return null; - } - - @Override - public URI relativize(URI uri) { - return null; - } - - public void addParams(String key, List list) { - this.queryParams.put(key, list); - } + + private MultivaluedMap queryParams = new MultivaluedHashMap<>(); + + @Override + public String getPath() { + return null; + } + + @Override + public String getPath(boolean decode) { + return null; + } + + @Override + public List getPathSegments() { + return null; + } + + @Override + public List getPathSegments(boolean decode) { + return null; + } + + @Override + public URI getRequestUri() { + return null; + } + + @Override + public UriBuilder getRequestUriBuilder() { + return null; + } + + @Override + public URI getAbsolutePath() { + return null; + } + + @Override + public UriBuilder getAbsolutePathBuilder() { + return null; + } + + @Override + public URI getBaseUri() { + return null; + } + + @Override + public UriBuilder getBaseUriBuilder() { + return null; + } + + @Override + public MultivaluedMap getPathParameters() { + return null; + } + + @Override + public MultivaluedMap getPathParameters(boolean decode) { + return null; + } + + @Override + public MultivaluedMap getQueryParameters() { + return this.queryParams; + } + + @Override + public MultivaluedMap getQueryParameters(boolean decode) { + return this.queryParams; + } + + @Override + public List getMatchedURIs() { + return null; + } + + @Override + public List getMatchedURIs(boolean decode) { + return null; + } + + @Override + public List getMatchedResources() { + return null; + } + + @Override + public URI resolve(URI uri) { + return null; + } + + @Override + public URI relativize(URI uri) { + return null; + } + + public void addParams(String key, List list) { + this.queryParams.put(key, list); + } } diff --git a/aai-resources/src/main/java/org/onap/aai/rest/bulk/pojos/Operation.java b/aai-resources/src/main/java/org/onap/aai/rest/bulk/pojos/Operation.java index 183f0ad..814cea0 100644 --- a/aai-resources/src/main/java/org/onap/aai/rest/bulk/pojos/Operation.java +++ b/aai-resources/src/main/java/org/onap/aai/rest/bulk/pojos/Operation.java @@ -17,6 +17,7 @@ * limitations under the License. * ============LICENSE_END========================================================= */ + package org.onap.aai.rest.bulk.pojos; import com.google.gson.*; diff --git a/aai-resources/src/main/java/org/onap/aai/rest/bulk/pojos/OperationResponse.java b/aai-resources/src/main/java/org/onap/aai/rest/bulk/pojos/OperationResponse.java index 007e434..95a6f2b 100644 --- a/aai-resources/src/main/java/org/onap/aai/rest/bulk/pojos/OperationResponse.java +++ b/aai-resources/src/main/java/org/onap/aai/rest/bulk/pojos/OperationResponse.java @@ -17,6 +17,7 @@ * limitations under the License. * ============LICENSE_END========================================================= */ + package org.onap.aai.rest.bulk.pojos; import com.google.gson.JsonObject; diff --git a/aai-resources/src/main/java/org/onap/aai/rest/bulk/pojos/Transaction.java b/aai-resources/src/main/java/org/onap/aai/rest/bulk/pojos/Transaction.java index 20329d7..6ce0dc8 100644 --- a/aai-resources/src/main/java/org/onap/aai/rest/bulk/pojos/Transaction.java +++ b/aai-resources/src/main/java/org/onap/aai/rest/bulk/pojos/Transaction.java @@ -17,6 +17,7 @@ * limitations under the License. * ============LICENSE_END========================================================= */ + package org.onap.aai.rest.bulk.pojos; import com.google.gson.annotations.SerializedName; diff --git a/aai-resources/src/main/java/org/onap/aai/rest/bulk/pojos/TransactionResponse.java b/aai-resources/src/main/java/org/onap/aai/rest/bulk/pojos/TransactionResponse.java index ce5462c..035ab06 100644 --- a/aai-resources/src/main/java/org/onap/aai/rest/bulk/pojos/TransactionResponse.java +++ b/aai-resources/src/main/java/org/onap/aai/rest/bulk/pojos/TransactionResponse.java @@ -17,6 +17,7 @@ * limitations under the License. * ============LICENSE_END========================================================= */ + package org.onap.aai.rest.bulk.pojos; import com.google.gson.annotations.SerializedName; diff --git a/aai-resources/src/main/java/org/onap/aai/rest/exceptions/AAIInvalidXMLNamespace.java b/aai-resources/src/main/java/org/onap/aai/rest/exceptions/AAIInvalidXMLNamespace.java index 5c4d9b0..e0bc148 100644 --- a/aai-resources/src/main/java/org/onap/aai/rest/exceptions/AAIInvalidXMLNamespace.java +++ b/aai-resources/src/main/java/org/onap/aai/rest/exceptions/AAIInvalidXMLNamespace.java @@ -17,23 +17,24 @@ * limitations under the License. * ============LICENSE_END========================================================= */ + package org.onap.aai.rest.exceptions; import org.onap.aai.exceptions.AAIException; public class AAIInvalidXMLNamespace extends AAIException { - - private static final long serialVersionUID = 7487333042291858169L; - public AAIInvalidXMLNamespace(String message) { - super("AAI_3011", message); - } + private static final long serialVersionUID = 7487333042291858169L; + + public AAIInvalidXMLNamespace(String message) { + super("AAI_3011", message); + } - public AAIInvalidXMLNamespace(Throwable cause) { - super("AAI_3011",cause); - } + public AAIInvalidXMLNamespace(Throwable cause) { + super("AAI_3011", cause); + } - public AAIInvalidXMLNamespace(String message, Throwable cause) { - super("AAI_3011", cause, message); - } + public AAIInvalidXMLNamespace(String message, Throwable cause) { + super("AAI_3011", cause, message); + } } diff --git a/aai-resources/src/main/java/org/onap/aai/rest/security/WebSecurityConfig.java b/aai-resources/src/main/java/org/onap/aai/rest/security/WebSecurityConfig.java index 127a490..ca303b1 100644 --- a/aai-resources/src/main/java/org/onap/aai/rest/security/WebSecurityConfig.java +++ b/aai-resources/src/main/java/org/onap/aai/rest/security/WebSecurityConfig.java @@ -21,6 +21,7 @@ * SPDX-License-Identifier: Apache-2.0 * ============LICENSE_END========================================================= */ + package org.onap.aai.rest.security; import org.keycloak.adapters.springboot.KeycloakSpringBootConfigResolver; @@ -48,10 +49,8 @@ public class WebSecurityConfig extends KeycloakWebSecurityConfigurerAdapter { @Autowired public void configureGlobal(AuthenticationManagerBuilder auth) { - KeycloakAuthenticationProvider keycloakAuthenticationProvider - = keycloakAuthenticationProvider(); - keycloakAuthenticationProvider.setGrantedAuthoritiesMapper( - new SimpleAuthorityMapper()); + KeycloakAuthenticationProvider keycloakAuthenticationProvider = keycloakAuthenticationProvider(); + keycloakAuthenticationProvider.setGrantedAuthoritiesMapper(new SimpleAuthorityMapper()); auth.authenticationProvider(keycloakAuthenticationProvider); } @@ -63,16 +62,13 @@ public class WebSecurityConfig extends KeycloakWebSecurityConfigurerAdapter { @Bean @Override protected SessionAuthenticationStrategy sessionAuthenticationStrategy() { - return new RegisterSessionAuthenticationStrategy( - new SessionRegistryImpl()); + return new RegisterSessionAuthenticationStrategy(new SessionRegistryImpl()); } @Override protected void configure(HttpSecurity http) throws Exception { super.configure(http); - http.authorizeRequests() - .antMatchers("/**") - .permitAll().and().csrf().disable(); + http.authorizeRequests().antMatchers("/**").permitAll().and().csrf().disable(); } @Override @@ -80,5 +76,4 @@ public class WebSecurityConfig extends KeycloakWebSecurityConfigurerAdapter { web.ignoring().regexMatchers("^.*/util/echo$"); } - } diff --git a/aai-resources/src/main/java/org/onap/aai/rest/util/EchoResponse.java b/aai-resources/src/main/java/org/onap/aai/rest/util/EchoResponse.java index 8b5eef6..8a66809 100644 --- a/aai-resources/src/main/java/org/onap/aai/rest/util/EchoResponse.java +++ b/aai-resources/src/main/java/org/onap/aai/rest/util/EchoResponse.java @@ -22,6 +22,7 @@ package org.onap.aai.rest.util; import java.util.ArrayList; import java.util.HashMap; + import javax.servlet.http.HttpServletRequest; import javax.ws.rs.GET; import javax.ws.rs.Path; @@ -32,6 +33,7 @@ import javax.ws.rs.core.HttpHeaders; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import javax.ws.rs.core.Response.Status; + import org.apache.commons.lang3.BooleanUtils; import org.onap.aai.exceptions.AAIException; import org.onap.aai.logging.ErrorLogHelper; @@ -66,16 +68,16 @@ public class EchoResponse extends RESTAPI { * data store. * If there is no query string, no transacction logging is done to hbase. * - * @param headers the headers - * @param req the req + * @param headers the headers + * @param req the req * @param myAction if exists will cause transaction to be logged to hbase * @return the response */ @GET @Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON}) @Path("/echo") - public Response echoResult( - @Context HttpHeaders headers, @Context HttpServletRequest req, @QueryParam("action") String myAction) { + public Response echoResult(@Context HttpHeaders headers, @Context HttpServletRequest req, + @QueryParam("action") String myAction) { String fromAppId; String transId; @@ -95,8 +97,8 @@ public class EchoResponse extends RESTAPI { templateVars.add(transId); try { - if (CHECK_DB_STATUS_ACTION.equalsIgnoreCase(myAction) || - CHECK_DB_STATUS_NOW_ACTION.equalsIgnoreCase(myAction)) { + if (CHECK_DB_STATUS_ACTION.equalsIgnoreCase(myAction) + || CHECK_DB_STATUS_NOW_ACTION.equalsIgnoreCase(myAction)) { validateDBStatus(myAction); } return generateSuccessResponse(headers, templateVars); @@ -114,7 +116,7 @@ public class EchoResponse extends RESTAPI { /** * Validates if Janus Graph can process request using AAIGraphChecker. * - * @param action expected input values 'checkDB' 'checkDBNow' + * @param action expected input values 'checkDB' 'checkDBNow' * @throws AAIException exception thrown if DB is not available */ private void validateDBStatus(String action) throws AAIException { @@ -138,17 +140,15 @@ public class EchoResponse extends RESTAPI { HashMap> exceptionList = new HashMap<>(); exceptionList.put(new AAIException("AAI_0002", "OK"), templateVariables); return Response.status(Status.OK) - .entity( - ErrorLogHelper.getRESTAPIInfoResponse(headers.getAcceptableMediaTypes(), exceptionList)).build(); + .entity(ErrorLogHelper.getRESTAPIInfoResponse(headers.getAcceptableMediaTypes(), exceptionList)) + .build(); } private Response generateFailureResponse(HttpHeaders headers, ArrayList templateVariables, - AAIException aaiException) { - return Response.status(aaiException.getErrorObject().getHTTPResponseCode()) - .entity( - ErrorLogHelper.getRESTAPIErrorResponseWithLogging( - headers.getAcceptableMediaTypes(), aaiException, templateVariables)) - .build(); + AAIException aaiException) { + return Response.status(aaiException.getErrorObject().getHTTPResponseCode()).entity(ErrorLogHelper + .getRESTAPIErrorResponseWithLogging(headers.getAcceptableMediaTypes(), aaiException, templateVariables)) + .build(); } } diff --git a/aai-resources/src/main/java/org/onap/aai/rest/util/LogFormatTools.java b/aai-resources/src/main/java/org/onap/aai/rest/util/LogFormatTools.java index 931ab0b..0ce54a8 100644 --- a/aai-resources/src/main/java/org/onap/aai/rest/util/LogFormatTools.java +++ b/aai-resources/src/main/java/org/onap/aai/rest/util/LogFormatTools.java @@ -17,6 +17,7 @@ * limitations under the License. * ============LICENSE_END========================================================= */ + package org.onap.aai.rest.util; import java.time.ZoneOffset; @@ -25,11 +26,10 @@ import java.time.format.DateTimeFormatter; public class LogFormatTools { - private static final String DATE_FORMAT = "yyyy-MM-dd'T'HH:mm:ss.SSSZ"; - private static final DateTimeFormatter DTF = DateTimeFormatter.ofPattern(DATE_FORMAT) - .withZone(ZoneOffset.UTC); - - public static String getCurrentDateTime() { - return DTF.format(ZonedDateTime.now()); - } + private static final String DATE_FORMAT = "yyyy-MM-dd'T'HH:mm:ss.SSSZ"; + private static final DateTimeFormatter DTF = DateTimeFormatter.ofPattern(DATE_FORMAT).withZone(ZoneOffset.UTC); + + public static String getCurrentDateTime() { + return DTF.format(ZonedDateTime.now()); + } } diff --git a/aai-resources/src/main/java/org/onap/aai/rest/util/ValidateEncoding.java b/aai-resources/src/main/java/org/onap/aai/rest/util/ValidateEncoding.java index 7d04bf7..520bff0 100644 --- a/aai-resources/src/main/java/org/onap/aai/rest/util/ValidateEncoding.java +++ b/aai-resources/src/main/java/org/onap/aai/rest/util/ValidateEncoding.java @@ -17,6 +17,7 @@ * limitations under the License. * ============LICENSE_END========================================================= */ + package org.onap.aai.rest.util; import java.io.UnsupportedEncodingException; @@ -32,131 +33,132 @@ import org.springframework.web.util.UriUtils; */ public class ValidateEncoding { - private final String encoding = "UTF-8"; - - /** - * Instantiates a new validate encoding. - */ - private ValidateEncoding() { - - } - - /** - * The Class Helper. - */ - private static class Helper { - - /** The Constant INSTANCE. */ - private static final ValidateEncoding INSTANCE = new ValidateEncoding(); - } - - /** - * Gets the single instance of ValidateEncoding. - * - * @return single instance of ValidateEncoding - */ - public static ValidateEncoding getInstance() { - return Helper.INSTANCE; - } - - /** - * Validate. - * - * @param uri the uri - * @return true, if successful - * @throws UnsupportedEncodingException the unsupported encoding exception - */ - public boolean validate(URI uri) throws UnsupportedEncodingException { - boolean result = true; - if (!validatePath(uri.getRawPath())) { - result = false; - } - /*if (!validateQueryParams(uri.getRawQuery())) { - result = false; - } //TODO - */ - - return result; - } - - /** - * Validate. - * - * @param info the info - * @return true, if successful - * @throws UnsupportedEncodingException the unsupported encoding exception - */ - public boolean validate(UriInfo info) throws UnsupportedEncodingException { - boolean result = true; - if (!validatePath(info.getPath(false))) { - result = false; - } - if (!validateQueryParams(info.getQueryParameters(false))) { - result = false; - } - - return result; - } - - /** - * Validate path. - * - * @param path the path - * @return true, if successful - * @throws UnsupportedEncodingException the unsupported encoding exception - */ - private boolean validatePath(String path) throws UnsupportedEncodingException { - String[] segments = path.split("/"); - boolean valid = true; - for (String segment : segments) { - if (!this.checkEncoding(segment)) { - valid = false; - } - } - - return valid; - - } - - /** - * Validate query params. - * - * @param params the params - * @return true, if successful - * @throws UnsupportedEncodingException the unsupported encoding exception - */ - private boolean validateQueryParams(MultivaluedMap params) throws UnsupportedEncodingException { - boolean valid = true; - - for (String key : params.keySet()) { - if (!this.checkEncoding(key)) { - valid = false; - } - for (String item : params.get(key)) { - if(item.contains("+")){ - item = item.replaceAll("\\+", "%20"); - } - if (!this.checkEncoding(item)) { - valid = false; - } - } - } - return valid; - } - - /** - * Check encoding. - * - * @param segment the segment - * @return true, if successful - * @throws UnsupportedEncodingException the unsupported encoding exception - */ - private boolean checkEncoding(String segment) throws UnsupportedEncodingException { - boolean result = false; - String decode = UriUtils.decode(segment, encoding); - String encode = UriUtils.encode(decode, encoding); - result = segment.equals(encode); - - return result; - } + private final String encoding = "UTF-8"; + + /** + * Instantiates a new validate encoding. + */ + private ValidateEncoding() { + + } + + /** + * The Class Helper. + */ + private static class Helper { + + /** The Constant INSTANCE. */ + private static final ValidateEncoding INSTANCE = new ValidateEncoding(); + } + + /** + * Gets the single instance of ValidateEncoding. + * + * @return single instance of ValidateEncoding + */ + public static ValidateEncoding getInstance() { + return Helper.INSTANCE; + } + + /** + * Validate. + * + * @param uri the uri + * @return true, if successful + * @throws UnsupportedEncodingException the unsupported encoding exception + */ + public boolean validate(URI uri) throws UnsupportedEncodingException { + boolean result = true; + if (!validatePath(uri.getRawPath())) { + result = false; + } + /* + * if (!validateQueryParams(uri.getRawQuery())) { + * result = false; + * } //TODO + */ + + return result; + } + + /** + * Validate. + * + * @param info the info + * @return true, if successful + * @throws UnsupportedEncodingException the unsupported encoding exception + */ + public boolean validate(UriInfo info) throws UnsupportedEncodingException { + boolean result = true; + if (!validatePath(info.getPath(false))) { + result = false; + } + if (!validateQueryParams(info.getQueryParameters(false))) { + result = false; + } + + return result; + } + + /** + * Validate path. + * + * @param path the path + * @return true, if successful + * @throws UnsupportedEncodingException the unsupported encoding exception + */ + private boolean validatePath(String path) throws UnsupportedEncodingException { + String[] segments = path.split("/"); + boolean valid = true; + for (String segment : segments) { + if (!this.checkEncoding(segment)) { + valid = false; + } + } + + return valid; + + } + + /** + * Validate query params. + * + * @param params the params + * @return true, if successful + * @throws UnsupportedEncodingException the unsupported encoding exception + */ + private boolean validateQueryParams(MultivaluedMap params) throws UnsupportedEncodingException { + boolean valid = true; + + for (String key : params.keySet()) { + if (!this.checkEncoding(key)) { + valid = false; + } + for (String item : params.get(key)) { + if (item.contains("+")) { + item = item.replaceAll("\\+", "%20"); + } + if (!this.checkEncoding(item)) { + valid = false; + } + } + } + return valid; + } + + /** + * Check encoding. + * + * @param segment the segment + * @return true, if successful + * @throws UnsupportedEncodingException the unsupported encoding exception + */ + private boolean checkEncoding(String segment) throws UnsupportedEncodingException { + boolean result = false; + String decode = UriUtils.decode(segment, encoding); + String encode = UriUtils.encode(decode, encoding); + result = segment.equals(encode); + + return result; + } } diff --git a/aai-resources/src/main/java/org/onap/aai/service/AuthorizationService.java b/aai-resources/src/main/java/org/onap/aai/service/AuthorizationService.java index 9b5a614..a5eca4e 100644 --- a/aai-resources/src/main/java/org/onap/aai/service/AuthorizationService.java +++ b/aai-resources/src/main/java/org/onap/aai/service/AuthorizationService.java @@ -17,17 +17,9 @@ * limitations under the License. * ============LICENSE_END========================================================= */ -package org.onap.aai.service; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.eclipse.jetty.util.security.Password; -import org.onap.aai.Profiles; -import org.onap.aai.util.AAIConstants; -import org.springframework.context.annotation.Profile; -import org.springframework.stereotype.Service; +package org.onap.aai.service; -import javax.annotation.PostConstruct; import java.io.IOException; import java.io.UnsupportedEncodingException; import java.nio.file.Files; @@ -37,6 +29,16 @@ import java.util.HashMap; import java.util.Map; import java.util.stream.Stream; +import javax.annotation.PostConstruct; + +import org.eclipse.jetty.util.security.Password; +import org.onap.aai.Profiles; +import org.onap.aai.util.AAIConstants; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.context.annotation.Profile; +import org.springframework.stereotype.Service; + @Profile(Profiles.ONE_WAY_SSL) @Service public class AuthorizationService { @@ -48,37 +50,38 @@ public class AuthorizationService { private static final Base64.Encoder ENCODER = Base64.getEncoder(); @PostConstruct - public void init(){ + public void init() { String basicAuthFile = getBasicAuthFilePath(); - try(Stream stream = Files.lines(Paths.get(basicAuthFile))){ + try (Stream stream = Files.lines(Paths.get(basicAuthFile))) { stream.filter(line -> !line.startsWith("#")).forEach(str -> { - byte [] bytes = null; + byte[] bytes = null; String usernamePassword = null; String accessType = null; try { - String [] userAccessType = str.split(","); + String[] userAccessType = str.split(","); - if(userAccessType == null || userAccessType.length != 2){ - throw new RuntimeException("Please check the realm.properties file as it is not conforming to the basic auth"); + if (userAccessType == null || userAccessType.length != 2) { + throw new RuntimeException( + "Please check the realm.properties file as it is not conforming to the basic auth"); } usernamePassword = userAccessType[0]; - accessType = userAccessType[1]; + accessType = userAccessType[1]; String[] usernamePasswordArray = usernamePassword.split(":"); - if(usernamePasswordArray == null || usernamePasswordArray.length != 3){ + if (usernamePasswordArray == null || usernamePasswordArray.length != 3) { throw new RuntimeException("This username / pwd is not a valid entry in realm.properties"); } String username = usernamePasswordArray[0]; String password = null; - if(str.contains("OBF:")){ + if (str.contains("OBF:")) { password = usernamePasswordArray[1] + ":" + usernamePasswordArray[2]; password = Password.deobfuscate(password); } @@ -87,8 +90,7 @@ public class AuthorizationService { authorizedUsers.put(new String(bytes), accessType); - } catch (UnsupportedEncodingException e) - { + } catch (UnsupportedEncodingException e) { logger.error("Unable to support the encoding of the file" + basicAuthFile); } @@ -99,11 +101,11 @@ public class AuthorizationService { } } - public boolean checkIfUserAuthorized(String authorization){ + public boolean checkIfUserAuthorized(String authorization) { return authorizedUsers.containsKey(authorization) && "admin".equals(authorizedUsers.get(authorization)); } - public String getBasicAuthFilePath(){ + public String getBasicAuthFilePath() { return AAIConstants.AAI_HOME_ETC_AUTH + AAIConstants.AAI_FILESEP + "realm.properties"; } } diff --git a/aai-resources/src/main/java/org/onap/aai/service/RetiredService.java b/aai-resources/src/main/java/org/onap/aai/service/RetiredService.java index 5989e31..506a097 100644 --- a/aai-resources/src/main/java/org/onap/aai/service/RetiredService.java +++ b/aai-resources/src/main/java/org/onap/aai/service/RetiredService.java @@ -17,18 +17,20 @@ * limitations under the License. * ============LICENSE_END========================================================= */ -package org.onap.aai.service; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.context.annotation.PropertySource; -import org.springframework.stereotype.Service; +package org.onap.aai.service; -import javax.annotation.PostConstruct; import java.util.Arrays; import java.util.List; import java.util.regex.Pattern; import java.util.stream.Collectors; +import javax.annotation.PostConstruct; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.PropertySource; +import org.springframework.stereotype.Service; + @Service @PropertySource("classpath:retired.properties") @PropertySource(value = "file:${server.local.startpath}/retired.properties") @@ -42,26 +44,28 @@ public class RetiredService { private List retiredAllVersionList; @PostConstruct - public void initialize(){ - this.retiredPatternsList = Arrays.stream(retiredPatterns.split(",")).map(Pattern::compile).collect(Collectors.toList()); - this.retiredAllVersionList = Arrays.stream(retiredAllVersions.split(",")).map(Pattern::compile).collect(Collectors.toList()); + public void initialize() { + this.retiredPatternsList = + Arrays.stream(retiredPatterns.split(",")).map(Pattern::compile).collect(Collectors.toList()); + this.retiredAllVersionList = + Arrays.stream(retiredAllVersions.split(",")).map(Pattern::compile).collect(Collectors.toList()); } @Value("${retired.api.pattern.list}") - public void setRetiredPatterns(String retiredPatterns){ + public void setRetiredPatterns(String retiredPatterns) { this.retiredPatterns = retiredPatterns; } - public List getRetiredPatterns(){ + public List getRetiredPatterns() { return retiredPatternsList; } @Value("${retired.api.all.versions}") - public void setRetiredAllVersions(String retiredPatterns){ + public void setRetiredAllVersions(String retiredPatterns) { this.retiredAllVersions = retiredPatterns; } - public List getRetiredAllVersionList(){ + public List getRetiredAllVersionList() { return retiredAllVersionList; } } diff --git a/aai-resources/src/main/java/org/onap/aai/tasks/AaiGraphChecker.java b/aai-resources/src/main/java/org/onap/aai/tasks/AaiGraphChecker.java index d1ea478..3c07a52 100644 --- a/aai-resources/src/main/java/org/onap/aai/tasks/AaiGraphChecker.java +++ b/aai-resources/src/main/java/org/onap/aai/tasks/AaiGraphChecker.java @@ -19,11 +19,14 @@ package org.onap.aai.tasks; import com.google.common.collect.Iterators; + import java.util.Iterator; import java.util.Timer; import java.util.TimerTask; + import javax.annotation.PostConstruct; import javax.annotation.PreDestroy; + import org.apache.commons.lang3.BooleanUtils; import org.apache.commons.lang3.Validate; import org.janusgraph.core.JanusGraphException; @@ -65,8 +68,7 @@ public class AaiGraphChecker extends TimerTask { * Enumeration of check type that can be made. */ public enum CheckerType { - ACTUAL, - CACHED + ACTUAL, CACHED } private AaiGraphChecker() { @@ -75,20 +77,13 @@ public class AaiGraphChecker extends TimerTask { @PostConstruct private void setupTimer() { - boolean scheduleEnabled = - Boolean.parseBoolean( - getConfigurationValueOrDefault( - "aai.graph.checker.task.enabled", DEFAULT_SCHEDULE_ENABLED_VALUE)); - long scheduleDelay = - Long.parseLong( - getConfigurationValueOrDefault( - "aai.graph.checker.task.delay", DEFAULT_SCHEDULE_DELAY_VALUE)); - long schedulePeriod = - Long.parseLong( - getConfigurationValueOrDefault( - "aai.graph.checker.task.period", DEFAULT_SCHEDULE_PERIOD_VALUE)); - LOGGER.debug( - "Setting up AaiGraphChecker with scheduleEnabled={}, scheduleDelay={}, schedulePeriod={} ", + boolean scheduleEnabled = Boolean.parseBoolean( + getConfigurationValueOrDefault("aai.graph.checker.task.enabled", DEFAULT_SCHEDULE_ENABLED_VALUE)); + long scheduleDelay = Long.parseLong( + getConfigurationValueOrDefault("aai.graph.checker.task.delay", DEFAULT_SCHEDULE_DELAY_VALUE)); + long schedulePeriod = Long.parseLong( + getConfigurationValueOrDefault("aai.graph.checker.task.period", DEFAULT_SCHEDULE_PERIOD_VALUE)); + LOGGER.debug("Setting up AaiGraphChecker with scheduleEnabled={}, scheduleDelay={}, schedulePeriod={} ", scheduleEnabled, scheduleDelay, schedulePeriod); if (scheduleEnabled) { @@ -120,11 +115,12 @@ public class AaiGraphChecker extends TimerTask { /** * Indicate if AAI Graph database is available either from actual db connection or from cached property state. + * * @param checkerType the type of check to be made (actual or cached). Null is not supported. * @return - *
  • true, if database is available
  • - *
  • false, if database is NOT available
  • - *
  • null, if database availability can not be determined
  • + *
  • true, if database is available
  • + *
  • false, if database is NOT available
  • + *
  • null, if database availability can not be determined
  • */ public Boolean isAaiGraphDbAvailable(CheckerType checkerType) { Validate.notNull(checkerType); @@ -169,7 +165,7 @@ public class AaiGraphChecker extends TimerTask { dbAvailable = null; } finally { if (transaction != null && !transaction.isClosed()) { - //check if transaction is open then close instead of flag + // check if transaction is open then close instead of flag try { transaction.rollback(); } catch (Exception e) { @@ -197,8 +193,7 @@ public class AaiGraphChecker extends TimerTask { try { result = AAIConfig.get(property); } catch (AAIException e) { - LOGGER.error( - "Unable to get defined configuration value for '{}' property, then default '{}' value is used", + LOGGER.error("Unable to get defined configuration value for '{}' property, then default '{}' value is used", property, defaultValue); result = defaultValue; } diff --git a/aai-resources/src/main/java/org/onap/aai/util/PositiveNumValidator.java b/aai-resources/src/main/java/org/onap/aai/util/PositiveNumValidator.java index ee58f55..609d84b 100644 --- a/aai-resources/src/main/java/org/onap/aai/util/PositiveNumValidator.java +++ b/aai-resources/src/main/java/org/onap/aai/util/PositiveNumValidator.java @@ -17,6 +17,7 @@ * limitations under the License. * ============LICENSE_END========================================================= */ + package org.onap.aai.util; import com.beust.jcommander.IParameterValidator; @@ -24,12 +25,12 @@ import com.beust.jcommander.ParameterException; public class PositiveNumValidator implements IParameterValidator { - @Override - public void validate(String name, String value) throws ParameterException { - int num = Integer.parseInt(value); + @Override + public void validate(String name, String value) throws ParameterException { + int num = Integer.parseInt(value); - if(num < 0) { - throw new ParameterException("Parameter " + name + " should be >= 0"); - } - } -} \ No newline at end of file + if (num < 0) { + throw new ParameterException("Parameter " + name + " should be >= 0"); + } + } +} diff --git a/aai-resources/src/main/java/org/onap/aai/web/JerseyConfiguration.java b/aai-resources/src/main/java/org/onap/aai/web/JerseyConfiguration.java index 80b542b..c1dc10e 100644 --- a/aai-resources/src/main/java/org/onap/aai/web/JerseyConfiguration.java +++ b/aai-resources/src/main/java/org/onap/aai/web/JerseyConfiguration.java @@ -17,21 +17,25 @@ * limitations under the License. * ============LICENSE_END========================================================= */ + package org.onap.aai.web; import static java.lang.Boolean.parseBoolean; import static java.util.Comparator.comparingInt; import com.google.common.collect.Sets; +import com.sun.jersey.api.client.filter.LoggingFilter; + import java.lang.reflect.AnnotatedElement; import java.util.Collection; import java.util.Comparator; import java.util.Set; import java.util.logging.Logger; + import javax.annotation.Priority; import javax.ws.rs.container.ContainerRequestFilter; import javax.ws.rs.container.ContainerResponseFilter; -import com.sun.jersey.api.client.filter.LoggingFilter; + import org.glassfish.jersey.server.ResourceConfig; import org.onap.aai.rest.BulkAddConsumer; import org.onap.aai.rest.BulkProcessConsumer; @@ -72,18 +76,12 @@ public class JerseyConfiguration { public ResourceConfig resourceConfig() { ResourceConfig resourceConfig = new ResourceConfig(); - Set> classes = Sets.newHashSet( - EchoResponse.class, - VertexIdConsumer.class, - ExampleConsumer.class, - BulkAddConsumer.class, - BulkProcessConsumer.class, - BulkSingleTransactionConsumer.class, - LegacyMoxyConsumer.class, - URLFromVertexIdConsumer.class - ); + Set> classes = Sets.newHashSet(EchoResponse.class, VertexIdConsumer.class, ExampleConsumer.class, + BulkAddConsumer.class, BulkProcessConsumer.class, BulkSingleTransactionConsumer.class, + LegacyMoxyConsumer.class, URLFromVertexIdConsumer.class); resourceConfig.registerClasses(classes); - registerFiltersForClasses(resourceConfig, ContainerRequestFilter.class, ContainerResponseFilter.class, AuditLogContainerFilter.class); + registerFiltersForClasses(resourceConfig, ContainerRequestFilter.class, ContainerResponseFilter.class, + AuditLogContainerFilter.class); if (isLoggingEnabled()) { logRequests(resourceConfig); @@ -103,10 +101,8 @@ public class JerseyConfiguration { filters.addAll(reflections.getSubTypesOf(clazz)); throwIfPriorityAnnotationAbsent(filters); - filters.stream() - .filter(this::isEnabledByActiveProfiles) - .sorted(priorityComparator()) - .forEach(resourceConfig::register); + filters.stream().filter(this::isEnabledByActiveProfiles).sorted(priorityComparator()) + .forEach(resourceConfig::register); } private void throwIfPriorityAnnotationAbsent(Collection> classes) { @@ -130,8 +126,8 @@ public class JerseyConfiguration { } private boolean isEnabledByActiveProfiles(AnnotatedElement annotatedElement) { - return !annotatedElement.isAnnotationPresent(Profile.class) || - environment.acceptsProfiles(annotatedElement.getAnnotation(Profile.class).value()); + return !annotatedElement.isAnnotationPresent(Profile.class) + || environment.acceptsProfiles(annotatedElement.getAnnotation(Profile.class).value()); } private class MissingFilterPriorityException extends RuntimeException { @@ -139,4 +135,4 @@ public class JerseyConfiguration { super("Container filter " + clazz.getName() + " does not have @Priority annotation"); } } -} \ No newline at end of file +} diff --git a/aai-resources/src/main/java/org/onap/aai/web/LocalHostAccessLog.java b/aai-resources/src/main/java/org/onap/aai/web/LocalHostAccessLog.java index 8faf828..8d63137 100644 --- a/aai-resources/src/main/java/org/onap/aai/web/LocalHostAccessLog.java +++ b/aai-resources/src/main/java/org/onap/aai/web/LocalHostAccessLog.java @@ -17,9 +17,13 @@ * limitations under the License. * ============LICENSE_END========================================================= */ + package org.onap.aai.web; import ch.qos.logback.access.jetty.RequestLogImpl; + +import java.util.Arrays; + import org.eclipse.jetty.server.handler.HandlerCollection; import org.eclipse.jetty.server.handler.RequestLogHandler; import org.eclipse.jetty.util.thread.QueuedThreadPool; @@ -30,19 +34,16 @@ import org.springframework.boot.web.servlet.server.AbstractServletWebServerFacto import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; -import java.util.Arrays; - @Configuration public class LocalHostAccessLog { - @Bean - public AbstractServletWebServerFactory jettyConfigBean( + @Bean + public AbstractServletWebServerFactory jettyConfigBean( @Value("${jetty.threadPool.maxThreads:200}") final String maxThreads, - @Value("${jetty.threadPool.minThreads:8}") final String minThreads - ){ + @Value("${jetty.threadPool.minThreads:8}") final String minThreads) { - JettyServletWebServerFactory jef = new JettyServletWebServerFactory(); - jef.addServerCustomizers((JettyServerCustomizer) server -> { + JettyServletWebServerFactory jef = new JettyServletWebServerFactory(); + jef.addServerCustomizers((JettyServerCustomizer) server -> { HandlerCollection handlers = new HandlerCollection(); @@ -63,6 +64,6 @@ public class LocalHostAccessLog { threadPool.setMaxThreads(Integer.valueOf(maxThreads)); threadPool.setMinThreads(Integer.valueOf(minThreads)); }); - return jef; - } + return jef; + } } diff --git a/aai-resources/src/main/java/org/onap/aai/web/MicrometerConfiguration.java b/aai-resources/src/main/java/org/onap/aai/web/MicrometerConfiguration.java index bbe94fc..e41e6d0 100644 --- a/aai-resources/src/main/java/org/onap/aai/web/MicrometerConfiguration.java +++ b/aai-resources/src/main/java/org/onap/aai/web/MicrometerConfiguration.java @@ -17,14 +17,17 @@ * limitations under the License. * ============LICENSE_END========================================================= */ + package org.onap.aai.web; + import io.micrometer.core.instrument.Tag; import io.micrometer.core.instrument.Tags; import io.micrometer.jersey2.server.JerseyTags; -import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import io.micrometer.jersey2.server.JerseyTagsProvider; + import org.glassfish.jersey.server.ContainerResponse; import org.glassfish.jersey.server.monitoring.RequestEvent; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -32,9 +35,7 @@ import org.springframework.context.annotation.Configuration; * Configuration Class to add customized tags to http metrics scraped in /actuator/prometheus endpoint */ @Configuration -@ConditionalOnProperty( - value="scrape.uri.metrics", - havingValue = "true") +@ConditionalOnProperty(value = "scrape.uri.metrics", havingValue = "true") public class MicrometerConfiguration { private static final String TAG_AAI_URI = "aai_uri"; private static final String NOT_AVAILABLE = "NOT AVAILABLE"; @@ -45,9 +46,10 @@ public class MicrometerConfiguration { @Override public Iterable httpRequestTags(RequestEvent event) { ContainerResponse response = event.getContainerResponse(); - return Tags.of(JerseyTags.method(event.getContainerRequest()), - JerseyTags.exception(event), JerseyTags.status(response), JerseyTags.outcome(response), getAaiUriTag(event)); + return Tags.of(JerseyTags.method(event.getContainerRequest()), JerseyTags.exception(event), + JerseyTags.status(response), JerseyTags.outcome(response), getAaiUriTag(event)); } + private Tag getAaiUriTag(RequestEvent event) { String aai_uri = event.getUriInfo().getRequestUri().toString(); if (aai_uri == null) { @@ -55,10 +57,11 @@ public class MicrometerConfiguration { } return Tag.of(TAG_AAI_URI, aai_uri); } + @Override public Iterable httpLongRequestTags(RequestEvent event) { return Tags.of(JerseyTags.method(event.getContainerRequest()), JerseyTags.uri(event)); } }; } -} \ No newline at end of file +} diff --git a/aai-resources/src/main/java/org/onap/aai/web/WebConfiguration.java b/aai-resources/src/main/java/org/onap/aai/web/WebConfiguration.java index a716b33..35b3569 100644 --- a/aai-resources/src/main/java/org/onap/aai/web/WebConfiguration.java +++ b/aai-resources/src/main/java/org/onap/aai/web/WebConfiguration.java @@ -17,6 +17,7 @@ * limitations under the License. * ============LICENSE_END========================================================= */ + package org.onap.aai.web; import org.springframework.context.annotation.Bean; @@ -27,20 +28,16 @@ import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; @Configuration public class WebConfiguration { - @Bean - public WebMvcConfigurer forwardToIndex() { - return new WebMvcConfigurer() { - @Override - public void addViewControllers(ViewControllerRegistry registry) { - registry.addViewController("/swagger").setViewName( - "redirect:/swagger/index.html"); - registry.addViewController("/swagger/").setViewName( - "redirect:/swagger/index.html"); - registry.addViewController("/docs").setViewName( - "redirect:/docs/html/index.html"); - registry.addViewController("/docs/").setViewName( - "redirect:/docs/html/index.html"); - } - }; - } -} \ No newline at end of file + @Bean + public WebMvcConfigurer forwardToIndex() { + return new WebMvcConfigurer() { + @Override + public void addViewControllers(ViewControllerRegistry registry) { + registry.addViewController("/swagger").setViewName("redirect:/swagger/index.html"); + registry.addViewController("/swagger/").setViewName("redirect:/swagger/index.html"); + registry.addViewController("/docs").setViewName("redirect:/docs/html/index.html"); + registry.addViewController("/docs/").setViewName("redirect:/docs/html/index.html"); + } + }; + } +} -- cgit 1.2.3-korg