aboutsummaryrefslogtreecommitdiffstats
path: root/src/main/java/org/onap
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/org/onap')
-rw-r--r--src/main/java/org/onap/aai/cacher/Application.java85
-rw-r--r--src/main/java/org/onap/aai/cacher/Profiles.java31
-rw-r--r--src/main/java/org/onap/aai/cacher/common/CacheKeyConfig.java62
-rw-r--r--src/main/java/org/onap/aai/cacher/common/MongoConfig.java104
-rw-r--r--src/main/java/org/onap/aai/cacher/common/MongoHelperSingleton.java312
-rw-r--r--src/main/java/org/onap/aai/cacher/config/JettyPasswordDecoder.java33
-rw-r--r--src/main/java/org/onap/aai/cacher/config/PasswordDecoder.java25
-rw-r--r--src/main/java/org/onap/aai/cacher/config/PropertyPasswordConfiguration.java80
-rw-r--r--src/main/java/org/onap/aai/cacher/dmaap/consumer/AAIDmaapEventProcessor.java175
-rw-r--r--src/main/java/org/onap/aai/cacher/dmaap/consumer/AAIEventConsumer.java34
-rw-r--r--src/main/java/org/onap/aai/cacher/dmaap/consumer/AAIParentEventConsumer.java237
-rw-r--r--src/main/java/org/onap/aai/cacher/dmaap/consumer/ClientConsumer.java31
-rw-r--r--src/main/java/org/onap/aai/cacher/dmaap/consumer/DmaapConsumerSingleton.java77
-rw-r--r--src/main/java/org/onap/aai/cacher/dmaap/consumer/DmaapProcessor.java32
-rw-r--r--src/main/java/org/onap/aai/cacher/dmaap/consumer/RestDmaapClientConsumer.java80
-rw-r--r--src/main/java/org/onap/aai/cacher/egestion/printer/PayloadPrinterFactory.java35
-rw-r--r--src/main/java/org/onap/aai/cacher/egestion/printer/PayloadPrinterFactoryConfiguration.java36
-rw-r--r--src/main/java/org/onap/aai/cacher/egestion/printer/PayloadPrinterService.java43
-rw-r--r--src/main/java/org/onap/aai/cacher/egestion/printer/strategy/AAIResourceGetAllPayloadPrinterStrategy.java49
-rw-r--r--src/main/java/org/onap/aai/cacher/egestion/printer/strategy/NonePayloadPrinterStrategy.java42
-rw-r--r--src/main/java/org/onap/aai/cacher/egestion/printer/strategy/PayloadPrinterStrategy.java28
-rw-r--r--src/main/java/org/onap/aai/cacher/egestion/printer/strategy/PayloadPrinterType.java46
-rw-r--r--src/main/java/org/onap/aai/cacher/injestion/parser/AAIResourcesUriTemplates.java208
-rw-r--r--src/main/java/org/onap/aai/cacher/injestion/parser/PayloadParserFactory.java35
-rw-r--r--src/main/java/org/onap/aai/cacher/injestion/parser/PayloadParserFactoryConfiguration.java36
-rw-r--r--src/main/java/org/onap/aai/cacher/injestion/parser/PayloadParserService.java71
-rw-r--r--src/main/java/org/onap/aai/cacher/injestion/parser/strategy/AAIResourceDmaapParserStrategy.java470
-rw-r--r--src/main/java/org/onap/aai/cacher/injestion/parser/strategy/AAIResourceGetAllPayloadParserStrategy.java85
-rw-r--r--src/main/java/org/onap/aai/cacher/injestion/parser/strategy/NonePayloadParserStrategy.java48
-rw-r--r--src/main/java/org/onap/aai/cacher/injestion/parser/strategy/PayloadParserStrategy.java31
-rw-r--r--src/main/java/org/onap/aai/cacher/injestion/parser/strategy/PayloadParserType.java45
-rw-r--r--src/main/java/org/onap/aai/cacher/model/CacheEntry.java206
-rw-r--r--src/main/java/org/onap/aai/cacher/model/CacheKey.java220
-rw-r--r--src/main/java/org/onap/aai/cacher/model/DBAction.java24
-rw-r--r--src/main/java/org/onap/aai/cacher/service/AuthorizationService.java109
-rw-r--r--src/main/java/org/onap/aai/cacher/service/helper/CacheHelperService.java545
-rw-r--r--src/main/java/org/onap/aai/cacher/service/helper/RestClientHelperService.java76
-rw-r--r--src/main/java/org/onap/aai/cacher/service/rest/CacheInteractionService.java88
-rw-r--r--src/main/java/org/onap/aai/cacher/service/rest/CacheKeyService.java200
-rw-r--r--src/main/java/org/onap/aai/cacher/service/rest/util/CacheKeyRequestValidation.java66
-rw-r--r--src/main/java/org/onap/aai/cacher/service/rest/util/CacheKeyRequestValidationType.java26
-rw-r--r--src/main/java/org/onap/aai/cacher/service/tasks/ScheduledTaskConfig.java74
-rw-r--r--src/main/java/org/onap/aai/cacher/service/tasks/ScheduledTasks.java148
-rw-r--r--src/main/java/org/onap/aai/cacher/util/AAIConstants.java51
-rw-r--r--src/main/java/org/onap/aai/cacher/util/RestClient.java157
-rw-r--r--src/main/java/org/onap/aai/cacher/web/JerseyConfiguration.java132
-rw-r--r--src/main/java/org/onap/aai/cacher/web/LocalHostAccessLog.java58
-rw-r--r--src/main/java/org/onap/aai/interceptors/AAIContainerFilter.java41
-rw-r--r--src/main/java/org/onap/aai/interceptors/AAIHeaderProperties.java40
-rw-r--r--src/main/java/org/onap/aai/interceptors/post/AAIResponseFilterPriority.java40
-rw-r--r--src/main/java/org/onap/aai/interceptors/post/ResponseTransactionLogging.java118
-rw-r--r--src/main/java/org/onap/aai/interceptors/pre/AAIRequestFilterPriority.java38
-rw-r--r--src/main/java/org/onap/aai/interceptors/pre/HeaderValidation.java87
-rw-r--r--src/main/java/org/onap/aai/interceptors/pre/OneWaySslAuthorization.java79
-rw-r--r--src/main/java/org/onap/aai/interceptors/pre/RequestHeaderManipulation.java60
-rw-r--r--src/main/java/org/onap/aai/interceptors/pre/RequestTransactionLogging.java131
-rw-r--r--src/main/java/org/onap/aai/interceptors/pre/SetLoggingContext.java70
57 files changed, 5590 insertions, 0 deletions
diff --git a/src/main/java/org/onap/aai/cacher/Application.java b/src/main/java/org/onap/aai/cacher/Application.java
new file mode 100644
index 0000000..9382f4b
--- /dev/null
+++ b/src/main/java/org/onap/aai/cacher/Application.java
@@ -0,0 +1,85 @@
+/**
+ * ============LICENSE_START=======================================================
+ * org.onap.aai
+ * ================================================================================
+ * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.aai.cacher;
+
+import org.onap.aai.cacher.config.PropertyPasswordConfiguration;
+import org.onap.aai.logging.LoggingContext;
+import org.onap.aai.logging.LoggingContext.StatusCode;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
+import org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration;
+import org.springframework.boot.builder.SpringApplicationBuilder;
+import org.springframework.boot.web.support.SpringBootServletInitializer;
+import org.springframework.context.annotation.ComponentScan;
+import org.springframework.context.annotation.PropertySource;
+import org.springframework.scheduling.annotation.EnableScheduling;
+
+import java.util.UUID;
+
+@SpringBootApplication
+@EnableScheduling
+@EnableAutoConfiguration(exclude = { DataSourceAutoConfiguration.class, HibernateJpaAutoConfiguration.class })
+@ComponentScan(basePackages = { "org.onap.aai.cacher", "com" })
+@PropertySource("classpath:application.properties")
+public class Application extends SpringBootServletInitializer {
+ private static final String APP_NAME = "cacher";
+
+ @Override
+ protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
+ return application.sources(Application.class);
+ }
+
+ public static void main(String[] args) throws Exception {
+ setDefaultProps();
+
+ LoggingContext.save();
+ LoggingContext.component("init");
+ LoggingContext.partnerName("NA");
+ LoggingContext.targetEntity(APP_NAME);
+ LoggingContext.requestId(UUID.randomUUID().toString());
+ LoggingContext.serviceName(APP_NAME);
+ LoggingContext.targetServiceName("contextInitialized");
+ LoggingContext.statusCode(StatusCode.COMPLETE);
+
+ SpringApplication app = new SpringApplication(Application.class);
+ app.setLogStartupInfo(false);
+ app.setRegisterShutdownHook(true);
+ app.addInitializers(new PropertyPasswordConfiguration());
+ app.run(args);
+
+ }
+
+ public static void setDefaultProps() {
+
+ if (System.getProperty("file.separator") == null) {
+ System.setProperty("file.separator", "/");
+ }
+
+ if (System.getProperty("AJSC_HOME") == null) {
+ System.setProperty("AJSC_HOME", ".");
+ }
+
+ if (System.getProperty("BUNDLECONFIG_DIR") == null) {
+ System.setProperty("BUNDLECONFIG_DIR", "src/main/resources");
+ }
+ }
+} \ No newline at end of file
diff --git a/src/main/java/org/onap/aai/cacher/Profiles.java b/src/main/java/org/onap/aai/cacher/Profiles.java
new file mode 100644
index 0000000..05c3559
--- /dev/null
+++ b/src/main/java/org/onap/aai/cacher/Profiles.java
@@ -0,0 +1,31 @@
+/**
+ * ============LICENSE_START=======================================================
+ * org.onap.aai
+ * ================================================================================
+ * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.aai.cacher;
+
+public final class Profiles {
+
+ 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 TWO_WAY_SSL = "two-way-ssl";
+
+ private Profiles(){}
+}
diff --git a/src/main/java/org/onap/aai/cacher/common/CacheKeyConfig.java b/src/main/java/org/onap/aai/cacher/common/CacheKeyConfig.java
new file mode 100644
index 0000000..e02ea81
--- /dev/null
+++ b/src/main/java/org/onap/aai/cacher/common/CacheKeyConfig.java
@@ -0,0 +1,62 @@
+/**
+ * ============LICENSE_START=======================================================
+ * org.onap.aai
+ * ================================================================================
+ * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.aai.cacher.common;
+
+import com.google.gson.JsonArray;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonParser;
+import org.onap.aai.cacher.model.CacheKey;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class CacheKeyConfig {
+ private JsonArray cachekeys = null;
+
+ private static final String CACHEKEYS = "cachekeys";
+
+ public CacheKeyConfig(String json) {
+ init(json);
+ }
+
+ private void init(String json) {
+ JsonParser parser = new JsonParser();
+ JsonObject queriesObject = parser.parse(json).getAsJsonObject();
+ if (queriesObject.has(CACHEKEYS)) {
+ cachekeys = queriesObject.getAsJsonArray(CACHEKEYS);
+ }
+ }
+
+ public List<CacheKey> populateCacheKeyList() {
+ List<CacheKey> ckList = new ArrayList<>();
+ for (JsonElement cacheKeyElement : cachekeys) {
+ if (cacheKeyElement.isJsonObject()) {
+ JsonObject cacheJsonObj = cacheKeyElement.getAsJsonObject();
+ if (cacheJsonObj != null) {
+ CacheKey cacheKey = CacheKey.fromJson(cacheJsonObj);
+ ckList.add(cacheKey);
+ }
+ }
+ }
+ return ckList;
+ }
+
+}
diff --git a/src/main/java/org/onap/aai/cacher/common/MongoConfig.java b/src/main/java/org/onap/aai/cacher/common/MongoConfig.java
new file mode 100644
index 0000000..d08930b
--- /dev/null
+++ b/src/main/java/org/onap/aai/cacher/common/MongoConfig.java
@@ -0,0 +1,104 @@
+/**
+ * ============LICENSE_START=======================================================
+ * org.onap.aai
+ * ================================================================================
+ * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.aai.cacher.common;
+
+import com.att.eelf.configuration.EELFLogger;
+import com.att.eelf.configuration.EELFManager;
+import com.mongodb.DB;
+import com.mongodb.MongoClient;
+import com.mongodb.client.MongoDatabase;
+import de.flapdoodle.embed.mongo.MongodExecutable;
+import de.flapdoodle.embed.mongo.MongodProcess;
+import de.flapdoodle.embed.mongo.MongodStarter;
+import de.flapdoodle.embed.mongo.config.IMongodConfig;
+import de.flapdoodle.embed.mongo.config.MongodConfigBuilder;
+import de.flapdoodle.embed.mongo.config.Net;
+import de.flapdoodle.embed.mongo.distribution.Version;
+import de.flapdoodle.embed.process.runtime.Network;
+import org.onap.aai.exceptions.AAIException;
+import org.onap.aai.logging.ErrorLogHelper;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+import javax.annotation.PostConstruct;
+import java.io.IOException;
+
+@Configuration
+public class MongoConfig {
+
+ private final static EELFLogger EELF_LOGGER = EELFManager.getInstance().getLogger(MongoConfig.class);
+
+ @Value("${mongodb.host}")
+ private String MONGO_DB_HOST;
+ @Value("${mongodb.dbName}")
+ private String MONGO_DB_NAME;
+ @Value("${mongodb.port}")
+ private int MONGO_DB_PORT;
+
+ @Bean
+ public MongoClient mongoClient() {
+ try {
+ // To connect to mongodb server
+ MongoClient mongoC = new MongoClient(MONGO_DB_HOST, MONGO_DB_PORT);
+
+ // Now connect to your databases
+ EELF_LOGGER.info("Connect to database successfully");
+
+ return mongoC;
+
+ } catch (Exception e) {
+ AAIException aaiException = new AAIException("AAI_4000");
+ ErrorLogHelper.logException(aaiException);
+ }
+
+ return null;
+ }
+
+ @Bean
+ public DB db(MongoClient mongoClient) {
+ return mongoClient.getDB(MONGO_DB_NAME);
+ }
+
+ @Bean
+ public MongoDatabase mongoDatabase(MongoClient mongoClient) {
+ return mongoClient.getDatabase(MONGO_DB_NAME);
+ }
+
+ @Bean
+ @PostConstruct
+ public MongodProcess mongoEmbedded() throws IOException, InterruptedException {
+
+ MongodStarter starter = MongodStarter.getDefaultInstance();
+
+ String bindIp = MONGO_DB_HOST;
+ int port = MONGO_DB_PORT;
+ IMongodConfig mongodConfig = new MongodConfigBuilder().version(Version.Main.PRODUCTION)
+ .net(new Net(port, Network.localhostIsIPv6())).configServer(false).build();
+
+ MongodExecutable mongodExecutable = starter.prepare(mongodConfig);
+ // Thread.sleep(20000L);
+ MongodProcess mongod = mongodExecutable.start();
+ if (mongod.isProcessRunning()) {
+ System.out.println("RUNNING");
+ }
+ return mongod;
+ }
+} \ No newline at end of file
diff --git a/src/main/java/org/onap/aai/cacher/common/MongoHelperSingleton.java b/src/main/java/org/onap/aai/cacher/common/MongoHelperSingleton.java
new file mode 100644
index 0000000..63638f1
--- /dev/null
+++ b/src/main/java/org/onap/aai/cacher/common/MongoHelperSingleton.java
@@ -0,0 +1,312 @@
+/**
+ * ============LICENSE_START=======================================================
+ * org.onap.aai
+ * ================================================================================
+ * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.aai.cacher.common;
+
+import com.att.eelf.configuration.EELFLogger;
+import com.att.eelf.configuration.EELFManager;
+import com.google.common.collect.Lists;
+import com.google.gson.JsonObject;
+import com.mongodb.*;
+import com.mongodb.client.AggregateIterable;
+import com.mongodb.client.MongoCollection;
+import com.mongodb.client.MongoDatabase;
+import com.mongodb.client.model.DBCollectionUpdateOptions;
+import com.mongodb.client.model.FindOneAndUpdateOptions;
+import com.mongodb.client.model.UpdateOptions;
+import com.mongodb.client.result.DeleteResult;
+import com.mongodb.client.result.UpdateResult;
+import org.apache.commons.lang3.StringUtils;
+import org.bson.Document;
+import org.onap.aai.cacher.model.CacheEntry;
+import org.onap.aai.exceptions.AAIException;
+import org.onap.aai.logging.ErrorLogHelper;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.config.ConfigurableBeanFactory;
+import org.springframework.context.annotation.Scope;
+import org.springframework.stereotype.Component;
+
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.Response.Status;
+import java.util.*;
+import java.util.stream.Collectors;
+
+/**
+ * Creates and returns a mongo instance
+ */
+
+@Component
+@Scope(scopeName = ConfigurableBeanFactory.SCOPE_SINGLETON)
+public class MongoHelperSingleton {
+
+ private final static EELFLogger EELF_LOGGER = EELFManager.getInstance().getLogger(MongoHelperSingleton.class);
+
+ private DB db;
+
+ private MongoDatabase mongoDatabase;
+
+ @Autowired
+ public MongoHelperSingleton(DB db, MongoDatabase mongoDatabase) {
+ this.mongoDatabase = mongoDatabase;
+ this.db = db;
+ }
+
+ public DB getDb() {
+ return db;
+ }
+
+ public void createCollection(String name) {
+ try {
+ db.getCollection(name);
+ EELF_LOGGER.info("Collection " + name + " created successfully");
+ } catch (Exception e) {
+ AAIException aaiException = new AAIException("AAI_4000");
+ ErrorLogHelper.logException(aaiException);
+ }
+ }
+
+ public boolean addToMongo(String collectionName, Object document) {
+ try {
+ DBCollection collection = db.getCollection(collectionName);
+ WriteResult result;
+ if (document instanceof List) {
+ result = collection.insert((List<BasicDBObject>) document);
+ return result.wasAcknowledged();
+ } else if (document instanceof BasicDBObject) {
+ result = collection.insert((BasicDBObject) document);
+ return result.wasAcknowledged();
+ } else {
+ EELF_LOGGER.error("The cachekey object to add was of unknown type");
+ return false;
+ }
+ } catch (MongoException ex) {
+ AAIException aaiException = new AAIException("AAI_5105");
+ ErrorLogHelper.logException(aaiException);
+ return false;
+ } catch (Exception e) {
+ AAIException aaiException = new AAIException("AAI_4000");
+ ErrorLogHelper.logException(aaiException);
+ return false;
+ }
+ }
+
+ public boolean updateInMongo(String collectionName, BasicDBObject searchQuery, Object document,
+ DBCollectionUpdateOptions updateOptions) {
+ try {
+ DBCollection collection = db.getCollection(collectionName);
+ WriteResult result;
+ result = collection.update(searchQuery, (BasicDBObject) document, updateOptions);
+ return result.wasAcknowledged();
+ } catch (MongoException ex) {
+ AAIException aaiException = new AAIException("AAI_5105");
+ ErrorLogHelper.logException(aaiException);
+ return false;
+ } catch (Exception e) {
+ AAIException aaiException = new AAIException("AAI_4000");
+ ErrorLogHelper.logException(aaiException);
+ return false;
+ }
+ }
+
+ public String deleteFromMongo(String collectionName, Map<String, String> whereClause) {
+ DBCollection collection = db.getCollection(collectionName);
+ DBObject searchQuery = new BasicDBObject();
+ for (Map.Entry<String, String> entry : whereClause.entrySet()) {
+ String key = entry.getKey();
+ Object value = entry.getValue();
+ searchQuery.put(key, value);
+ }
+ try {
+ WriteResult result = collection.remove(searchQuery);
+ if (result.getN() > 0) {
+ return "DELETED";
+ } else {
+ return "NOT_FOUND";
+ }
+ } catch (MongoException ex) {
+ AAIException aaiException = new AAIException("AAI_5105");
+ ErrorLogHelper.logException(aaiException);
+ return "EXCEPTION_THROWN";
+ }
+ }
+
+ public void dropCollection(String collectionName) {
+ db.getCollection(collectionName).drop();
+ }
+
+ public Response buildResponse(Status status, String result) {
+ return Response.status(status).type(MediaType.APPLICATION_JSON).entity(result).build();
+ }
+
+ public Response buildExceptionResponse(AAIException aaiException) {
+ ErrorLogHelper.logException(aaiException);
+ return Response.status(aaiException.getErrorObject().getHTTPResponseCode())
+ .entity(ErrorLogHelper.getRESTAPIErrorResponseWithLogging(
+ Lists.newArrayList(MediaType.APPLICATION_JSON_TYPE), aaiException, new ArrayList<>()))
+ .build();
+ }
+
+ public boolean insertReplace(CacheEntry cacheEntry) {
+ MongoCollection<Document> collection = mongoDatabase.getCollection(cacheEntry.getCollection());
+
+ Document findQuery = Document.parse(cacheEntry.getFindQuery().toString());
+ Document payload = Document.parse(cacheEntry.getPayload().toString());
+
+ if (!cacheEntry.isNested()) {
+ UpdateResult updateResult = collection.replaceOne(findQuery, payload, new UpdateOptions().upsert(true));
+
+ return updateResult.wasAcknowledged();
+ } else {
+ CacheEntry localCacheEntry = CacheEntry.CacheEntryBuilder.createCacheEntry().deepCopy(cacheEntry).build();
+ Document nestedFind = Document.parse(localCacheEntry.getNestedFind().toString());
+
+ // if exists remove
+ if (collection.count(nestedFind) > 0L) {
+ mongoPull(localCacheEntry, collection, nestedFind);
+ }
+
+ ArrayList<Document> filters = this.getFiltersAndUpdateNestedField(localCacheEntry);
+ Document doc = new Document();
+ doc.put(localCacheEntry.getNestedField(), payload);
+ Document push = new Document();
+ push.put("$push", doc);
+
+ collection.findOneAndUpdate(findQuery, push,
+ new FindOneAndUpdateOptions().arrayFilters(filters).upsert(true));
+
+ return collection.count(nestedFind) > 0L;
+ }
+ }
+
+ public boolean delete(CacheEntry cacheEntry) {
+
+ MongoCollection<Document> collection = mongoDatabase.getCollection(cacheEntry.getCollection());
+
+ Document findQuery = Document.parse(cacheEntry.getFindQuery().toString());
+
+ if (!cacheEntry.isNested()) {
+ if (collection.count(findQuery) == 0L) {
+ return true;
+ }
+ DeleteResult deleteResult = collection.deleteOne(findQuery);
+ return deleteResult.wasAcknowledged();
+
+ } else {
+ Document nestedFind = Document.parse(cacheEntry.getNestedFind().toString());
+ if (collection.count(nestedFind) == 0L) {
+ return true;
+ }
+
+ mongoPull(cacheEntry, collection, nestedFind);
+ return collection.count(nestedFind) == 0L;
+
+ }
+ }
+
+ public Optional<Document> getObject(CacheEntry cacheEntry) {
+ MongoCollection<Document> collection = mongoDatabase.getCollection(cacheEntry.getCollection());
+ Document resultingObject;
+
+ if (!cacheEntry.isNested()) {
+ resultingObject = collection.find(Document.parse(cacheEntry.getFindQuery().toString())).first();
+ } else {
+ List<Document> aggregate = getAggregateFromFind(cacheEntry.getNestedFind());
+ AggregateIterable<Document> aggregateResult = collection.aggregate(aggregate);
+ resultingObject = aggregateResult.first();
+ if (resultingObject != null) {
+ resultingObject = (Document) (resultingObject.get("output"));
+ }
+ }
+
+ return Optional.ofNullable(resultingObject);
+ }
+
+ private List<Document> getAggregateFromFind(JsonObject nestedFind) {
+ Document nestedFindDocument = Document.parse(nestedFind.toString());
+ List<Document> aggregate = new ArrayList<>();
+ List<String> keys = new ArrayList<>(nestedFindDocument.keySet());
+ for (int i = 0; i < keys.size(); i++) {
+ if (!keys.get(i).contains(".")) {
+ aggregate.add(new Document("$match", new Document(keys.get(i), nestedFindDocument.get(keys.get(i)))));
+ } else {
+ aggregate.add(new Document("$unwind", "$" + keys.get(i).substring(0, keys.get(i).lastIndexOf('.'))));
+ aggregate.add(new Document("$match", new Document(keys.get(i), nestedFindDocument.get(keys.get(i)))));
+ }
+ if (i == keys.size() - 1) {
+ aggregate.add(new Document("$project", new Document("_id", 0).append("output",
+ "$" + keys.get(i).substring(0, keys.get(i).lastIndexOf('.')))));
+ }
+ }
+ return aggregate;
+ }
+
+ protected void mongoPull(CacheEntry cacheEntry, MongoCollection<Document> collection, Document nestedFind) {
+ CacheEntry localCacheEntry = CacheEntry.CacheEntryBuilder.createCacheEntry().deepCopy(cacheEntry).build();
+ ArrayList<Document> filters = this.getFiltersAndUpdateNestedField(localCacheEntry);
+
+ Document pullObj = new Document();
+ pullObj.put(localCacheEntry.getNestedField(),
+ Document.parse(localCacheEntry.getNestedFieldIdentifierObj().toString()));
+ Document pull = new Document();
+ pull.put("$pull", pullObj);
+ collection.findOneAndUpdate(nestedFind, pull, new FindOneAndUpdateOptions().arrayFilters(filters).upsert(true));
+ // TODO remove wrapping if there are no entries in array.
+
+ }
+
+ private ArrayList<Document> getFiltersAndUpdateNestedField(CacheEntry cacheEntry) {
+
+ if (StringUtils.countMatches(cacheEntry.getNestedField(), ".$.") < 2) {
+ return new ArrayList<>();
+ }
+
+ ArrayList<Document> filters = new ArrayList<>();
+ List<String> keys = cacheEntry.getNestedFind().entrySet().stream().map(Map.Entry::getKey)
+ .filter(s -> !s.equals("_id")).sorted((s, t1) -> {
+ if (StringUtils.countMatches(s, ".") > StringUtils.countMatches(t1, ".")) {
+ return 1;
+ }
+ return s.compareTo(t1);
+ }).collect(Collectors.toList());
+ String filterKey;
+ String filterValue;
+ String key;
+ char filterIndex = 'a';
+ StringBuilder newNestedField = new StringBuilder();
+ List<String> fieldSplit = Arrays.asList(cacheEntry.getNestedField().split("\\.\\$"));
+ for (int i = 0; i < fieldSplit.size(); i++) {
+ final String subSplit = StringUtils.join(fieldSplit.subList(0, i + 1), "");
+ key = keys.stream().filter(s -> s.startsWith(subSplit)).findFirst().get();
+ filterIndex += i;
+ filterKey = filterIndex + "." + key.substring(key.lastIndexOf(".") + 1);
+ filterValue = cacheEntry.getNestedFind().get(key).getAsString();
+ newNestedField.append(fieldSplit.get(i));
+ if (i + 1 != fieldSplit.size()) {
+ newNestedField.append(".$[").append(filterIndex).append("]");
+ filters.add(new Document().append(filterKey, filterValue));
+ }
+
+ }
+ cacheEntry.setNestedField(newNestedField.toString());
+
+ return filters;
+ }
+
+}
diff --git a/src/main/java/org/onap/aai/cacher/config/JettyPasswordDecoder.java b/src/main/java/org/onap/aai/cacher/config/JettyPasswordDecoder.java
new file mode 100644
index 0000000..ef18883
--- /dev/null
+++ b/src/main/java/org/onap/aai/cacher/config/JettyPasswordDecoder.java
@@ -0,0 +1,33 @@
+/**
+ * ============LICENSE_START=======================================================
+ * org.onap.aai
+ * ================================================================================
+ * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.aai.cacher.config;
+
+import org.eclipse.jetty.util.security.Password;
+
+public class JettyPasswordDecoder implements PasswordDecoder {
+
+ @Override
+ public String decode(String input) {
+ if (input.startsWith("OBF:")) {
+ return Password.deobfuscate(input);
+ }
+ return Password.deobfuscate("OBF:" + input);
+ }
+}
diff --git a/src/main/java/org/onap/aai/cacher/config/PasswordDecoder.java b/src/main/java/org/onap/aai/cacher/config/PasswordDecoder.java
new file mode 100644
index 0000000..053e3e8
--- /dev/null
+++ b/src/main/java/org/onap/aai/cacher/config/PasswordDecoder.java
@@ -0,0 +1,25 @@
+/**
+ * ============LICENSE_START=======================================================
+ * org.onap.aai
+ * ================================================================================
+ * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.aai.cacher.config;
+
+public interface PasswordDecoder {
+
+ String decode(String input);
+}
diff --git a/src/main/java/org/onap/aai/cacher/config/PropertyPasswordConfiguration.java b/src/main/java/org/onap/aai/cacher/config/PropertyPasswordConfiguration.java
new file mode 100644
index 0000000..27a43e2
--- /dev/null
+++ b/src/main/java/org/onap/aai/cacher/config/PropertyPasswordConfiguration.java
@@ -0,0 +1,80 @@
+/**
+ * ============LICENSE_START=======================================================
+ * org.onap.aai
+ * ================================================================================
+ * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.aai.cacher.config;
+
+import org.springframework.context.ApplicationContextInitializer;
+import org.springframework.context.ConfigurableApplicationContext;
+import org.springframework.core.env.ConfigurableEnvironment;
+import org.springframework.core.env.EnumerablePropertySource;
+import org.springframework.core.env.MapPropertySource;
+import org.springframework.core.env.PropertySource;
+
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+public class PropertyPasswordConfiguration implements ApplicationContextInitializer<ConfigurableApplicationContext> {
+
+ private static final Pattern decodePasswordPattern = Pattern.compile("password\\((.*?)\\)");
+
+ private PasswordDecoder passwordDecoder = new JettyPasswordDecoder();
+
+ @Override
+ public void initialize(ConfigurableApplicationContext applicationContext) {
+ ConfigurableEnvironment environment = applicationContext.getEnvironment();
+ for (PropertySource<?> propertySource : environment.getPropertySources()) {
+ Map<String, Object> propertyOverrides = new LinkedHashMap<>();
+ decodePasswords(propertySource, propertyOverrides);
+ if (!propertyOverrides.isEmpty()) {
+ PropertySource<?> decodedProperties = new MapPropertySource("decoded " + propertySource.getName(),
+ propertyOverrides);
+ environment.getPropertySources().addBefore(propertySource.getName(), decodedProperties);
+ }
+ }
+ }
+
+ private void decodePasswords(PropertySource<?> source, Map<String, Object> propertyOverrides) {
+ if (source instanceof EnumerablePropertySource) {
+ EnumerablePropertySource<?> enumerablePropertySource = (EnumerablePropertySource<?>) source;
+ for (String key : enumerablePropertySource.getPropertyNames()) {
+ Object rawValue = source.getProperty(key);
+ if (rawValue instanceof String) {
+ String decodedValue = decodePasswordsInString((String) rawValue);
+ propertyOverrides.put(key, decodedValue);
+ }
+ }
+ }
+ }
+
+ private String decodePasswordsInString(String input) {
+ if (input == null)
+ return null;
+ StringBuffer output = new StringBuffer();
+ Matcher matcher = decodePasswordPattern.matcher(input);
+ while (matcher.find()) {
+ String replacement = passwordDecoder.decode(matcher.group(1));
+ matcher.appendReplacement(output, replacement);
+ }
+ matcher.appendTail(output);
+ return output.toString();
+ }
+
+}
diff --git a/src/main/java/org/onap/aai/cacher/dmaap/consumer/AAIDmaapEventProcessor.java b/src/main/java/org/onap/aai/cacher/dmaap/consumer/AAIDmaapEventProcessor.java
new file mode 100644
index 0000000..5c684a2
--- /dev/null
+++ b/src/main/java/org/onap/aai/cacher/dmaap/consumer/AAIDmaapEventProcessor.java
@@ -0,0 +1,175 @@
+/**
+ * ============LICENSE_START=======================================================
+ * org.onap.aai
+ * ================================================================================
+ * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.aai.cacher.dmaap.consumer;
+
+import com.att.eelf.configuration.EELFLogger;
+import com.att.eelf.configuration.EELFManager;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonParser;
+import com.mongodb.MongoCommandException;
+import org.bson.Document;
+import org.json.JSONException;
+import org.json.JSONObject;
+import org.onap.aai.cacher.common.MongoHelperSingleton;
+import org.onap.aai.cacher.injestion.parser.PayloadParserService;
+import org.onap.aai.cacher.injestion.parser.strategy.PayloadParserType;
+import org.onap.aai.cacher.model.CacheEntry;
+import org.onap.aai.exceptions.AAIException;
+import org.onap.aai.logging.ErrorLogHelper;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+import java.util.Optional;
+
+@Service
+public class AAIDmaapEventProcessor implements DmaapProcessor {
+
+ private static EELFLogger LOGGER = EELFManager.getInstance().getLogger(AAIEventConsumer.class);
+
+ private final JsonParser parser = new JsonParser();
+
+ private JSONObject event;
+ private JSONObject eventHeader;
+ private JSONObject eventBody;
+
+ private MongoHelperSingleton mongoHelper;
+ private PayloadParserService payloadParserService;
+
+ @Autowired
+ public AAIDmaapEventProcessor(MongoHelperSingleton mongoHelper, PayloadParserService payloadParserService) {
+ this.mongoHelper = mongoHelper;
+ this.payloadParserService = payloadParserService;
+ }
+
+ public AAIDmaapEventProcessor() {
+ }
+
+ /**
+ *
+ * @param eventMessage
+ * @return
+ */
+ public void process(String eventMessage) throws Exception {
+ this.event = null;
+ this.eventHeader = null;
+ this.eventBody = null;
+
+ try {
+ LOGGER.debug("Processing event: " + eventMessage);
+ this.event = new JSONObject(eventMessage);
+ } catch (JSONException je) {
+ LOGGER.error("ERROR: Event is not valid JSON [" + eventMessage + "].");
+ ErrorLogHelper.logException(new AAIException("AAI_4000", je));
+ throw je;
+ }
+
+ try {
+ LOGGER.debug("Validating event header.");
+ this.validateEventHeader(this.event);
+ } catch (JSONException je) {
+ LOGGER.error("ERROR: Event header is not valid [" + eventMessage + "].");
+ ErrorLogHelper.logException(new AAIException("AAI_4000", je));
+ throw je;
+ }
+
+ try {
+ LOGGER.debug("Processing entity.");
+ eventBody = this.event.getJSONObject("entity");
+ } catch (JSONException je) {
+ LOGGER.error("ERROR: Event body is not valid JSON [" + eventMessage + "].");
+ ErrorLogHelper.logException(new AAIException("AAI_4000", je));
+ throw je;
+ }
+
+ List<CacheEntry> dmaapCacheEntries = payloadParserService.doParse("aai-dmaap",
+ parser.parse(eventMessage).getAsJsonObject(), PayloadParserType.AAI_RESOURCE_DMAAP);
+
+ // Get existing object if is update
+ Optional<Document> existingObj = Optional.empty();
+ if (this.eventHeader != null && "UPDATE".equals(eventHeader.getString("action"))) {
+ existingObj = mongoHelper.getObject(dmaapCacheEntries.get(0));
+ }
+
+ // Add existing object to payload to be parsed by AAI_RESOURCE_DMAAP parser
+ if (existingObj.isPresent()) {
+ JsonObject eventMessageObj = parser.parse(eventMessage).getAsJsonObject();
+ eventMessageObj.add("existing-obj", parser.parse(existingObj.get().toJson()).getAsJsonObject());
+ eventMessage = eventMessageObj.toString();
+ dmaapCacheEntries = payloadParserService.doParse("aai-dmaap", parser.parse(eventMessage).getAsJsonObject(),
+ PayloadParserType.AAI_RESOURCE_DMAAP);
+ }
+
+ for (CacheEntry cacheEntry : dmaapCacheEntries) {
+ try {
+ switch (cacheEntry.getDbAction()) {
+ case DELETE:
+ mongoHelper.delete(cacheEntry);
+ break;
+ case UPDATE:
+ mongoHelper.insertReplace(cacheEntry);
+ break;
+ case INSERT_REPLACE:
+ mongoHelper.insertReplace(cacheEntry);
+ break;
+ }
+ } catch (MongoCommandException exception) {
+ LOGGER.warn("Attempted to update nested that does not exist in cache.", exception);
+ }
+ }
+
+ LOGGER.debug("Event processed successfully.");
+
+ }
+
+ /**
+ * Validates that the event header has the id and source name for processing.
+ * (needed for status response msg)
+ *
+ * @param event
+ * @throws JSONException
+ */
+ private void validateEventHeader(JSONObject event) throws JSONException {
+ eventHeader = event.getJSONObject("event-header");
+ if (this.eventHeader.getString("id") == null || this.eventHeader.getString("id").isEmpty()) {
+ throw new JSONException("Event header id missing.");
+ } else if (this.eventHeader.getString("source-name") == null
+ || this.eventHeader.getString("source-name").isEmpty()) {
+ throw new JSONException("Event header source-name missing.");
+ }
+ }
+
+ /**
+ *
+ * @return
+ */
+ public JSONObject getEventHeader() {
+ return eventHeader;
+ }
+
+ /**
+ *
+ * @return
+ */
+ public JSONObject getEventBody() {
+ return eventBody;
+ }
+
+}
diff --git a/src/main/java/org/onap/aai/cacher/dmaap/consumer/AAIEventConsumer.java b/src/main/java/org/onap/aai/cacher/dmaap/consumer/AAIEventConsumer.java
new file mode 100644
index 0000000..cb1c77a
--- /dev/null
+++ b/src/main/java/org/onap/aai/cacher/dmaap/consumer/AAIEventConsumer.java
@@ -0,0 +1,34 @@
+/**
+ * ============LICENSE_START=======================================================
+ * org.onap.aai
+ * ================================================================================
+ * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.aai.cacher.dmaap.consumer;
+
+import com.att.eelf.configuration.EELFLogger;
+import com.att.eelf.configuration.EELFManager;
+
+public class AAIEventConsumer extends AAIParentEventConsumer {
+
+ private static EELFLogger LOGGER = EELFManager.getInstance().getLogger(AAIEventConsumer.class);
+
+ public AAIEventConsumer(String consumerPropFile, boolean injestConsumer) throws Exception {
+ super(consumerPropFile, injestConsumer);
+ LOGGER.debug("Initialization completed.");
+ }
+
+}
diff --git a/src/main/java/org/onap/aai/cacher/dmaap/consumer/AAIParentEventConsumer.java b/src/main/java/org/onap/aai/cacher/dmaap/consumer/AAIParentEventConsumer.java
new file mode 100644
index 0000000..8d64116
--- /dev/null
+++ b/src/main/java/org/onap/aai/cacher/dmaap/consumer/AAIParentEventConsumer.java
@@ -0,0 +1,237 @@
+/**
+ * ============LICENSE_START=======================================================
+ * org.onap.aai
+ * ================================================================================
+ * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.aai.cacher.dmaap.consumer;
+
+import com.att.eelf.configuration.EELFLogger;
+import com.att.eelf.configuration.EELFManager;
+import com.att.nsa.mr.client.MRClientFactory;
+import com.att.nsa.mr.client.MRConsumer;
+import org.apache.commons.configuration.ConfigurationException;
+import org.eclipse.jetty.util.security.Password;
+import org.onap.aai.cacher.util.AAIConstants;
+import org.onap.aai.exceptions.AAIException;
+import org.onap.aai.logging.ErrorLogHelper;
+import org.onap.aai.util.AAIConfig;
+
+import java.io.*;
+import java.util.Properties;
+import java.util.UUID;
+import java.util.logging.Level;
+
+public class AAIParentEventConsumer {
+
+ protected String fromAppId = "AAIEventConsumerScheduledTask";
+ protected String COMPONENT = "DMAAP-AAI-EVENT";
+ private static EELFLogger LOGGER = EELFManager.getInstance().getLogger(AAIParentEventConsumer.class);
+
+ protected String preferredRouterFilePath;
+ protected String aaiDmaapEventConsumerPropertiesFile;
+
+ protected String dmaapPropertyHome = "";
+ protected String dmaapConusmerId = "";
+ protected String transId = "";
+
+ protected Properties aaiDmaapEventConsumerProperties = new Properties();
+
+ protected MRConsumer aaiDmaapEventConsumer;
+
+ protected DmaapConsumerSingleton dmaapConsumerSingleton;
+
+ /*
+ * Change the client consumer implementation from RestDmaapClientConsumer to
+ * DmaapClientConsumer when the bug that is making dme2 connections in dev,
+ * testINT, testEXT is fixed
+ */
+ protected ClientConsumer clientConsumer;
+
+ public AAIParentEventConsumer(String consumerPropFile, boolean injestConsumer) throws Exception {
+ this.transId = UUID.randomUUID().toString();
+ LOGGER.debug("Initalize the AAIParentEventConsumer");
+
+ DmaapConsumerSingleton dmaapConsumerSingleton = DmaapConsumerSingleton.getInstance();
+
+ this.dmaapPropertyHome = AAIConstants.AAI_HOME_ETC_APP_PROPERTIES;
+
+ if (dmaapConsumerSingleton.getDmaapConsumerId() == null) {
+ dmaapConsumerSingleton.setDmaapConsumerId(UUID.randomUUID().toString());
+ }
+ this.dmaapConusmerId = dmaapConsumerSingleton.getDmaapConsumerId();
+
+ processPropertyFiles(consumerPropFile);
+ if (!injestConsumer) {
+ this.aaiDmaapEventConsumer = MRClientFactory.createConsumer(this.aaiDmaapEventConsumerProperties.toString());
+ setConsumer(aaiDmaapEventConsumer);
+ }
+ LOGGER.debug("Initialization completed.");
+
+ }
+
+ public void setConsumer(MRConsumer aaiDmaapEventConsumer) {
+ this.aaiDmaapEventConsumer = aaiDmaapEventConsumer;
+ this.clientConsumer = new RestDmaapClientConsumer(this.aaiDmaapEventConsumer,
+ this.aaiDmaapEventConsumerProperties);
+ }
+
+ public Properties getDmaapEventConsumerProperties() {
+ return aaiDmaapEventConsumerProperties;
+ }
+
+ private void processPropertyFiles(String consumerPropFile) throws IOException, ConfigurationException {
+
+ this.preferredRouterFilePath = this.dmaapPropertyHome + "preferredRoute.txt";
+ this.aaiDmaapEventConsumerPropertiesFile = this.dmaapPropertyHome + consumerPropFile;
+
+ LOGGER.debug("Preferred router file path: " + this.preferredRouterFilePath);
+ LOGGER.debug("AAI Dmaap Event Consumer Properties path: " + this.aaiDmaapEventConsumerPropertiesFile);
+
+ File fo = new File(this.preferredRouterFilePath);
+ if (!fo.exists()) {
+ FileNotFoundException ex = new FileNotFoundException(
+ "Dmaap Route file " + preferredRouterFilePath + " does not exist");
+ ErrorLogHelper.logException(new AAIException("AAI_4000", ex));
+ throw ex;
+ }
+
+ fo = new File(this.aaiDmaapEventConsumerPropertiesFile);
+ if (!fo.exists()) {
+ FileNotFoundException ex = new FileNotFoundException(
+ "Dmaap consumer property file " + aaiDmaapEventConsumerPropertiesFile + " does not exist.");
+ ErrorLogHelper.logException(new AAIException("AAI_4000", ex));
+ throw ex;
+ }
+
+ modifyProperties();
+
+ }
+
+ private void modifyProperties() throws ConfigurationException, IOException {
+
+ try (Reader reader = new FileReader(new File(this.aaiDmaapEventConsumerPropertiesFile))) {
+ this.aaiDmaapEventConsumerProperties.load(reader);
+ }
+
+ aaiDmaapEventConsumerProperties.setProperty("id", this.dmaapConusmerId);
+ LOGGER.debug("Updated " + this.aaiDmaapEventConsumerPropertiesFile + " id " + this.dmaapConusmerId);
+
+ aaiDmaapEventConsumerProperties.setProperty("DME2preferredRouterFilePath", this.preferredRouterFilePath);
+ if (aaiDmaapEventConsumerProperties.getProperty("password") != null
+ && aaiDmaapEventConsumerProperties.getProperty("password").startsWith("OBF:")) {
+ aaiDmaapEventConsumerProperties.setProperty("password",
+ Password.deobfuscate(aaiDmaapEventConsumerProperties.getProperty("password")));
+ }
+ LOGGER.debug("Updated " + this.aaiDmaapEventConsumerPropertiesFile + " DME2preferredRouterFilePath property to "
+ + this.preferredRouterFilePath);
+
+ if (getIsInitialCheck()) {
+ aaiDmaapEventConsumerProperties.setProperty("limit", "1");
+ }
+ LOGGER.debug("Using limit " + aaiDmaapEventConsumerProperties.getProperty("limit"));
+ LOGGER.debug("Using filter " + aaiDmaapEventConsumerProperties.getProperty("filter"));
+ }
+
+ public void startProcessing(DmaapProcessor dmaapProcessor) throws Exception {
+ int fetchFailCounter = 0;
+
+ while (AAIConfig.get("aai.cacher.dmaap.consumer.enableEventProcessing").equals("true")) {
+ try {
+ LOGGER.debug("processEvents=" + dmaapConsumerSingleton.getProcessEvents() + " isInitialized="
+ + dmaapConsumerSingleton.getIsInitialized());
+ if (dmaapConsumerSingleton.getProcessEvents() || !dmaapConsumerSingleton.getIsInitialized()) {
+ Iterable<String> eventMessages = clientConsumer.process();
+ if (dmaapConsumerSingleton.getFirstEventMessage() != null) {
+ String firstMessage = getFirstMessage();
+ if (firstMessage != null) {
+ LOGGER.debug("Processing held dmaap message from the aaiDmaapEvent topic." + transId);
+ LOGGER.debug("Processing held dmaap message from the aaiDmaapEvent topic: " + firstMessage);
+ dmaapProcessor.process(firstMessage);
+ }
+ }
+ for (String eventMessage : eventMessages) {
+ if (!dmaapConsumerSingleton.getProcessEvents()) {
+ // hold message until app is ready for dmaap processing
+ setFirstMessage(eventMessage);
+ LOGGER.debug("Holding new dmaap message from the aaiDmaapEvent topic: " + eventMessage);
+ dmaapConsumerSingleton.setIsInitialized(true);
+ continue;
+ }
+ LOGGER.debug("Processing held dmaap message from the aaiDmaapEvent topic: " + eventMessage);
+ dmaapProcessor.process(eventMessage);
+ }
+ fetchFailCounter = 0;
+ } else {
+ // not processing events
+ this.aaiDmaapEventConsumer.close();
+ return;
+ }
+ break;
+ } catch (IOException e) {
+ fetchFailCounter++;
+ if (fetchFailCounter > 10) {
+ ErrorLogHelper.logException(new AAIException("AAI_4000", e));
+ this.aaiDmaapEventConsumer.close();
+ throw e;
+ }
+ LOGGER.info("ignoring IOException, count is at." + fetchFailCounter);
+ } catch (Exception e) {
+ ErrorLogHelper.logException(new AAIException("AAI_4000", e));
+
+ e.printStackTrace();
+ this.aaiDmaapEventConsumer.close();
+ e.printStackTrace();
+ throw e;
+ }
+ }
+ this.aaiDmaapEventConsumer.close();
+ }
+
+ /**
+ * checks on processing events flag
+ *
+ * @return
+ */
+ private boolean getIsInitialCheck() {
+ dmaapConsumerSingleton = DmaapConsumerSingleton.getInstance();
+ if (dmaapConsumerSingleton.getProcessEvents()) {
+ return false;
+ }
+ return !dmaapConsumerSingleton.getIsInitialized();
+ }
+
+ /**
+ * used to hold the first event message received before the app is ready to
+ * process
+ */
+
+ private void setFirstMessage(String message) {
+ dmaapConsumerSingleton.setFirstEventMessage(message);
+ }
+
+ /**
+ * used to get the first event message being held before the app is ready to
+ * process
+ */
+
+ private String getFirstMessage() {
+ String message = dmaapConsumerSingleton.getFirstEventMessage();
+ dmaapConsumerSingleton.setFirstEventMessage(null);
+ return message;
+ }
+
+}
diff --git a/src/main/java/org/onap/aai/cacher/dmaap/consumer/ClientConsumer.java b/src/main/java/org/onap/aai/cacher/dmaap/consumer/ClientConsumer.java
new file mode 100644
index 0000000..eaa341b
--- /dev/null
+++ b/src/main/java/org/onap/aai/cacher/dmaap/consumer/ClientConsumer.java
@@ -0,0 +1,31 @@
+/**
+ * ============LICENSE_START=======================================================
+ * org.onap.aai
+ * ================================================================================
+ * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.aai.cacher.dmaap.consumer;
+
+/**
+ * Interface that encapsulates the MRConsumer to switch between using just
+ * MRConsumer or to use MRConsumer with RestClient for environments where dme2
+ * is having problems
+ */
+public interface ClientConsumer {
+
+ Iterable<String> process() throws Exception;
+
+}
diff --git a/src/main/java/org/onap/aai/cacher/dmaap/consumer/DmaapConsumerSingleton.java b/src/main/java/org/onap/aai/cacher/dmaap/consumer/DmaapConsumerSingleton.java
new file mode 100644
index 0000000..5c2faa3
--- /dev/null
+++ b/src/main/java/org/onap/aai/cacher/dmaap/consumer/DmaapConsumerSingleton.java
@@ -0,0 +1,77 @@
+/**
+ * ============LICENSE_START=======================================================
+ * org.onap.aai
+ * ================================================================================
+ * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.aai.cacher.dmaap.consumer;
+
+public class DmaapConsumerSingleton {
+
+ private boolean processEvents;
+ private boolean isInitialized;
+
+ private String dmaapConsumerId;
+
+ private String firstEventMessage;
+
+ private static class Helper {
+ private static final DmaapConsumerSingleton INSTANCE = new DmaapConsumerSingleton();
+ }
+
+ public static DmaapConsumerSingleton getInstance() {
+ return Helper.INSTANCE;
+ }
+
+ private DmaapConsumerSingleton() {
+ processEvents = false;
+ isInitialized = false;
+ firstEventMessage = null;
+ dmaapConsumerId = null;
+ }
+
+ public void setProcessEvents(boolean processEvents) {
+ this.processEvents = processEvents;
+ }
+
+ public boolean getProcessEvents() {
+ return processEvents;
+ }
+
+ public void setIsInitialized(boolean isInitialized) {
+ this.isInitialized = isInitialized;
+ }
+
+ public boolean getIsInitialized() {
+ return isInitialized;
+ }
+
+ public void setFirstEventMessage(String firstEventMessage) {
+ this.firstEventMessage = firstEventMessage;
+ }
+
+ public String getFirstEventMessage() {
+ return firstEventMessage;
+ }
+
+ public void setDmaapConsumerId(String dmaapConsumerId) {
+ this.dmaapConsumerId = dmaapConsumerId;
+ }
+
+ public String getDmaapConsumerId() {
+ return dmaapConsumerId;
+ }
+}
diff --git a/src/main/java/org/onap/aai/cacher/dmaap/consumer/DmaapProcessor.java b/src/main/java/org/onap/aai/cacher/dmaap/consumer/DmaapProcessor.java
new file mode 100644
index 0000000..6cb4b82
--- /dev/null
+++ b/src/main/java/org/onap/aai/cacher/dmaap/consumer/DmaapProcessor.java
@@ -0,0 +1,32 @@
+/**
+ * ============LICENSE_START=======================================================
+ * org.onap.aai
+ * ================================================================================
+ * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.aai.cacher.dmaap.consumer;
+
+/**
+ * <b>DmaapProcessor</b> is the interface to use to process dmaap consumer
+ * events
+ *
+ * Any new topic that needs to be subscribed should implement this interface to
+ * process the events received by the dmaap publisher
+ */
+public interface DmaapProcessor {
+
+ void process(String eventMessage) throws Exception;
+}
diff --git a/src/main/java/org/onap/aai/cacher/dmaap/consumer/RestDmaapClientConsumer.java b/src/main/java/org/onap/aai/cacher/dmaap/consumer/RestDmaapClientConsumer.java
new file mode 100644
index 0000000..5839934
--- /dev/null
+++ b/src/main/java/org/onap/aai/cacher/dmaap/consumer/RestDmaapClientConsumer.java
@@ -0,0 +1,80 @@
+/**
+ * ============LICENSE_START=======================================================
+ * org.onap.aai
+ * ================================================================================
+ * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.aai.cacher.dmaap.consumer;
+
+import com.att.eelf.configuration.EELFLogger;
+import com.att.eelf.configuration.EELFManager;
+import com.att.nsa.mr.client.MRConsumer;
+import org.springframework.http.HttpHeaders;
+import org.springframework.web.client.RestTemplate;
+import org.springframework.web.util.UriComponentsBuilder;
+
+import java.util.Base64;
+import java.util.Properties;
+
+/**
+ * Encapsulates the MRConsumer and invokes it only if the environment is dev,
+ * testINT, testEXT If its one of those environments, uses the RestClient
+ */
+public class RestDmaapClientConsumer implements ClientConsumer {
+
+ private MRConsumer aaiDmaapEventConsumer;
+
+ private static final Base64.Encoder base64Encoder = Base64.getEncoder();
+
+ private HttpHeaders httpHeaders;
+ private RestTemplate restTemplate;
+
+ private String env;
+ // private String url;
+ private UriComponentsBuilder builder;
+
+ private Properties consumerProperties;
+
+ private static EELFLogger LOGGER = EELFManager.getInstance().getLogger(RestDmaapClientConsumer.class);
+
+ public RestDmaapClientConsumer(MRConsumer consumer, Properties aaiDmaapEventConsumerProperties) {
+
+ env = System.getProperty("lrmRO");
+
+ this.aaiDmaapEventConsumer = consumer;
+ this.consumerProperties = aaiDmaapEventConsumerProperties;
+
+ }
+
+ /**
+ * Checks if the environment is null or if the environment starts with dev,
+ * testEXT, or testINT and then if that is the case, it makes a request to the
+ * url to subscribe to that topic to retrieve all messages there If it is not
+ * one of those environments, then it will call the default fetch of messages
+ * from the MR Consumer
+ *
+ * @return a list of messages from the topic
+ * @throws Exception
+ */
+ @Override
+ public Iterable<String> process() throws Exception {
+
+ Iterable<String> messages = aaiDmaapEventConsumer.fetch();
+
+ LOGGER.debug("Finished the consumption of messages from dmaap");
+ return messages;
+ }
+}
diff --git a/src/main/java/org/onap/aai/cacher/egestion/printer/PayloadPrinterFactory.java b/src/main/java/org/onap/aai/cacher/egestion/printer/PayloadPrinterFactory.java
new file mode 100644
index 0000000..af6384f
--- /dev/null
+++ b/src/main/java/org/onap/aai/cacher/egestion/printer/PayloadPrinterFactory.java
@@ -0,0 +1,35 @@
+/**
+ * ============LICENSE_START=======================================================
+ * org.onap.aai
+ * ================================================================================
+ * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.aai.cacher.egestion.printer;
+
+import org.onap.aai.cacher.egestion.printer.strategy.PayloadPrinterStrategy;
+import org.onap.aai.cacher.egestion.printer.strategy.PayloadPrinterType;
+
+/**
+ * Factory to get parser strategy based on parser type.
+ */
+public interface PayloadPrinterFactory {
+ /**
+ *
+ * @param payloadParserType payload parser strategy type to use
+ * @return
+ */
+ PayloadPrinterStrategy getPayloadPrinterStrategy(PayloadPrinterType payloadParserType);
+}
diff --git a/src/main/java/org/onap/aai/cacher/egestion/printer/PayloadPrinterFactoryConfiguration.java b/src/main/java/org/onap/aai/cacher/egestion/printer/PayloadPrinterFactoryConfiguration.java
new file mode 100644
index 0000000..abbc30a
--- /dev/null
+++ b/src/main/java/org/onap/aai/cacher/egestion/printer/PayloadPrinterFactoryConfiguration.java
@@ -0,0 +1,36 @@
+/**
+ * ============LICENSE_START=======================================================
+ * org.onap.aai
+ * ================================================================================
+ * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.aai.cacher.egestion.printer;
+
+import org.springframework.beans.factory.FactoryBean;
+import org.springframework.beans.factory.config.ServiceLocatorFactoryBean;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+public class PayloadPrinterFactoryConfiguration {
+
+ @Bean
+ public FactoryBean locatorFactoryBean() {
+ ServiceLocatorFactoryBean bean = new ServiceLocatorFactoryBean();
+ bean.setServiceLocatorInterface(PayloadPrinterFactory.class);
+ return bean;
+ }
+} \ No newline at end of file
diff --git a/src/main/java/org/onap/aai/cacher/egestion/printer/PayloadPrinterService.java b/src/main/java/org/onap/aai/cacher/egestion/printer/PayloadPrinterService.java
new file mode 100644
index 0000000..6acea02
--- /dev/null
+++ b/src/main/java/org/onap/aai/cacher/egestion/printer/PayloadPrinterService.java
@@ -0,0 +1,43 @@
+/**
+ * ============LICENSE_START=======================================================
+ * org.onap.aai
+ * ================================================================================
+ * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.aai.cacher.egestion.printer;
+
+import com.google.gson.JsonArray;
+import com.google.gson.JsonObject;
+import org.onap.aai.cacher.egestion.printer.strategy.PayloadPrinterStrategy;
+import org.onap.aai.cacher.egestion.printer.strategy.PayloadPrinterType;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+@Service
+public class PayloadPrinterService {
+ @Autowired
+ private PayloadPrinterFactory payloadPrinterFactory;
+
+ public JsonObject createJson(String collectionName, JsonArray jsonArray, PayloadPrinterType payloadParserType) {
+ PayloadPrinterStrategy printer = payloadPrinterFactory.getPayloadPrinterStrategy(payloadParserType);
+ return printer.createJson(collectionName, jsonArray);
+ }
+
+ public JsonObject createJson(String collectionName, JsonArray jsonArray, String parserStrategy) {
+ return createJson(collectionName, jsonArray, PayloadPrinterType.fromString(parserStrategy + "-printer"));
+ }
+
+}
diff --git a/src/main/java/org/onap/aai/cacher/egestion/printer/strategy/AAIResourceGetAllPayloadPrinterStrategy.java b/src/main/java/org/onap/aai/cacher/egestion/printer/strategy/AAIResourceGetAllPayloadPrinterStrategy.java
new file mode 100644
index 0000000..8dfeb0b
--- /dev/null
+++ b/src/main/java/org/onap/aai/cacher/egestion/printer/strategy/AAIResourceGetAllPayloadPrinterStrategy.java
@@ -0,0 +1,49 @@
+/**
+ * ============LICENSE_START=======================================================
+ * org.onap.aai
+ * ================================================================================
+ * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.aai.cacher.egestion.printer.strategy;
+
+import com.google.gson.JsonArray;
+import com.google.gson.JsonObject;
+import org.springframework.beans.factory.config.ConfigurableBeanFactory;
+import org.springframework.context.annotation.Scope;
+import org.springframework.stereotype.Component;
+
+@Component(value = "aai-resource-get-all-printer")
+@Scope(scopeName = ConfigurableBeanFactory.SCOPE_SINGLETON)
+public class AAIResourceGetAllPayloadPrinterStrategy implements PayloadPrinterStrategy {
+
+ /**
+ * Create a jsonObject from the jsonArray for a specific collection
+ *
+ * @param collectionName
+ * @param jsonArray
+ * @return
+ */
+ @Override
+ public JsonObject createJson(String collectionName, JsonArray jsonArray) {
+ if (jsonArray != null && jsonArray.size() > 0) {
+ JsonObject jsonObj = new JsonObject();
+ jsonObj.add(collectionName, jsonArray);
+ return jsonObj;
+ } else {
+ return null;
+ }
+ }
+}
diff --git a/src/main/java/org/onap/aai/cacher/egestion/printer/strategy/NonePayloadPrinterStrategy.java b/src/main/java/org/onap/aai/cacher/egestion/printer/strategy/NonePayloadPrinterStrategy.java
new file mode 100644
index 0000000..3aecfe8
--- /dev/null
+++ b/src/main/java/org/onap/aai/cacher/egestion/printer/strategy/NonePayloadPrinterStrategy.java
@@ -0,0 +1,42 @@
+/**
+ * ============LICENSE_START=======================================================
+ * org.onap.aai
+ * ================================================================================
+ * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.aai.cacher.egestion.printer.strategy;
+
+import com.google.gson.JsonArray;
+import com.google.gson.JsonObject;
+import org.springframework.beans.factory.config.ConfigurableBeanFactory;
+import org.springframework.context.annotation.Scope;
+import org.springframework.stereotype.Component;
+
+/**
+ * Default parser strategy that dont not manipulate the payload.
+ */
+@Component(value = "none-printer")
+@Scope(scopeName = ConfigurableBeanFactory.SCOPE_SINGLETON)
+public class NonePayloadPrinterStrategy implements PayloadPrinterStrategy {
+ @Override
+ public JsonObject createJson(String collectionName, JsonArray jsonArray) {
+ if (jsonArray != null && jsonArray.size() > 0) {
+ return jsonArray.get(0).getAsJsonObject();
+ } else {
+ return null;
+ }
+ }
+}
diff --git a/src/main/java/org/onap/aai/cacher/egestion/printer/strategy/PayloadPrinterStrategy.java b/src/main/java/org/onap/aai/cacher/egestion/printer/strategy/PayloadPrinterStrategy.java
new file mode 100644
index 0000000..b6d3f08
--- /dev/null
+++ b/src/main/java/org/onap/aai/cacher/egestion/printer/strategy/PayloadPrinterStrategy.java
@@ -0,0 +1,28 @@
+/**
+ * ============LICENSE_START=======================================================
+ * org.onap.aai
+ * ================================================================================
+ * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.aai.cacher.egestion.printer.strategy;
+
+import com.google.gson.JsonArray;
+import com.google.gson.JsonObject;
+
+public interface PayloadPrinterStrategy {
+
+ JsonObject createJson(String collectionName, JsonArray jsonArray);
+}
diff --git a/src/main/java/org/onap/aai/cacher/egestion/printer/strategy/PayloadPrinterType.java b/src/main/java/org/onap/aai/cacher/egestion/printer/strategy/PayloadPrinterType.java
new file mode 100644
index 0000000..d83d622
--- /dev/null
+++ b/src/main/java/org/onap/aai/cacher/egestion/printer/strategy/PayloadPrinterType.java
@@ -0,0 +1,46 @@
+/**
+ * ============LICENSE_START=======================================================
+ * org.onap.aai
+ * ================================================================================
+ * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.aai.cacher.egestion.printer.strategy;
+
+import java.util.Arrays;
+
+public enum PayloadPrinterType {
+
+ NONE_PRINTER("none-printer"), AAI_RESOURCE_GET_ALL_PRINTER("aai-resource-get-all-printer");
+
+ private final String value;
+
+ PayloadPrinterType(String input) {
+ this.value = input;
+ }
+
+ public String getValue() {
+ return this.value;
+ }
+
+ @Override
+ public String toString() {
+ return this.value;
+ }
+
+ public static PayloadPrinterType fromString(String text) {
+ return Arrays.stream(values()).filter(bl -> bl.getValue().equalsIgnoreCase(text)).findFirst().orElse(null);
+ }
+}
diff --git a/src/main/java/org/onap/aai/cacher/injestion/parser/AAIResourcesUriTemplates.java b/src/main/java/org/onap/aai/cacher/injestion/parser/AAIResourcesUriTemplates.java
new file mode 100644
index 0000000..0885851
--- /dev/null
+++ b/src/main/java/org/onap/aai/cacher/injestion/parser/AAIResourcesUriTemplates.java
@@ -0,0 +1,208 @@
+/**
+ * ============LICENSE_START=======================================================
+ * org.onap.aai
+ * ================================================================================
+ * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.aai.cacher.injestion.parser;
+
+import com.google.gson.JsonObject;
+import org.apache.commons.lang3.StringUtils;
+import org.onap.aai.cacher.util.AAIConstants;
+import org.springframework.beans.factory.config.ConfigurableBeanFactory;
+import org.springframework.context.annotation.Scope;
+import org.springframework.stereotype.Component;
+import org.springframework.web.util.UriTemplate;
+import org.springframework.web.util.UriUtils;
+
+import javax.ws.rs.core.UriBuilder;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.UnsupportedEncodingException;
+import java.util.*;
+
+@Component
+@Scope(scopeName = ConfigurableBeanFactory.SCOPE_SINGLETON)
+public class AAIResourcesUriTemplates {
+
+ private final Map<String, String> typeToUriTemplate;
+
+ public AAIResourcesUriTemplates() throws IOException {
+ InputStream inputStream = new FileInputStream(AAIConstants.AAI_RESOURCES_URI_TEMPLATES);
+ Properties prop = new Properties();
+ prop.load(inputStream);
+
+ typeToUriTemplate = new HashMap<>(prop.size() + 1);
+ for (final String type : prop.stringPropertyNames()) {
+ typeToUriTemplate.put(type, prop.getProperty(type));
+ if (!typeToUriTemplate.containsKey("relationship")) {
+ typeToUriTemplate.put("relationship", "/relationship-list/relationship/{related-link}");
+ }
+ }
+ }
+
+ /**
+ * Get templated aai uri segment by type.
+ *
+ * @param type
+ * @return
+ */
+ public String getUriTemplateByType(String type) {
+ return typeToUriTemplate.get(type);
+ }
+
+ public Map<String, String> getUriTemplateMappings(String uri, String template) {
+
+ UriTemplate uriTemplate = new UriTemplate(template);
+ Map<String, String> mappings = uriTemplate.match(uri);
+
+ mappings.replaceAll((k, v) -> this.decodeProp(v));
+
+ return mappings;
+ }
+
+ /**
+ * For a given uri get an ordered list of templates.
+ *
+ * @param uri
+ * @return
+ */
+ public List<String> uriToTemplates(String uri) {
+ List<String> uriTemplateList = new ArrayList<>();
+ String template = "";
+ String truncatedUri = uri;
+
+ while (truncatedUri.contains("/")) {
+ template = this.getMatchingStartingTemplate(truncatedUri).get();
+ uriTemplateList.add(template);
+ int count = StringUtils.countMatches(template, "/");
+ if (count < StringUtils.countMatches(truncatedUri, "/")) {
+ truncatedUri = StringUtils.substring(truncatedUri,
+ StringUtils.ordinalIndexOf(truncatedUri, "/", count + 1));
+ } else {
+ truncatedUri = "";
+ }
+ }
+
+ return uriTemplateList;
+ }
+
+ /**
+ * For a given uri get an ordered list of templates.
+ *
+ * @param uri
+ * @return
+ */
+ public List<String> uriToSegments(String uri) {
+ List<String> uriList = new ArrayList<>();
+ String template = "";
+ String truncatedUri = uri;
+
+ while (truncatedUri.contains("/")) {
+ template = this.getMatchingStartingTemplate(truncatedUri).get();
+ int count = StringUtils.countMatches(template, "/");
+ int cutIndex = truncatedUri.length();
+ if (count != StringUtils.countMatches(truncatedUri, "/")) {
+ cutIndex = StringUtils.ordinalIndexOf(truncatedUri, "/", count + 1);
+ }
+ uriList.add(StringUtils.substring(truncatedUri, 0, cutIndex));
+ truncatedUri = StringUtils.substring(truncatedUri, cutIndex);
+ }
+
+ return uriList;
+ }
+
+ /**
+ * returns the template matching the start of the uri.
+ *
+ * @param uri
+ * @return @see java.util.Optional
+ */
+ public Optional<String> getMatchingStartingTemplate(String uri) {
+ return typeToUriTemplate.values().stream().filter(s -> uri.startsWith(s.split("/\\{")[0])).findFirst();
+ }
+
+ /**
+ * Given aai type and json object generate the uri for it.
+ *
+ * @param type
+ * @param jo
+ * @return
+ */
+ public String getUri(String type, JsonObject jo) {
+ String uriTemplate = getUriTemplateByType(type);
+ UriBuilder uriBuilder = UriBuilder.fromPath(uriTemplate);
+ List<String> keys = getUriKeys(uriTemplate);
+ Map<String, String> mapping = getEncodedMapping(keys, jo);
+
+ return uriBuilder.buildFromEncodedMap(mapping).toString();
+ }
+
+ /**
+ * Get encoded values from json object for each key in keys
+ *
+ * @param keys
+ * @param jo
+ * @return
+ */
+ private Map<String, String> getEncodedMapping(List<String> keys, JsonObject jo) {
+ final Map<String, String> mapping = new HashMap<>();
+ keys.forEach(key -> mapping.put(key, encodeProp(jo.get(key).getAsString())));
+
+ return mapping;
+ }
+
+ /**
+ * extract uri keys from the templated uri
+ *
+ * @param template
+ * @return
+ */
+ private List<String> getUriKeys(String template) {
+
+ UriTemplate uriTemplate = new UriTemplate(template);
+ return uriTemplate.getVariableNames();
+ }
+
+ /**
+ * UTF-8 encoding of @param string
+ *
+ * @param string string to be encoded
+ * @return
+ */
+ public String encodeProp(String string) {
+ try {
+ return UriUtils.encode(string, "UTF-8");
+ } catch (UnsupportedEncodingException e) {
+ return "";
+ }
+ }
+
+ /**
+ * UTF-8 decoding of @param string
+ *
+ * @param string string to be encoded
+ * @return
+ */
+ public String decodeProp(String string) {
+ try {
+ return UriUtils.decode(string, "UTF-8");
+ } catch (UnsupportedEncodingException e) {
+ return "";
+ }
+ }
+} \ No newline at end of file
diff --git a/src/main/java/org/onap/aai/cacher/injestion/parser/PayloadParserFactory.java b/src/main/java/org/onap/aai/cacher/injestion/parser/PayloadParserFactory.java
new file mode 100644
index 0000000..bd36e8f
--- /dev/null
+++ b/src/main/java/org/onap/aai/cacher/injestion/parser/PayloadParserFactory.java
@@ -0,0 +1,35 @@
+/**
+ * ============LICENSE_START=======================================================
+ * org.onap.aai
+ * ================================================================================
+ * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.aai.cacher.injestion.parser;
+
+import org.onap.aai.cacher.injestion.parser.strategy.PayloadParserStrategy;
+import org.onap.aai.cacher.injestion.parser.strategy.PayloadParserType;
+
+/**
+ * Factory to get parser strategy based on parser type.
+ */
+public interface PayloadParserFactory {
+ /**
+ *
+ * @param ppse payload parser strategy type to use
+ * @return
+ */
+ PayloadParserStrategy getPayloadParserStrategy(PayloadParserType ppse);
+}
diff --git a/src/main/java/org/onap/aai/cacher/injestion/parser/PayloadParserFactoryConfiguration.java b/src/main/java/org/onap/aai/cacher/injestion/parser/PayloadParserFactoryConfiguration.java
new file mode 100644
index 0000000..28424cb
--- /dev/null
+++ b/src/main/java/org/onap/aai/cacher/injestion/parser/PayloadParserFactoryConfiguration.java
@@ -0,0 +1,36 @@
+/**
+ * ============LICENSE_START=======================================================
+ * org.onap.aai
+ * ================================================================================
+ * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.aai.cacher.injestion.parser;
+
+import org.springframework.beans.factory.FactoryBean;
+import org.springframework.beans.factory.config.ServiceLocatorFactoryBean;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+public class PayloadParserFactoryConfiguration {
+
+ @Bean
+ public FactoryBean serviceLocatorFactoryBean() {
+ ServiceLocatorFactoryBean factoryBean = new ServiceLocatorFactoryBean();
+ factoryBean.setServiceLocatorInterface(PayloadParserFactory.class);
+ return factoryBean;
+ }
+} \ No newline at end of file
diff --git a/src/main/java/org/onap/aai/cacher/injestion/parser/PayloadParserService.java b/src/main/java/org/onap/aai/cacher/injestion/parser/PayloadParserService.java
new file mode 100644
index 0000000..1d7b38c
--- /dev/null
+++ b/src/main/java/org/onap/aai/cacher/injestion/parser/PayloadParserService.java
@@ -0,0 +1,71 @@
+/**
+ * ============LICENSE_START=======================================================
+ * org.onap.aai
+ * ================================================================================
+ * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.aai.cacher.injestion.parser;
+
+import com.google.gson.JsonObject;
+import com.google.gson.JsonParser;
+import org.onap.aai.cacher.injestion.parser.strategy.PayloadParserStrategy;
+import org.onap.aai.cacher.injestion.parser.strategy.PayloadParserType;
+import org.onap.aai.cacher.model.CacheEntry;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+
+/**
+ * Service to be use to interact with parsers.
+ */
+@Service
+public class PayloadParserService {
+
+ private PayloadParserFactory payloadParserFactory;
+
+ @Autowired
+ public PayloadParserService(PayloadParserFactory payloadParserFactory) {
+ this.payloadParserFactory = payloadParserFactory;
+ }
+
+ public List<CacheEntry> doParse(String cacheKey, JsonObject jo, PayloadParserType payloadParserType) {
+
+ PayloadParserStrategy parser = payloadParserFactory.getPayloadParserStrategy(payloadParserType);
+ return parser.process(cacheKey, jo);
+ }
+
+ public List<CacheEntry> doParse(String cacheKey, JsonObject jo, String payloadParserTypeStr) {
+ return doParse(cacheKey, jo, PayloadParserType.fromString(payloadParserTypeStr));
+ }
+
+ public List<CacheEntry> doParse(String cacheKey, JsonObject jo) {
+ return this.doParse(cacheKey, jo, PayloadParserType.NONE);
+ }
+
+ public List<CacheEntry> doParse(String cacheKey, String jo, PayloadParserType payloadParserType) {
+ JsonParser jsonParser = new JsonParser();
+ return doParse(cacheKey, jsonParser.parse(jo).getAsJsonObject(), payloadParserType);
+ }
+
+ public List<CacheEntry> doParse(String cacheKey, String jo, String payloadParserTypeStr) {
+ return doParse(cacheKey, jo, PayloadParserType.fromString(payloadParserTypeStr));
+ }
+
+ public List<CacheEntry> doParse(String cacheKey, String jo) {
+ return this.doParse(cacheKey, jo, PayloadParserType.NONE);
+ }
+} \ No newline at end of file
diff --git a/src/main/java/org/onap/aai/cacher/injestion/parser/strategy/AAIResourceDmaapParserStrategy.java b/src/main/java/org/onap/aai/cacher/injestion/parser/strategy/AAIResourceDmaapParserStrategy.java
new file mode 100644
index 0000000..6de0585
--- /dev/null
+++ b/src/main/java/org/onap/aai/cacher/injestion/parser/strategy/AAIResourceDmaapParserStrategy.java
@@ -0,0 +1,470 @@
+/**
+ * ============LICENSE_START=======================================================
+ * org.onap.aai
+ * ================================================================================
+ * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.aai.cacher.injestion.parser.strategy;
+
+import com.google.gson.JsonArray;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import org.apache.commons.lang3.StringUtils;
+import org.onap.aai.cacher.injestion.parser.AAIResourcesUriTemplates;
+import org.onap.aai.cacher.injestion.parser.PayloadParserService;
+import org.onap.aai.cacher.model.CacheEntry;
+import org.onap.aai.cacher.model.DBAction;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.config.ConfigurableBeanFactory;
+import org.springframework.context.annotation.Scope;
+import org.springframework.stereotype.Component;
+import org.springframework.util.LinkedMultiValueMap;
+import org.springframework.util.MultiValueMap;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+
+/**
+ * AAI resource get all parser strategy
+ */
+@Component(value = "aai-resource-dmaap")
+@Scope(scopeName = ConfigurableBeanFactory.SCOPE_SINGLETON)
+public class AAIResourceDmaapParserStrategy implements PayloadParserStrategy {
+
+ protected AAIResourcesUriTemplates aaiResourcesUriTemplates;
+
+ private PayloadParserService payloadParserService;
+
+ private DmaapAction actionType;
+
+ @Autowired
+ public AAIResourceDmaapParserStrategy(AAIResourcesUriTemplates aaiResourcesUriTemplates,
+ PayloadParserService payloadParserService) {
+ this.aaiResourcesUriTemplates = aaiResourcesUriTemplates;
+ this.payloadParserService = payloadParserService;
+ }
+
+ /**
+ * Parses aai resources specific payloads generating the details for caching.
+ *
+ * @param originalKey
+ * @param jsonObject
+ * @return
+ */
+ @Override
+ public List<CacheEntry> process(String originalKey, JsonObject jsonObject) {
+ final List<CacheEntry> cacheEntries = new ArrayList<>();
+
+ JsonObject header = jsonObject.getAsJsonObject("event-header");
+ JsonObject entity = jsonObject.getAsJsonObject("entity");
+ String topEntity = header.get("top-entity-type").getAsString();
+
+ actionType = DmaapAction.valueOf(header.get("action").getAsString());
+ boolean isTopLevel = topEntity.equals(header.get("entity-type").getAsString());
+ String fullUri = getFullUri(header);
+
+ CacheEntry cacheEntry = generateCacheEntry(entity, actionType, isTopLevel, fullUri);
+
+ cacheEntries.add(cacheEntry);
+
+ // determine relationships on the other end that need to be modified.
+ MultiValueMap<String, AAIResourceDmaapParserStrategy.AAIRelatedToDetails> relationships;
+ if (isTopLevel) {
+ relationships = getFromRelationshipFullUriToRelationshipObj(entity, fullUri);
+ } else {
+ relationships = getFromRelationshipFullUriToRelationshipObj(entity, getBaseUri(fullUri));
+ }
+ if (jsonObject.has("existing-obj")) {
+ adjustRelationshipsBasedOnExisting(jsonObject, fullUri, relationships);
+ }
+
+ JsonObject relatedToObj;
+ for (Map.Entry<String, List<AAIResourceDmaapParserStrategy.AAIRelatedToDetails>> relationship : relationships
+ .entrySet()) {
+ for (AAIResourceDmaapParserStrategy.AAIRelatedToDetails aaiRelatedToDetails : relationship.getValue()) {
+ relatedToObj = fullUriToRelationshipObj(relationship.getKey(), aaiRelatedToDetails.getLabel());
+ cacheEntries.add(generateCacheEntry(relatedToObj, aaiRelatedToDetails.getActionType(), false,
+ aaiRelatedToDetails.getFullUri() + "/relationship-list/relationship/"
+ + aaiResourcesUriTemplates.encodeProp(relationship.getKey())));
+ }
+ }
+
+ return cacheEntries;
+ }
+
+ private String getBaseUri(String fullUri) {
+ String uri = getUri(fullUri);
+ List<AAIUriSegment> uriSegmentList = getAaiUriSegments(uri);
+ return uriSegmentList.get(0).getSegment();
+ }
+
+ protected String getFullUriPrefix(String fullUri) {
+ return StringUtils.substring(fullUri, 0, StringUtils.ordinalIndexOf(fullUri, "/", 3));
+ }
+
+ protected CacheEntry generateCacheEntry(JsonObject entity, DmaapAction actionType, boolean isTopLevel,
+ String fullUri) {
+ String uri = getUri(fullUri);
+ List<AAIUriSegment> uriSegmentList = getAaiUriSegments(uri);
+ String id = uriSegmentList.get(0).getSegment();
+ String collection = uriSegmentList.get(0).getSegmentSingular();
+ JsonObject entityBody = getEntityBody(entity, uriSegmentList);
+ JsonObject findQuery = getFindQuery(uriSegmentList);
+ JsonObject nestedFindQuery = getNestedFindQuery(uriSegmentList);
+ String nestedField = getNestedField(uriSegmentList);
+ JsonObject nestedIdentifier = getNestedIdentifier(uriSegmentList);
+ DBAction dbAction = getDBAction(actionType);
+
+ return CacheEntry.CacheEntryBuilder.createCacheEntry().inCollection(collection).withDbAction(dbAction)
+ .withId(id).isNested(!isTopLevel).withPayload(entityBody).withFindQuery(findQuery)
+ .withNestedFind(nestedFindQuery).withNestedField(nestedField)
+ .withNestedFieldIdentifierObj(nestedIdentifier).build();
+ }
+
+ protected DBAction getDBAction(DmaapAction actionType) {
+ DBAction dbAction = DBAction.INSERT_REPLACE;
+ switch (actionType) {
+ case CREATE:
+ dbAction = DBAction.INSERT_REPLACE;
+ break;
+ case DELETE:
+ dbAction = DBAction.DELETE;
+ break;
+ case UPDATE:
+ dbAction = DBAction.UPDATE;
+ break;
+ }
+ return dbAction;
+ }
+
+ protected JsonObject getNestedIdentifier(List<AAIUriSegment> uriSegmentList) {
+ final JsonObject nestedIdentifier = new JsonObject();
+ if (uriSegmentList.size() > 1) {
+ AAIUriSegment lastSegment = uriSegmentList.get(uriSegmentList.size() - 1);
+ lastSegment.getSegmentKeyValues().forEach(nestedIdentifier::addProperty);
+ }
+ return nestedIdentifier;
+ }
+
+ protected String getNestedField(List<AAIUriSegment> uriSegmentList) {
+ StringBuilder nestedField = new StringBuilder();
+
+ if (uriSegmentList.size() > 1) {
+ if (uriSegmentList.get(1).getSegmentPlural().isPresent()) {
+ nestedField.append(uriSegmentList.get(1).getSegmentPlural().get()).append(".")
+ .append(uriSegmentList.get(1).getSegmentSingular());
+ } else {
+ nestedField.append(uriSegmentList.get(1).getSegmentSingular());
+ }
+
+ for (int i = 2; i < uriSegmentList.size(); i++) {
+ if (uriSegmentList.get(i).getSegmentPlural().isPresent()) {
+ nestedField.append(".$.").append(uriSegmentList.get(i).getSegmentPlural().get()).append(".")
+ .append(uriSegmentList.get(i).getSegmentSingular());
+ } else {
+ nestedField.append(".$.").append(uriSegmentList.get(i).getSegmentSingular());
+ }
+ }
+ }
+ return nestedField.toString();
+ }
+
+ protected JsonObject getNestedFindQuery(List<AAIUriSegment> uriSegmentList) {
+ return getFindQuery(uriSegmentList, true);
+ }
+
+ protected JsonObject getFindQuery(List<AAIUriSegment> uriSegmentList) {
+ return getFindQuery(uriSegmentList, false);
+ }
+
+ protected JsonObject getFindQuery(List<AAIUriSegment> uriSegmentList, boolean isNested) {
+ final JsonObject findQuery = new JsonObject();
+ if (uriSegmentList.isEmpty()) {
+ return findQuery;
+ }
+
+ AAIUriSegment aaiUriSegment = uriSegmentList.get(0);
+ findQuery.addProperty("_id", aaiUriSegment.getSegment());
+ aaiUriSegment.getSegmentKeyValues().forEach(findQuery::addProperty);
+
+ StringBuilder nestedField = new StringBuilder();
+ int segmentToProcess = uriSegmentList.size();
+ if (!isNested) {
+ segmentToProcess--;
+ }
+ for (int i = 1; i < segmentToProcess; i++) {
+ aaiUriSegment = uriSegmentList.get(i);
+ if (nestedField.length() != 0) {
+ nestedField.append(".");
+ }
+ if (aaiUriSegment.getSegmentPlural().isPresent()) {
+ nestedField.append(aaiUriSegment.getSegmentPlural().get()).append(".");
+ }
+ nestedField.append(aaiUriSegment.getSegmentSingular());
+ aaiUriSegment.getSegmentKeyValues()
+ .forEach((k, v) -> findQuery.addProperty(nestedField.toString() + "." + k, v));
+ }
+ return findQuery;
+ }
+
+ /**
+ * strips away the parent wrapping from the dmaap events entity payload
+ *
+ * @param entity
+ * @param uriSegmentList
+ * @return
+ */
+ protected JsonObject getEntityBody(JsonObject entity, List<AAIUriSegment> uriSegmentList) {
+
+ if (uriSegmentList.size() == 1) {
+ return entity;
+ }
+
+ JsonObject entityBody = entity.getAsJsonObject();
+
+ // if processing relationship no need to look for nested obj, entity is the obj
+ if (!"relationship".equals(uriSegmentList.get(uriSegmentList.size() - 1).getSegmentSingular())) {
+ for (int i = 1; i < uriSegmentList.size(); i++) {
+ if (uriSegmentList.get(i).getSegmentPlural().isPresent()) {
+ entityBody = entityBody.getAsJsonObject(uriSegmentList.get(i).getSegmentPlural().get())
+ .getAsJsonArray(uriSegmentList.get(i).getSegmentSingular()).get(0).getAsJsonObject();
+ } else {
+ entityBody = entityBody.getAsJsonArray(uriSegmentList.get(i).getSegmentSingular()).get(0)
+ .getAsJsonObject();
+ }
+
+ }
+ }
+
+ return entityBody;
+
+ }
+
+ protected List<AAIUriSegment> getAaiUriSegments(String uri) {
+ List<String> uriSegmentTemplates = aaiResourcesUriTemplates.uriToTemplates(uri);
+ List<String> uriSegments = aaiResourcesUriTemplates.uriToSegments(uri);
+
+ List<AAIUriSegment> uriSegmentList = new ArrayList<>(uriSegments.size());
+
+ AAIUriSegment aus;
+ for (int i = 0; i < uriSegments.size(); i++) {
+ aus = new AAIUriSegment(uriSegments.get(i), uriSegmentTemplates.get(i));
+ aus.setSegmentKeyValues(
+ aaiResourcesUriTemplates.getUriTemplateMappings(aus.getSegment(), aus.getSegmentTemplate()));
+ uriSegmentList.add(aus);
+ }
+ return uriSegmentList;
+ }
+
+ /**
+ * For update events with an existing obj available adjust the cache actions to
+ * be taken on relationship objects.
+ *
+ * @param jsonObject
+ * @param fullUri
+ * @param newObjectRelationships
+ */
+ private void adjustRelationshipsBasedOnExisting(JsonObject jsonObject, String fullUri,
+ MultiValueMap<String, AAIResourceDmaapParserStrategy.AAIRelatedToDetails> newObjectRelationships) {
+ JsonObject existingObj = jsonObject.getAsJsonObject("existing-obj");
+ MultiValueMap<String, AAIResourceDmaapParserStrategy.AAIRelatedToDetails> oldRelationships = getFromRelationshipFullUriToRelationshipObj(
+ existingObj, fullUri);
+ oldRelationships.forEach((k, v) -> {
+ if (newObjectRelationships.containsKey(k)) {
+ v.forEach(oldA -> {
+ int found = -1;
+ for (int i = 0; i < newObjectRelationships.get(k).size(); i++) {
+ if (newObjectRelationships.get(k).get(i).getFullUri().equals(oldA.getFullUri())) {
+ found = i;
+ break;
+ }
+ }
+ if (found != -1) {
+ newObjectRelationships.get(k).remove(newObjectRelationships.get(k).get(found));
+ } else {
+ oldA.setActionType(DmaapAction.DELETE);
+ newObjectRelationships.get(k).add(oldA);
+ }
+ });
+ } else {
+ v.forEach(aaiRelatedToDetails -> {
+ aaiRelatedToDetails.setActionType(DmaapAction.DELETE);
+ newObjectRelationships.add(k, aaiRelatedToDetails);
+ });
+ }
+ });
+ }
+
+ /**
+ * Given fullUri uri generate an aai relationship obj
+ *
+ * @param fullUri
+ * @return
+ */
+ protected JsonObject fullUriToRelationshipObj(String fullUri, String label) {
+ final JsonObject relObj = new JsonObject();
+ final JsonArray relData = new JsonArray();
+ String uri = getUri(fullUri);
+ List<AAIUriSegment> uriSegmentList = getAaiUriSegments(uri);
+
+ relObj.addProperty("related-to", uriSegmentList.get(uriSegmentList.size() - 1).getSegmentSingular());
+ if (label != null) {
+ relObj.addProperty("relationship-label", label);
+ }
+ relObj.addProperty("related-link", fullUri);
+
+ for (AAIUriSegment aaiUriSegment : uriSegmentList) {
+ aaiUriSegment.getSegmentKeyValues().forEach((k, v) -> {
+ JsonObject relDataEntry;
+ relDataEntry = new JsonObject();
+ relDataEntry.addProperty("relationship-key", aaiUriSegment.getSegmentSingular() + "." + k);
+ relDataEntry.addProperty("relationship-value", v);
+ relData.add(relDataEntry);
+ });
+ }
+ relObj.add("relationship-data", relData);
+
+ return relObj;
+ }
+
+ /**
+ *
+ * @param entity
+ * @param fullUri
+ * @return
+ */
+ protected MultiValueMap<String, AAIResourceDmaapParserStrategy.AAIRelatedToDetails> getFromRelationshipFullUriToRelationshipObj(
+ JsonObject entity, String fullUri) {
+ final MultiValueMap<String, AAIResourceDmaapParserStrategy.AAIRelatedToDetails> relationshipMapping = new LinkedMultiValueMap<>();
+ for (Map.Entry<String, JsonElement> e : entity.entrySet()) {
+ if (e.getKey().equals("relationship-list") && e.getValue().isJsonObject()) {
+ JsonArray relationships = e.getValue().getAsJsonObject().getAsJsonArray("relationship");
+ for (JsonElement relationship : relationships) {
+ relationshipMapping.add(fullUri, new AAIResourceDmaapParserStrategy.AAIRelatedToDetails(
+ relationship.getAsJsonObject().get("related-link").getAsString(),
+ relationship.getAsJsonObject().get("relationship-label").getAsString(), actionType));
+ }
+ } else if (e.getValue().isJsonObject() && e.getValue().getAsJsonObject().entrySet().size() == 1) {
+ Map.Entry<String, JsonElement> entry = e.getValue().getAsJsonObject().entrySet().iterator().next();
+ if (entry.getValue().isJsonArray()) {
+ String type = entry.getKey();
+ JsonArray children = entry.getValue().getAsJsonArray();
+ for (JsonElement child : children) {
+ relationshipMapping.putAll(getFromRelationshipFullUriToRelationshipObj(child.getAsJsonObject(),
+ fullUri + aaiResourcesUriTemplates.getUri(type, child.getAsJsonObject())));
+ }
+ }
+ }
+ }
+ return relationshipMapping;
+ }
+
+ protected String getUri(String fullUri) {
+ return fullUri.replaceAll("/aai/v\\d+", "");
+ }
+
+ protected String getFullUri(JsonObject header) {
+ return header.get("entity-link").getAsString();
+ }
+
+ protected enum DmaapAction {
+ DELETE, UPDATE, CREATE
+ }
+
+ class AAIUriSegment {
+
+ private String segment;
+ private String segmentTemplate;
+ private Optional<String> segmentPlural = Optional.empty();
+ private String segmentSingular;
+ private Map<String, String> segmentKeyValues;
+
+ AAIUriSegment(String segment, String template) {
+ this.segment = segment;
+ this.segmentTemplate = template;
+ String[] segmentSplit = segment.split("/");
+ String[] templateSplit = template.split("/");
+ for (int i = 0; i < templateSplit.length; i++) {
+ if (templateSplit[i].contains("{")) {
+ segmentSingular = segmentSplit[i - 1];
+ if (!"".equals(segmentSplit[i - 2])) {
+ segmentPlural = Optional.of(segmentSplit[i - 2]);
+ }
+ break;
+ }
+ }
+ }
+
+ String getSegment() {
+ return segment;
+ }
+
+ String getSegmentTemplate() {
+ return segmentTemplate;
+ }
+
+ Map<String, String> getSegmentKeyValues() {
+ return segmentKeyValues;
+ }
+
+ void setSegmentKeyValues(Map<String, String> segmentKeyValues) {
+ this.segmentKeyValues = segmentKeyValues;
+ }
+
+ Optional<String> getSegmentPlural() {
+ return segmentPlural;
+ }
+
+ String getSegmentSingular() {
+ return segmentSingular;
+ }
+ }
+
+ class AAIRelatedToDetails {
+ private String fullUri;
+ private String label;
+ private DmaapAction actionType;
+
+ public AAIRelatedToDetails(String fullUri, String label, DmaapAction actionType) {
+ this.fullUri = fullUri;
+ this.label = label;
+ this.actionType = actionType;
+ }
+
+ public String getFullUri() {
+ return fullUri;
+ }
+
+ public String getLabel() {
+ return label;
+ }
+
+ public DmaapAction getActionType() {
+ return actionType;
+ }
+
+ public void setActionType(DmaapAction actionType) {
+ this.actionType = actionType;
+ }
+
+ @Override
+ public String toString() {
+ return fullUri + " : " + label;
+ }
+ }
+}
diff --git a/src/main/java/org/onap/aai/cacher/injestion/parser/strategy/AAIResourceGetAllPayloadParserStrategy.java b/src/main/java/org/onap/aai/cacher/injestion/parser/strategy/AAIResourceGetAllPayloadParserStrategy.java
new file mode 100644
index 0000000..1c2f6cf
--- /dev/null
+++ b/src/main/java/org/onap/aai/cacher/injestion/parser/strategy/AAIResourceGetAllPayloadParserStrategy.java
@@ -0,0 +1,85 @@
+/**
+ * ============LICENSE_START=======================================================
+ * org.onap.aai
+ * ================================================================================
+ * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.aai.cacher.injestion.parser.strategy;
+
+import com.google.gson.JsonArray;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import org.onap.aai.cacher.injestion.parser.AAIResourcesUriTemplates;
+import org.onap.aai.cacher.model.CacheEntry;
+import org.onap.aai.cacher.model.DBAction;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.config.ConfigurableBeanFactory;
+import org.springframework.context.annotation.Scope;
+import org.springframework.stereotype.Component;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * AAI resource get all parser strategy
+ */
+@Component(value = "aai-resource-get-all")
+@Scope(scopeName = ConfigurableBeanFactory.SCOPE_SINGLETON)
+public class AAIResourceGetAllPayloadParserStrategy implements PayloadParserStrategy {
+
+ AAIResourcesUriTemplates aaiResourcesUriTemplates;
+
+ @Autowired
+ public AAIResourceGetAllPayloadParserStrategy(AAIResourcesUriTemplates aaiResourcesUriTemplates) {
+ this.aaiResourcesUriTemplates = aaiResourcesUriTemplates;
+ }
+
+ /**
+ * Parses aai resources specific payloads generating the details for .
+ *
+ * @param originalKey
+ * @param jsonObject
+ * @return
+ */
+ @Override
+ public List<CacheEntry> process(String originalKey, JsonObject jsonObject) {
+ final List<CacheEntry> cacheEntries = new ArrayList<>();
+
+ String type = jsonObject.entrySet().iterator().next().getKey();
+
+ JsonArray ja = jsonObject.getAsJsonArray(type);
+ CacheEntry cacheEntry;
+ String uri;
+ JsonObject jo;
+ for (JsonElement jsonElement : ja) {
+ jo = jsonElement.getAsJsonObject();
+ uri = aaiResourcesUriTemplates.getUri(type, jo);
+ jsonObject.addProperty("_id", uri);
+ cacheEntry = CacheEntry.CacheEntryBuilder.createCacheEntry().withId(uri).inCollection(originalKey)
+ .withFindQuery(getFindQuery(uri)).withPayload(jo).withDbAction(DBAction.INSERT_REPLACE).build();
+ cacheEntries.add(cacheEntry);
+ }
+
+ return cacheEntries;
+ }
+
+ protected JsonObject getFindQuery(String uri) {
+ JsonObject jo = new JsonObject();
+ jo.addProperty("_id", uri);
+ return jo;
+ }
+
+}
diff --git a/src/main/java/org/onap/aai/cacher/injestion/parser/strategy/NonePayloadParserStrategy.java b/src/main/java/org/onap/aai/cacher/injestion/parser/strategy/NonePayloadParserStrategy.java
new file mode 100644
index 0000000..9d468b9
--- /dev/null
+++ b/src/main/java/org/onap/aai/cacher/injestion/parser/strategy/NonePayloadParserStrategy.java
@@ -0,0 +1,48 @@
+/**
+ * ============LICENSE_START=======================================================
+ * org.onap.aai
+ * ================================================================================
+ * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.aai.cacher.injestion.parser.strategy;
+
+import com.google.gson.JsonObject;
+import org.onap.aai.cacher.model.CacheEntry;
+import org.onap.aai.cacher.model.DBAction;
+import org.springframework.beans.factory.config.ConfigurableBeanFactory;
+import org.springframework.context.annotation.Scope;
+import org.springframework.stereotype.Component;
+
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * Default parser strategy that dont not manipulate the payload.
+ */
+@Component(value = "none")
+@Scope(scopeName = ConfigurableBeanFactory.SCOPE_SINGLETON)
+public class NonePayloadParserStrategy implements PayloadParserStrategy {
+
+ @Override
+ public List<CacheEntry> process(String originalKey, JsonObject jsonObject) {
+ JsonObject find = new JsonObject();
+ jsonObject.addProperty("_id", originalKey);
+ return Collections.singletonList(
+ CacheEntry.CacheEntryBuilder.createCacheEntry().withId(originalKey).inCollection(originalKey)
+ .withFindQuery(find).withPayload(jsonObject).withDbAction(DBAction.INSERT_REPLACE).build());
+ }
+
+}
diff --git a/src/main/java/org/onap/aai/cacher/injestion/parser/strategy/PayloadParserStrategy.java b/src/main/java/org/onap/aai/cacher/injestion/parser/strategy/PayloadParserStrategy.java
new file mode 100644
index 0000000..a8f66b6
--- /dev/null
+++ b/src/main/java/org/onap/aai/cacher/injestion/parser/strategy/PayloadParserStrategy.java
@@ -0,0 +1,31 @@
+/**
+ * ============LICENSE_START=======================================================
+ * org.onap.aai
+ * ================================================================================
+ * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.aai.cacher.injestion.parser.strategy;
+
+import com.google.gson.JsonObject;
+import org.onap.aai.cacher.model.CacheEntry;
+
+import java.util.List;
+
+public interface PayloadParserStrategy {
+
+ List<CacheEntry> process(String originalKey, JsonObject jsonObject);
+
+}
diff --git a/src/main/java/org/onap/aai/cacher/injestion/parser/strategy/PayloadParserType.java b/src/main/java/org/onap/aai/cacher/injestion/parser/strategy/PayloadParserType.java
new file mode 100644
index 0000000..b497a8c
--- /dev/null
+++ b/src/main/java/org/onap/aai/cacher/injestion/parser/strategy/PayloadParserType.java
@@ -0,0 +1,45 @@
+/**
+ * ============LICENSE_START=======================================================
+ * org.onap.aai
+ * ================================================================================
+ * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.aai.cacher.injestion.parser.strategy;
+
+import java.util.Arrays;
+
+public enum PayloadParserType {
+
+ NONE("none"), AAI_RESOURCE_GET_ALL("aai-resource-get-all"), AAI_RESOURCE_DMAAP("aai-resource-dmaap");
+ private final String value;
+
+ PayloadParserType(String input) {
+ this.value = input;
+ }
+
+ public String getValue() {
+ return this.value;
+ }
+
+ @Override
+ public String toString() {
+ return this.value;
+ }
+
+ public static PayloadParserType fromString(String text) {
+ return Arrays.stream(values()).filter(bl -> bl.getValue().equalsIgnoreCase(text)).findFirst().orElse(null);
+ }
+}
diff --git a/src/main/java/org/onap/aai/cacher/model/CacheEntry.java b/src/main/java/org/onap/aai/cacher/model/CacheEntry.java
new file mode 100644
index 0000000..ed6715e
--- /dev/null
+++ b/src/main/java/org/onap/aai/cacher/model/CacheEntry.java
@@ -0,0 +1,206 @@
+/**
+ * ============LICENSE_START=======================================================
+ * org.onap.aai
+ * ================================================================================
+ * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.aai.cacher.model;
+
+import com.google.gson.JsonObject;
+
+/**
+ * Captures the details of a cache entry to be inserted onto the database
+ */
+public class CacheEntry {
+
+ protected DBAction dbAction;
+
+ protected String id;
+ protected String collection;
+ protected JsonObject payload;
+ protected JsonObject findQuery;
+
+ protected boolean isNested = false;
+ protected String nestedField;
+ protected JsonObject nestedFind;
+ protected JsonObject nestedFieldIdentifierObj;
+
+ private CacheEntry() {
+ }
+
+ public DBAction getDbAction() {
+ return dbAction;
+ }
+
+ public void setDbAction(DBAction dbAction) {
+ this.dbAction = dbAction;
+ }
+
+ public String getId() {
+ return id;
+ }
+
+ public void setId(String id) {
+ this.id = id;
+ }
+
+ public String getCollection() {
+ return collection;
+ }
+
+ public void setCollection(String collection) {
+ this.collection = collection;
+ }
+
+ public JsonObject getPayload() {
+ return payload;
+ }
+
+ public void setPayload(JsonObject payload) {
+ this.payload = payload;
+ }
+
+ public JsonObject getFindQuery() {
+ return findQuery;
+ }
+
+ public void setFindQuery(JsonObject findQuery) {
+ this.findQuery = findQuery;
+ }
+
+ public boolean isNested() {
+ return isNested;
+ }
+
+ public void setNested(boolean nested) {
+ isNested = nested;
+ }
+
+ public String getNestedField() {
+ return nestedField;
+ }
+
+ public void setNestedField(String nestedField) {
+ this.nestedField = nestedField;
+ }
+
+ public JsonObject getNestedFind() {
+ return nestedFind;
+ }
+
+ public void setNestedFind(JsonObject nestedFind) {
+ this.nestedFind = nestedFind;
+ }
+
+ public JsonObject getNestedFieldIdentifierObj() {
+ return nestedFieldIdentifierObj;
+ }
+
+ public void setNestedFieldIdentifierObj(JsonObject nestedFieldIdentifierObj) {
+ this.nestedFieldIdentifierObj = nestedFieldIdentifierObj;
+ }
+
+ public static final class CacheEntryBuilder {
+ protected DBAction dbAction;
+ protected String id;
+ protected String collection;
+ protected JsonObject payload;
+ protected JsonObject findQuery;
+ protected boolean isNested;
+ protected String nestedField;
+ protected JsonObject nestedFind;
+ protected JsonObject nestedFieldIdentifierObj;
+
+ private CacheEntryBuilder() {
+ }
+
+ public static CacheEntryBuilder createCacheEntry() {
+ return new CacheEntryBuilder();
+ }
+
+ public CacheEntryBuilder deepCopy(CacheEntry cacheEntry) {
+ dbAction = cacheEntry.getDbAction();
+ id = cacheEntry.getId();
+ collection = cacheEntry.getCollection();
+ payload = cacheEntry.getPayload();
+ findQuery = cacheEntry.getFindQuery();
+ isNested = cacheEntry.isNested();
+ nestedField = cacheEntry.getNestedField();
+ nestedFind = cacheEntry.getNestedFind();
+ nestedFieldIdentifierObj = cacheEntry.getNestedFieldIdentifierObj();
+ return this;
+ }
+
+ public CacheEntryBuilder withDbAction(DBAction dbAction) {
+ this.dbAction = dbAction;
+ return this;
+ }
+
+ public CacheEntryBuilder withId(String id) {
+ this.id = id;
+ return this;
+ }
+
+ public CacheEntryBuilder inCollection(String collection) {
+ this.collection = collection;
+ return this;
+ }
+
+ public CacheEntryBuilder withPayload(JsonObject payload) {
+ this.payload = payload;
+ return this;
+ }
+
+ public CacheEntryBuilder withFindQuery(JsonObject findQuery) {
+ this.findQuery = findQuery;
+ return this;
+ }
+
+ public CacheEntryBuilder isNested(boolean isNested) {
+ this.isNested = isNested;
+ return this;
+ }
+
+ public CacheEntryBuilder withNestedField(String nestedField) {
+ this.nestedField = nestedField;
+ return this;
+ }
+
+ public CacheEntryBuilder withNestedFind(JsonObject nestedFind) {
+ this.nestedFind = nestedFind;
+ return this;
+ }
+
+ public CacheEntryBuilder withNestedFieldIdentifierObj(JsonObject nestedFieldIdentifierObj) {
+ this.nestedFieldIdentifierObj = nestedFieldIdentifierObj;
+ return this;
+ }
+
+ public CacheEntry build() {
+ CacheEntry cacheEntry = new CacheEntry();
+ cacheEntry.setDbAction(dbAction);
+ cacheEntry.setId(id);
+ cacheEntry.setCollection(collection);
+ cacheEntry.setPayload(payload);
+ cacheEntry.setFindQuery(findQuery);
+ cacheEntry.setNestedField(nestedField);
+ cacheEntry.setNestedFind(nestedFind);
+ cacheEntry.setNestedFieldIdentifierObj(nestedFieldIdentifierObj);
+ cacheEntry.isNested = this.isNested;
+ return cacheEntry;
+ }
+ }
+}
diff --git a/src/main/java/org/onap/aai/cacher/model/CacheKey.java b/src/main/java/org/onap/aai/cacher/model/CacheKey.java
new file mode 100644
index 0000000..e87f34a
--- /dev/null
+++ b/src/main/java/org/onap/aai/cacher/model/CacheKey.java
@@ -0,0 +1,220 @@
+/**
+ * ============LICENSE_START=======================================================
+ * org.onap.aai
+ * ================================================================================
+ * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.aai.cacher.model;
+
+import com.google.gson.Gson;
+import com.google.gson.JsonObject;
+import com.mongodb.BasicDBObject;
+
+public class CacheKey {
+
+ public static final String DEFAULT_VALUE = "-1";
+
+ public String cacheKey = DEFAULT_VALUE;
+ public String baseUrl = DEFAULT_VALUE;
+ public String module = DEFAULT_VALUE;
+ public String URI = DEFAULT_VALUE;
+ public String timingIndicator = DEFAULT_VALUE;
+
+ public String syncInterval = DEFAULT_VALUE;
+ public String lastSyncStartTime = DEFAULT_VALUE;
+ public String lastSyncSuccessTime = DEFAULT_VALUE;
+ public String lastSyncEndTime = DEFAULT_VALUE;
+ public String httpBody = DEFAULT_VALUE;
+ public String httpMethod = DEFAULT_VALUE;
+
+ public String parserStrategy = "none";
+
+ public CacheKey(String cacheKey) {
+ this.cacheKey = cacheKey;
+ }
+
+ public static CacheKey createCacheKeyDefault(JsonObject payload) {
+ Gson gson = new Gson();
+ CacheKey cacheKey = gson.fromJson(payload.toString(), CacheKey.class);
+
+ if (cacheKey.cacheKey == null) {
+ cacheKey.cacheKey = DEFAULT_VALUE;
+ if (payload.has("_id")) {
+ cacheKey.cacheKey = payload.get("_id").getAsString();
+ }
+ }
+ if (cacheKey.baseUrl == null) {
+ cacheKey.baseUrl = DEFAULT_VALUE;
+ }
+ if (cacheKey.module == null) {
+ cacheKey.module = DEFAULT_VALUE;
+ }
+ if (cacheKey.URI == null) {
+ cacheKey.URI = DEFAULT_VALUE;
+ }
+ if (cacheKey.syncInterval == null) {
+ cacheKey.syncInterval = DEFAULT_VALUE;
+ }
+ if (cacheKey.lastSyncStartTime == null) {
+ cacheKey.lastSyncStartTime = DEFAULT_VALUE;
+ }
+ if (cacheKey.lastSyncSuccessTime == null) {
+ cacheKey.lastSyncSuccessTime = DEFAULT_VALUE;
+ }
+ if (cacheKey.lastSyncEndTime == null) {
+ cacheKey.lastSyncEndTime = DEFAULT_VALUE;
+ }
+ if (cacheKey.httpBody == null) {
+ cacheKey.httpBody = DEFAULT_VALUE;
+ }
+ if (cacheKey.parserStrategy == null) {
+ cacheKey.parserStrategy = DEFAULT_VALUE;
+ }
+ if (cacheKey.timingIndicator == null) {
+ cacheKey.timingIndicator = DEFAULT_VALUE;
+ }
+ if (cacheKey.httpMethod == null) {
+ cacheKey.httpMethod = DEFAULT_VALUE;
+ }
+ return cacheKey;
+ }
+
+ public static CacheKey fromJson(JsonObject payload) {
+ CacheKey cacheKey = createCacheKeyDefault(payload);
+ if (DEFAULT_VALUE.equals(cacheKey.parserStrategy)) {
+ cacheKey.parserStrategy = "none";
+ }
+ if (DEFAULT_VALUE.equals(cacheKey.timingIndicator)) {
+ cacheKey.timingIndicator = "firstHit";
+ } else if (cacheKey.getTimingIndicator().equals("scheduled") && DEFAULT_VALUE.equals(cacheKey.syncInterval)) {
+ cacheKey.syncInterval = "1440";
+ }
+ if (DEFAULT_VALUE.equals(cacheKey.httpMethod)) {
+ cacheKey.httpMethod = "GET";
+ }
+ return cacheKey;
+ }
+
+ public BasicDBObject toDBObject() {
+ BasicDBObject document = new BasicDBObject();
+ document.put("_id", this.cacheKey);
+ document.put("baseUrl", this.baseUrl);
+ document.put("module", this.module);
+ document.put("URI", this.URI);
+ document.put("timingIndicator", this.timingIndicator);
+ document.put("syncInterval", this.syncInterval);
+ document.put("lastSyncStartTime", this.lastSyncStartTime);
+ document.put("lastSyncSuccessTime", this.lastSyncSuccessTime);
+ document.put("lastSyncEndTime", this.lastSyncEndTime);
+ document.put("httpBody", this.httpBody);
+ document.put("httpMethod", this.httpMethod);
+ document.put("parserStrategy", parserStrategy);
+ return document;
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder();
+
+ sb.append("cacheKey: " + cacheKey + "\n");
+ sb.append("Base URL: " + baseUrl + "\n");
+ sb.append("Module: " + module + "\n");
+ sb.append("URI: " + URI + "\n");
+ sb.append("timingIndicator: " + timingIndicator + "\n");
+ sb.append("syncInterval: " + syncInterval + "\n");
+ sb.append("lastSyncStartTime: " + lastSyncStartTime + "\n");
+ sb.append("lastSyncSuccessTime: " + lastSyncSuccessTime + "\n");
+ sb.append("lastSyncEndTime: " + lastSyncEndTime + "\n");
+ sb.append("httpMethod: " + httpMethod + "\n");
+ sb.append("httpBody: " + httpBody + "\n");
+ sb.append("parserStrategy: " + parserStrategy + "\n");
+
+ return sb.toString();
+ }
+
+ public String getCacheKey() {
+ return cacheKey;
+ }
+
+ public void setCacheKey(String cacheKey) {
+ this.cacheKey = cacheKey;
+ }
+
+ public String getBaseUrl() {
+ return baseUrl;
+ }
+
+ public String getModule() {
+ return module;
+ }
+
+ public String getURI() {
+ return URI;
+ }
+
+ public String getTimingIndicator() {
+ return timingIndicator;
+ }
+
+ public String getSyncInterval() {
+ return syncInterval;
+ }
+
+ public void setSyncInterval(String syncInterval) {
+ this.syncInterval = syncInterval;
+ }
+
+ public String getLastSyncStartTime() {
+ return lastSyncStartTime;
+ }
+
+ public void setLastSyncStartTime(String ls) {
+ this.lastSyncStartTime = ls;
+ }
+
+ public String getLastSyncSuccessTime() {
+ return lastSyncSuccessTime;
+ }
+
+ public void setLastSyncSuccessTime(String ls) {
+ this.lastSyncSuccessTime = ls;
+ }
+
+ public String getLastSyncEndTime() {
+ return lastSyncEndTime;
+ }
+
+ public void setLastSyncEndTime(String le) {
+ this.lastSyncEndTime = le;
+ }
+
+ public String getHttpBody() {
+ return httpBody;
+ }
+
+ public String getHttpMethod() {
+ return httpMethod;
+ }
+
+ public String getParserStrategy() {
+ return parserStrategy;
+ }
+
+ public void setParserStrategy(String parserStrategy) {
+ this.parserStrategy = parserStrategy;
+ }
+
+} \ No newline at end of file
diff --git a/src/main/java/org/onap/aai/cacher/model/DBAction.java b/src/main/java/org/onap/aai/cacher/model/DBAction.java
new file mode 100644
index 0000000..0d7fbd5
--- /dev/null
+++ b/src/main/java/org/onap/aai/cacher/model/DBAction.java
@@ -0,0 +1,24 @@
+/**
+ * ============LICENSE_START=======================================================
+ * org.onap.aai
+ * ================================================================================
+ * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.aai.cacher.model;
+
+public enum DBAction {
+ DELETE, INSERT_REPLACE, UPDATE
+}
diff --git a/src/main/java/org/onap/aai/cacher/service/AuthorizationService.java b/src/main/java/org/onap/aai/cacher/service/AuthorizationService.java
new file mode 100644
index 0000000..369503a
--- /dev/null
+++ b/src/main/java/org/onap/aai/cacher/service/AuthorizationService.java
@@ -0,0 +1,109 @@
+/**
+ * ============LICENSE_START=======================================================
+ * org.onap.aai
+ * ================================================================================
+ * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.aai.cacher.service;
+
+import com.att.eelf.configuration.EELFLogger;
+import com.att.eelf.configuration.EELFManager;
+import org.eclipse.jetty.util.security.Password;
+import org.onap.aai.cacher.Profiles;
+import org.onap.aai.util.AAIConstants;
+import org.springframework.context.annotation.Profile;
+import org.springframework.stereotype.Service;
+
+import javax.annotation.PostConstruct;
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.util.Base64;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.stream.Stream;
+
+@Profile(Profiles.ONE_WAY_SSL)
+@Service
+public class AuthorizationService {
+
+ private static final EELFLogger logger = EELFManager.getInstance().getLogger(AuthorizationService.class);
+
+ private final Map<String, String> authorizedUsers = new HashMap<>();
+
+ private static final Base64.Encoder ENCODER = Base64.getEncoder();
+
+ @PostConstruct
+ public void init(){
+
+ String basicAuthFile = getBasicAuthFilePath();
+
+ try(Stream<String> stream = Files.lines(Paths.get(basicAuthFile))){
+ stream.filter(line -> !line.startsWith("#")).forEach(str -> {
+ byte [] bytes = null;
+
+ String usernamePassword = null;
+ String accessType = null;
+
+ try {
+ 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");
+ }
+
+ usernamePassword = userAccessType[0];
+ accessType = userAccessType[1];
+
+ String[] usernamePasswordArray = usernamePassword.split(":");
+
+ if(usernamePasswordArray == null || usernamePasswordArray.length != 3){
+ throw new RuntimeException("Not a valid entry for the realm.properties entry: " + usernamePassword);
+ }
+
+ String username = usernamePasswordArray[0];
+ String password = null;
+
+ if(str.contains("OBF:")){
+ password = usernamePasswordArray[1] + ":" + usernamePasswordArray[2];
+ password = Password.deobfuscate(password);
+ }
+
+ bytes = ENCODER.encode((username + ":" + password).getBytes("UTF-8"));
+
+ authorizedUsers.put(new String(bytes), accessType);
+
+ } catch (UnsupportedEncodingException e)
+ {
+ logger.error("Unable to support the encoding of the file" + basicAuthFile);
+ }
+
+ authorizedUsers.put(new String(ENCODER.encode(bytes)), accessType);
+ });
+ } catch (IOException e) {
+ logger.error("IO Exception occurred during the reading of realm.properties", e);
+ }
+ }
+
+ public boolean checkIfUserAuthorized(String authorization){
+ return authorizedUsers.containsKey(authorization) && "admin".equals(authorizedUsers.get(authorization));
+ }
+
+ public String getBasicAuthFilePath(){
+ return AAIConstants.AAI_HOME_ETC_AUTH + AAIConstants.AAI_FILESEP + "realm.properties";
+ }
+}
diff --git a/src/main/java/org/onap/aai/cacher/service/helper/CacheHelperService.java b/src/main/java/org/onap/aai/cacher/service/helper/CacheHelperService.java
new file mode 100644
index 0000000..8b85174
--- /dev/null
+++ b/src/main/java/org/onap/aai/cacher/service/helper/CacheHelperService.java
@@ -0,0 +1,545 @@
+/**
+ * ============LICENSE_START=======================================================
+ * org.onap.aai
+ * ================================================================================
+ * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.aai.cacher.service.helper;
+
+import com.att.eelf.configuration.EELFLogger;
+import com.att.eelf.configuration.EELFManager;
+import com.google.common.collect.Lists;
+import com.google.gson.*;
+import com.mongodb.*;
+import org.onap.aai.cacher.common.MongoHelperSingleton;
+import org.onap.aai.cacher.egestion.printer.PayloadPrinterService;
+import org.onap.aai.cacher.injestion.parser.PayloadParserService;
+import org.onap.aai.cacher.model.CacheEntry;
+import org.onap.aai.cacher.model.CacheKey;
+import org.onap.aai.cacher.util.AAIConstants;
+import org.onap.aai.exceptions.AAIException;
+import org.onap.aai.logging.ErrorLogHelper;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.ResponseEntity;
+import org.springframework.stereotype.Service;
+
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.Response.Status;
+import java.lang.reflect.Field;
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+
+@Service
+public class CacheHelperService {
+
+ private final static EELFLogger EELF_LOGGER = EELFManager.getInstance().getLogger(CacheHelperService.class);
+ private Gson gson = new GsonBuilder().create();
+
+ @Autowired
+ private MongoHelperSingleton mongoHelper;
+
+ @Autowired
+ private RestClientHelperService rchs;
+
+ @Autowired
+ private PayloadParserService payloadParserService;
+
+ @Autowired
+ private PayloadPrinterService payloadPrinterService;
+
+ public void setMongoHelper(MongoHelperSingleton mongoHelper) {
+ this.mongoHelper = mongoHelper;
+ }
+
+ public void setRchs(RestClientHelperService rchs) {
+ this.rchs = rchs;
+ }
+
+ public void setPayloadParserService(PayloadParserService payloadParserService) {
+ this.payloadParserService = payloadParserService;
+ }
+
+ public void setPayloadPrinterService(PayloadPrinterService payloadPrinterService) {
+ this.payloadPrinterService = payloadPrinterService;
+ }
+
+ public CacheKey retrieveCacheKeyObject(CacheKey ck) {
+ String ckString = retrieveCollectionString(ck, AAIConstants.COLLECTION_CACHEKEY);
+ if (ckString.equals("")) {
+ EELF_LOGGER.error("Could not retrieve cache key");
+ return null;
+ }
+ JsonParser parser = new JsonParser();
+ JsonObject ckJson = (JsonObject) parser.parse(ckString);
+ return CacheKey.fromJson(ckJson);
+ }
+
+ public String retrieveCollectionString(CacheKey ck, String collectionName) {
+ StringBuilder result = new StringBuilder("");
+ try {
+ DBCollection collection = mongoHelper.getDb().getCollection(collectionName);
+ BasicDBObject whereQuery = new BasicDBObject();
+ whereQuery.put("_id", ck.getCacheKey());
+ DBCursor cursor = collection.find(whereQuery);
+ while (cursor.hasNext()) {
+ result.append(cursor.next());
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ ErrorLogHelper.logException(new AAIException("AAI_4000", e));
+ }
+ return result.toString();
+ }
+
+ public boolean isCollectionPresent(String collectionName) {
+ if (collectionName != null && !collectionName.isEmpty()) {
+ try {
+ DBCollection collection = mongoHelper.getDb().getCollection(collectionName);
+ DBCursor cursor = collection.find();
+ if (cursor.count() > 0) {
+ return true;
+ }
+ } catch (Exception e) {
+ ErrorLogHelper.logException(new AAIException("AAI_4000", e));
+ }
+ }
+ return false;
+ }
+
+ public String retrieveCollectionString(CacheKey ck) {
+ JsonArray jsonArray = new JsonArray();
+ try {
+ DBCollection collection = mongoHelper.getDb().getCollection(ck.getCacheKey());
+ DBCursor cursor = collection.find();
+ if (cursor.count() > 0) {
+ while (cursor.hasNext()) {
+ // remove "_id" property from cache response
+ JsonParser parser = new JsonParser();
+ JsonObject jsonObj = (JsonObject) parser.parse(cursor.next().toString());
+ jsonObj.remove("_id");
+ jsonArray.add(jsonObj);
+ }
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ ErrorLogHelper.logException(new AAIException("AAI_4000", e));
+ }
+ JsonObject jsonObject = payloadPrinterService.createJson(ck.getCacheKey(), jsonArray, ck.getParserStrategy());
+ if (jsonObject != null) {
+ return jsonObject.toString();
+ }
+ return "";
+ }
+
+ public boolean isKeyPresent(CacheKey ck, String collectionName) {
+ return !retrieveCollectionString(ck, collectionName).equals("");
+ }
+
+ public boolean isCurrentlyRunning(CacheKey ck) {
+ CacheKey ckPopulated = retrieveCacheKeyObject(ck);
+ SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-ddHH:mm:ss.SSSZ");
+ Long syncStartTimeInMillis = -1L;
+ Long syncLastEndInMillis = -1L;
+ if (ckPopulated != null && !ckPopulated.getLastSyncStartTime().equals("-1")) {
+ try {
+ syncStartTimeInMillis = sdf.parse(ckPopulated.getLastSyncStartTime()).getTime();
+ } catch (Exception e) {
+ // TODO handle exceptions
+ }
+ }
+ if (ckPopulated != null && !ckPopulated.getLastSyncEndTime().equals("-1")) {
+ try {
+ syncLastEndInMillis = sdf.parse(ckPopulated.getLastSyncEndTime()).getTime();
+ } catch (Exception e) {
+ // TODO handle exceptions
+ }
+ }
+ return ckPopulated != null && syncLastEndInMillis < syncStartTimeInMillis;
+ }
+
+ public Response getData(CacheKey ck) {
+ if (ck == null) {
+ AAIException aaiException = new AAIException("AAI_3014", "Cache key provided does not exist");
+ return buildExceptionResponse(aaiException);
+ } else if (isCurrentlyRunning(ck)) {
+ AAIException aaiException = new AAIException("AAI_4000", "Sync is currently running from another process.");
+ return buildExceptionResponse(aaiException);
+ } else if (isKeyPresent(ck, AAIConstants.COLLECTION_CACHEKEY)) {
+ if (isCollectionPresent(ck.getCacheKey())) {
+ return retrieveCollectionByKey(ck);
+ } else {
+ ResponseEntity resp = rchs.triggerRestCall(ck);
+ if (!resp.getStatusCode().is2xxSuccessful()) {
+ // TODO log/return accordingly
+ }
+ Response response = populateCache(ck, (String) resp.getBody());
+ if (response.getStatus() == 201) {
+ return retrieveCollectionByKey(ck);
+ } else {
+ AAIException aaiException = new AAIException("AAI_5105");
+ return buildExceptionResponse(aaiException);
+ }
+ }
+ } else {
+ AAIException aaiException = new AAIException("AAI_3014", "Cache key provided does not exist");
+ return buildExceptionResponse(aaiException);
+ }
+ }
+
+ public Response forceSync(CacheKey ck) {
+ if (isCurrentlyRunning(ck)) {
+ AAIException aaiException = new AAIException("AAI_4000", "Sync is currently running from another process.");
+ return buildExceptionResponse(aaiException);
+ } else if (isKeyPresent(ck, AAIConstants.COLLECTION_CACHEKEY)) {
+ // populate cache and return status on sync
+ ResponseEntity resp = rchs.triggerRestCall(ck);
+ if (!resp.getStatusCode().is2xxSuccessful()) {
+ // TODO unsure if this is correct behavior
+ return Response.noContent().build();
+ }
+ return populateCache(ck, (String) resp.getBody());
+ } else {
+ AAIException aaiException = new AAIException("AAI_3014", "Cache key provided does not exist");
+ return buildExceptionResponse(aaiException);
+ }
+ }
+
+ public Response retrieveCollectionByKey(CacheKey ck, String collection) {
+ Status status = Status.OK;
+ String result = "";
+ try {
+ result = this.retrieveCollectionString(ck, collection);
+
+ if (result.equals("")) {
+ status = Status.NOT_FOUND;
+ EELF_LOGGER.error("Cannot not found the cache key from mongodb");
+ }
+ return this.buildResponse(status, result);
+ } catch (Exception e) {
+ AAIException aaiException = new AAIException("AAI_4000", e);
+ return buildExceptionResponse(aaiException);
+
+ }
+ }
+
+ public Response retrieveCollectionByKey(CacheKey ck) {
+ Status status = Status.OK;
+ String result = "";
+ try {
+ result = this.retrieveCollectionString(ck);
+ if (result.equals("")) {
+ status = Status.NOT_FOUND;
+ EELF_LOGGER.error("Cannot not found the cache key from mongodb");
+ }
+ return this.buildResponse(status, result);
+ } catch (Exception e) {
+ AAIException aaiException = new AAIException("AAI_4000", e);
+ return buildExceptionResponse(aaiException);
+
+ }
+ }
+
+ public boolean addCacheKey(CacheKey ck) {
+ return mongoHelper.addToMongo(AAIConstants.COLLECTION_CACHEKEY, ck.toDBObject());
+ }
+
+ public Response getAllKeys() {
+ Status status = Status.OK;
+ StringBuilder result = new StringBuilder();
+ try {
+ DBCollection collection = mongoHelper.getDb().getCollection(AAIConstants.COLLECTION_CACHEKEY);
+ DBCursor cursor = collection.find();
+ if (cursor.count() > 1) {
+ result.append("[");
+ while (cursor.hasNext()) {
+ result.append(cursor.next());
+ if (cursor.numSeen() != cursor.count()) {
+ result.append(",");
+ }
+ }
+ result.append("]");
+
+ } else if (cursor.count() == 1) {
+ while (cursor.hasNext()) {
+ result.append(cursor.next());
+ }
+ } else {
+ status = Status.NOT_FOUND;
+ }
+ return buildResponse(status, result.toString());
+ } catch (Exception e) {
+ AAIException aaiException = new AAIException("AAI_4000", e);
+ return buildExceptionResponse(aaiException);
+ }
+ }
+
+ public Response updateCacheKey(CacheKey ck) {
+ DBCollection collection = mongoHelper.getDb().getCollection(AAIConstants.COLLECTION_CACHEKEY);
+ Status status;
+
+ BasicDBObject updateFields = new BasicDBObject();
+
+ for (Field field : ck.getClass().getDeclaredFields()) {
+ try {
+ String name = field.getName();
+ Object value = field.get(ck);
+ if (!name.equals(AAIConstants.COLLECTION_CACHEKEY) && !value.equals("-1")) {
+ updateFields.append(name, value);
+ }
+ } catch (Exception e) {
+ EELF_LOGGER.warn("Could not retrieve updatable field from the class", e);
+ }
+ }
+
+ BasicDBObject setQuery = new BasicDBObject();
+ setQuery.append("$set", updateFields);
+
+ BasicDBObject searchQuery = new BasicDBObject("_id", ck.getCacheKey());
+ try {
+ WriteResult result = collection.update(searchQuery, setQuery);
+ if (result.getN() > 0) {
+ status = Status.OK;
+ } else {
+ // TODO set proper status for no results updated meaning it didn't find the key
+ status = Status.NOT_FOUND;
+ }
+ return buildResponse(status, "{}");
+ } catch (MongoException ex) {
+ AAIException aaiException = new AAIException("AAI_5105", ex);
+ return buildExceptionResponse(aaiException);
+ }
+ }
+
+ public boolean bulkAddCacheKeys(List<CacheKey> ckList) {
+ try {
+ List<BasicDBObject> documents = new ArrayList<BasicDBObject>();
+ for (CacheKey ck : ckList) {
+ documents.add(ck.toDBObject());
+ }
+ return mongoHelper.addToMongo(AAIConstants.COLLECTION_CACHEKEY, documents);
+ } catch (Exception e) {
+ AAIException aaiException = new AAIException("AAI_4000", e);
+ ErrorLogHelper.logException(aaiException);
+ return false;
+ }
+ }
+
+ public Response deleteCacheKeyAndAssociatedCache(String id) {
+ String cacheDelete = deleteFromCollection(null, id);
+ dropCollection(id);
+ String cacheKeyDelete = deleteFromCollection(id, AAIConstants.COLLECTION_CACHEKEY);
+ Status status;
+ if (cacheKeyDelete.equals("DELETED") && (cacheDelete.equals("DELETED") || cacheDelete.equals("NOT_FOUND"))) {
+ status = Status.NO_CONTENT;
+ return buildResponse(status, "{}");
+ } else if (cacheKeyDelete.equals("NOT_FOUND")) {
+ status = Status.NOT_FOUND;
+ return buildResponse(status, "{}");
+ } else {
+ AAIException aaiException = new AAIException("AAI_5105");
+ return buildExceptionResponse(aaiException);
+ }
+ }
+
+ public Response deleteCache(String id, String collection) {
+ String cacheDelete = deleteFromCollection(id, collection);
+ Status status;
+ if (cacheDelete.equals("DELETED")) {
+ status = Status.NO_CONTENT;
+ return buildResponse(status, "{}");
+ } else if (cacheDelete.equals("NOT_FOUND")) {
+ status = Status.NOT_FOUND;
+ return buildResponse(status, "{}");
+ } else {
+ AAIException aaiException = new AAIException("AAI_5105");
+ return buildExceptionResponse(aaiException);
+ }
+ }
+
+ public String deleteFromCollection(String id, String collection) {
+ Map<String, String> whereClause = new HashMap<>();
+ if (id != null) {
+ whereClause.put("_id", id);
+ }
+ return mongoHelper.deleteFromMongo(collection, whereClause);
+ }
+
+ public void dropCollection(String collection) {
+ mongoHelper.dropCollection(collection);
+ }
+
+ public Response populateCache(CacheKey ck, String responseBody) {
+ // Check to see if the cache key object is fully populated or an empty
+ // identifier object
+ // if it's an empty identifier object pull the entire object
+ if (ck.getBaseUrl().equals("-1")) {
+ ck = retrieveCacheKeyObject(ck);
+ }
+ DateFormat formatter = new SimpleDateFormat("yyyy-MM-ddHH:mm:ss.SSSZ");
+
+ List<CacheEntry> cacheEntries = payloadParserService.doParse(ck.getCacheKey(), responseBody,
+ ck.getParserStrategy());
+ for (CacheEntry cacheEntry : cacheEntries) {
+ boolean success = false;
+
+ switch (cacheEntry.getDbAction()) {
+ case DELETE:
+ success = mongoHelper.delete(cacheEntry);
+ break;
+ case UPDATE:
+ success = mongoHelper.insertReplace(cacheEntry);
+ break;
+ case INSERT_REPLACE:
+ success = mongoHelper.insertReplace(cacheEntry);
+ break;
+ }
+
+ if (!success) {
+ ck.setLastSyncEndTime(formatter.format(System.currentTimeMillis()));
+ updateCacheKey(ck);
+ AAIException aaiException = new AAIException("AAI_4000", "Unable to populate the cache");
+ return buildExceptionResponse(aaiException);
+ }
+ }
+ ck.setLastSyncSuccessTime(formatter.format(System.currentTimeMillis()));
+ ck.setLastSyncEndTime(formatter.format(System.currentTimeMillis()));
+ updateCacheKey(ck);
+ return buildResponse(Status.CREATED, "{}");
+ }
+
+ public Response buildResponse(Status status, String result) {
+ return Response.status(status).type(MediaType.APPLICATION_JSON).entity(result).build();
+ }
+
+ public Response buildValidationResponse(List<String> issues) {
+ AAIException aaiException = new AAIException("AAI_3014");
+ ArrayList<String> templateVars = new ArrayList<>();
+
+ if (templateVars.isEmpty()) {
+ templateVars.add(issues.toString());
+ }
+ ErrorLogHelper.logException(aaiException);
+ return Response.status(aaiException.getErrorObject().getHTTPResponseCode())
+ .entity(ErrorLogHelper.getRESTAPIErrorResponseWithLogging(
+ Lists.newArrayList(MediaType.APPLICATION_JSON_TYPE), aaiException, templateVars))
+ .build();
+ }
+
+ public Response buildExceptionResponse(AAIException aaiException) {
+ ErrorLogHelper.logException(aaiException);
+ return Response.status(aaiException.getErrorObject().getHTTPResponseCode())
+ .entity(ErrorLogHelper.getRESTAPIErrorResponseWithLogging(
+ Lists.newArrayList(MediaType.APPLICATION_JSON_TYPE), aaiException, new ArrayList<>()))
+ .build();
+ }
+
+ public List<CacheKey> getScheduledCaches() {
+ List<CacheKey> cks = new ArrayList<>();
+ EELF_LOGGER.info("Retrieving scheduled cache keys");
+ DBCollection collection = mongoHelper.getDb().getCollection(AAIConstants.COLLECTION_CACHEKEY);
+ BasicDBObject whereQuery = new BasicDBObject();
+ whereQuery.put("timingIndicator", "scheduled");
+ DBCursor cursor = collection.find(whereQuery);
+ while (cursor.hasNext()) {
+ JsonObject ckJson = (JsonObject) new JsonParser().parse((cursor.next().toString()));
+ CacheKey ck = CacheKey.fromJson(ckJson);
+ cks.add(ck);
+ }
+ return cks;
+ }
+
+ public void checkAndInitTasks() {
+ List<CacheKey> ckList = this.getScheduledCaches();
+ int numOfThread = 10;
+ ExecutorService taskExecutor = Executors.newFixedThreadPool(numOfThread);
+ try {
+ List<Callable<Void>> tasks = new ArrayList<>();
+ for (CacheKey ck : ckList) {
+
+ boolean shouldTrigger = isShouldTrigger(ck);
+
+ if (shouldTrigger) {
+ Callable<Void> task = new Callable<Void>() {
+ @Override
+ public Void call() throws Exception {
+ long startTimeV = System.currentTimeMillis();
+ ResponseEntity respEntity = rchs.triggerRestCall(ck);
+ if (respEntity.getStatusCode().is2xxSuccessful()) {
+ populateCache(ck, (String) respEntity.getBody());
+ long endTimeV = System.currentTimeMillis();
+ EELF_LOGGER.info("Elapsed time in seconds: " + (endTimeV - startTimeV) / 1000);
+ } else {
+ // TODO: cache update failed
+ }
+ return null;
+ }
+ };
+ if (task != null) {
+ tasks.add(task);
+ }
+ }
+ }
+ if (!tasks.isEmpty()) {
+ taskExecutor.invokeAll(tasks);
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ // TODO throw exception
+ } finally {
+ taskExecutor.shutdown();
+ }
+ }
+
+ protected boolean isShouldTrigger(CacheKey ck) {
+
+ // convert minutes to milliseconds for the interval
+ int interval = Integer.parseInt(ck.getSyncInterval()) * 60000;
+ SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-ddHH:mm:ss.SSSZ");
+ long syncStartTimeInMillis = Integer.MAX_VALUE;
+ long syncLastEndInMillis = Integer.MIN_VALUE;
+
+ if ("-1".equals(ck.getLastSyncStartTime())) {
+ return true;
+ } else {
+ try {
+ syncStartTimeInMillis = sdf.parse(ck.getLastSyncStartTime()).getTime();
+ } catch (Exception e) {
+ e.printStackTrace();
+ // TODO handle exceptions
+ }
+ }
+
+ if (!"-1".equals(ck.getLastSyncEndTime())) {
+ try {
+ syncLastEndInMillis = sdf.parse(ck.getLastSyncEndTime()).getTime();
+ } catch (Exception e) {
+ e.printStackTrace();
+ // TODO handle exceptions
+ }
+ }
+
+ return ((System.currentTimeMillis() - syncStartTimeInMillis) > interval)
+ && (syncStartTimeInMillis < syncLastEndInMillis);
+ }
+}
diff --git a/src/main/java/org/onap/aai/cacher/service/helper/RestClientHelperService.java b/src/main/java/org/onap/aai/cacher/service/helper/RestClientHelperService.java
new file mode 100644
index 0000000..b72101f
--- /dev/null
+++ b/src/main/java/org/onap/aai/cacher/service/helper/RestClientHelperService.java
@@ -0,0 +1,76 @@
+/**
+ * ============LICENSE_START=======================================================
+ * org.onap.aai
+ * ================================================================================
+ * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.aai.cacher.service.helper;
+
+import org.onap.aai.cacher.model.CacheKey;
+import org.onap.aai.cacher.util.RestClient;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.ResponseEntity;
+import org.springframework.stereotype.Component;
+
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+
+@Component
+public class RestClientHelperService {
+
+ @Autowired
+ CacheHelperService chs;
+
+ private RestClient restClient = getRestClient();
+
+ public RestClient getRestClient() {
+ try {
+ return new RestClient();
+ } catch (Exception e) {
+ // TODO handle exceptions
+ return null;
+ }
+ }
+
+ /**
+ * Given a cacheKey trigger its corresponding rest call
+ *
+ * @param ck
+ * @return ResponseEntity to process
+ */
+ public ResponseEntity triggerRestCall(CacheKey ck) {
+ // populated cacheKey with mongo variables
+ CacheKey ckPopulated = chs.retrieveCacheKeyObject(ck);
+ ResponseEntity resp = null;
+ // Check to see if the cache key object is fully populated or an empty
+ // identifier object
+ // if it's an empty identifier object pull the entire object
+ if ("-1".equals(ck.getBaseUrl())) {
+ ck = chs.retrieveCacheKeyObject(ck);
+ }
+ DateFormat formatter = new SimpleDateFormat("yyyy-MM-ddHH:mm:ss.SSSZ");
+ String dateFormatted = formatter.format(System.currentTimeMillis());
+ ck.setLastSyncStartTime(dateFormatted);
+ chs.updateCacheKey(ck);
+ try {
+ resp = this.restClient.get(ckPopulated.getBaseUrl(), ckPopulated.getModule(), ckPopulated.getURI(),
+ "AAI-CACHER");
+ } catch (Exception e) {
+ // TODO log an exception
+ }
+ return resp;
+ }
+}
diff --git a/src/main/java/org/onap/aai/cacher/service/rest/CacheInteractionService.java b/src/main/java/org/onap/aai/cacher/service/rest/CacheInteractionService.java
new file mode 100644
index 0000000..57bebdd
--- /dev/null
+++ b/src/main/java/org/onap/aai/cacher/service/rest/CacheInteractionService.java
@@ -0,0 +1,88 @@
+/**
+ * ============LICENSE_START=======================================================
+ * org.onap.aai
+ * ================================================================================
+ * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.aai.cacher.service.rest;
+
+import com.att.eelf.configuration.EELFLogger;
+import com.att.eelf.configuration.EELFManager;
+import com.google.gson.JsonParser;
+import org.onap.aai.cacher.model.CacheKey;
+import org.onap.aai.cacher.service.helper.CacheHelperService;
+import org.springframework.beans.factory.annotation.Autowired;
+
+import javax.ws.rs.*;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+
+@Path("/cache/v1")
+@Produces({ MediaType.APPLICATION_JSON })
+public class CacheInteractionService {
+
+ private final static EELFLogger EELF_LOGGER = EELFManager.getInstance().getLogger(CacheKeyService.class);
+
+ @Autowired
+ protected CacheHelperService chs;
+
+ /**
+ * Delete the associated cache and handle responses
+ *
+ * @param payload, requires the cache key to delete the cache
+ */
+ @DELETE
+ @Path("/delete")
+ @Consumes({ MediaType.APPLICATION_JSON })
+ @Produces({ MediaType.APPLICATION_JSON })
+ public Response executeDelete(String payload) {
+ CacheKey ck = CacheKey.fromJson(new JsonParser().parse(payload).getAsJsonObject());
+ Response resp = chs.deleteCache(null, ck.getCacheKey());
+ chs.dropCollection(ck.getCacheKey());
+ return resp;
+ }
+
+ /**
+ * Sync the cache from the provided cache key and handle responses
+ *
+ * @param payload, needs the cache key in the request payload to force sync the
+ * cache
+ */
+ @PUT
+ @Path("/sync")
+ @Consumes({ MediaType.APPLICATION_JSON })
+ @Produces({ MediaType.APPLICATION_JSON })
+ public Response executeSync(String payload) {
+ CacheKey ck = CacheKey.fromJson(new JsonParser().parse(payload).getAsJsonObject());
+ return chs.forceSync(ck);
+ }
+
+ /**
+ * Execute to build and return the payload for the provided cache key
+ *
+ * @param cacheKey, needs the cacheKey to know which response payload to build
+ * and return
+ */
+ @GET
+ @Path("/get")
+ @Consumes({ MediaType.APPLICATION_JSON })
+ @Produces({ MediaType.APPLICATION_JSON })
+ public Response executeGetSingle(@DefaultValue("-1") @QueryParam("cacheKey") String cacheKey) {
+ CacheKey ck = new CacheKey(cacheKey);
+ ck = chs.retrieveCacheKeyObject(ck);
+ return chs.getData(ck);
+ }
+} \ No newline at end of file
diff --git a/src/main/java/org/onap/aai/cacher/service/rest/CacheKeyService.java b/src/main/java/org/onap/aai/cacher/service/rest/CacheKeyService.java
new file mode 100644
index 0000000..962be77
--- /dev/null
+++ b/src/main/java/org/onap/aai/cacher/service/rest/CacheKeyService.java
@@ -0,0 +1,200 @@
+/**
+ * ============LICENSE_START=======================================================
+ * org.onap.aai
+ * ================================================================================
+ * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.aai.cacher.service.rest;
+
+import com.att.eelf.configuration.EELFLogger;
+import com.att.eelf.configuration.EELFManager;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonParser;
+import org.onap.aai.cacher.model.CacheKey;
+import org.onap.aai.cacher.service.helper.CacheHelperService;
+import org.onap.aai.cacher.service.rest.util.CacheKeyRequestValidation;
+import org.onap.aai.cacher.service.rest.util.CacheKeyRequestValidationType;
+import org.onap.aai.cacher.util.AAIConstants;
+import org.springframework.beans.factory.annotation.Autowired;
+
+import javax.ws.rs.*;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.Response.Status;
+import java.util.List;
+
+@Path("/cacheKey/v1")
+@Produces({ MediaType.APPLICATION_JSON })
+public class CacheKeyService {
+ private final static EELFLogger EELF_LOGGER = EELFManager.getInstance().getLogger(CacheKeyService.class);
+
+ @Autowired
+ protected CacheHelperService chs;
+
+ /**
+ * Store the cache key to Mongodb
+ *
+ * @param payload, the json payload needed to populate the cacheKey object and
+ * add to the database
+ */
+ @PUT
+ @Path("/add")
+ @Consumes({ MediaType.APPLICATION_JSON })
+ @Produces({ MediaType.APPLICATION_JSON })
+ public Response executeAdd(String payload) {
+ EELF_LOGGER.info("Got the request to add cache key to mongodb");
+ CacheKeyRequestValidation ckrv = new CacheKeyRequestValidation(CacheKeyRequestValidationType.ADD);
+ JsonObject input = convertStringToJSON(payload);
+ List<String> issues = ckrv.validateCacheKeyRequest(input, chs);
+ Response response;
+ if (!issues.isEmpty()) {
+ response = chs.buildValidationResponse(issues);
+ } else {
+ CacheKey ck = CacheKey.fromJson(convertStringToJSON(payload));
+ boolean addSuccessful = chs.addCacheKey(ck);
+ // Since we are adding an onInit, we need to populate its cache
+ if (ck.getTimingIndicator().equals("onInit")) {
+ chs.forceSync(ck);
+ }
+ Status status;
+ if (addSuccessful) {
+ status = Status.CREATED;
+ } else {
+ EELF_LOGGER.error("Adding of cache key was not successfull");
+ status = Status.INTERNAL_SERVER_ERROR;
+ }
+ response = Response.status(status).type(MediaType.APPLICATION_JSON).build();
+ }
+ return response;
+ }
+
+ /**
+ * Update the stored cache key and handle responses
+ *
+ * @param payload, the json payload needed to populate the cacheKey object and
+ * update the entry in the database
+ */
+ @PUT
+ @Path("/update")
+ @Consumes({ MediaType.APPLICATION_JSON })
+ @Produces({ MediaType.APPLICATION_JSON })
+ public Response executeUpdate(String payload) {
+ EELF_LOGGER.info("Got the request to update cache key in mongodb");
+ CacheKeyRequestValidation ckrv = new CacheKeyRequestValidation(CacheKeyRequestValidationType.UPDATE);
+ JsonObject input = convertStringToJSON(payload);
+ List<String> issues = ckrv.validateCacheKeyRequest(input, chs);
+ Response response;
+ if (!issues.isEmpty()) {
+ response = chs.buildValidationResponse(issues);
+ } else {
+ CacheKey ck = CacheKey.createCacheKeyDefault(input);
+ response = chs.updateCacheKey(ck);
+ }
+ return response;
+ }
+
+ /**
+ * Delete the cache key and associated cache and handle responses
+ *
+ * @param payload, the json payload needed to delete the cacheKey entry in the
+ * database
+ */
+ @DELETE
+ @Path("/delete")
+ @Consumes({ MediaType.APPLICATION_JSON })
+ @Produces({ MediaType.APPLICATION_JSON })
+ public Response executeDelete(String payload) {
+ EELF_LOGGER.info("Got the request to delete cache key from mongodb");
+ CacheKeyRequestValidation ckrv = new CacheKeyRequestValidation(CacheKeyRequestValidationType.DELETE);
+ JsonObject input = convertStringToJSON(payload);
+ List<String> issues = ckrv.validateCacheKeyRequest(input, chs);
+ Response response;
+ if (!issues.isEmpty()) {
+ response = chs.buildValidationResponse(issues);
+ } else {
+ CacheKey ck = new CacheKey(getValueFromPayload(input, "cacheKey"));
+ response = chs.deleteCacheKeyAndAssociatedCache(ck.getCacheKey());
+ }
+ return response;
+ }
+
+ /**
+ * Get the cache key information given a provided cache key, or if no key is
+ * provided return all keys
+ *
+ * @param cacheKey, the string id to match against _id in mongodb as the unique
+ * cache key
+ */
+ @GET
+ @Path("/get")
+ @Consumes({ MediaType.APPLICATION_JSON })
+ @Produces({ MediaType.APPLICATION_JSON })
+ public Response executeGet(@DefaultValue("-1") @QueryParam("cacheKey") String cacheKey) {
+ /*
+ * Method to get a single cache key entry
+ */
+ EELF_LOGGER.info("Got the request to get cache key from mongodb");
+ CacheKey ck;
+ Response response;
+ if (cacheKey.equals("-1")) {
+ response = chs.getAllKeys();
+ } else {
+ ck = new CacheKey(cacheKey);
+ response = chs.retrieveCollectionByKey(ck, AAIConstants.COLLECTION_CACHEKEY);
+ }
+ return response;
+ }
+
+ /**
+ * This method accepts a string converts it into a JsonObject
+ *
+ * @param payload, the string payload to convert to a JsonObject
+ */
+ public JsonObject convertStringToJSON(String payload) {
+ JsonParser parser = new JsonParser();
+ return (JsonObject) parser.parse(payload);
+ }
+
+ /**
+ * This method accepts a string payload and extracts the cacheKey
+ *
+ * @param payload, the string payload to convert to a JsonObject
+ */
+ public String getValueFromPayload(String payload, String key) {
+ JsonObject payloadJSON = convertStringToJSON(payload);
+ if (payloadJSON.has(key)) {
+ return ((payloadJSON.get(key)).toString()).replaceAll("\"", "");
+ } else {
+ EELF_LOGGER.error("Could not extract cachekey from the payload");
+ return null;
+ }
+ }
+
+ /**
+ * This method accepts a JsonObject input and extracts the cacheKey
+ *
+ * @param input, the string payload to convert to a JsonObject
+ */
+ public String getValueFromPayload(JsonObject input, String key) {
+ if (input.has(key)) {
+ return ((input.get(key)).toString()).replaceAll("\"", "");
+ } else {
+ EELF_LOGGER.error("Could not extract cachekey from the payload");
+ return null;
+ }
+ }
+
+} \ No newline at end of file
diff --git a/src/main/java/org/onap/aai/cacher/service/rest/util/CacheKeyRequestValidation.java b/src/main/java/org/onap/aai/cacher/service/rest/util/CacheKeyRequestValidation.java
new file mode 100644
index 0000000..4df1921
--- /dev/null
+++ b/src/main/java/org/onap/aai/cacher/service/rest/util/CacheKeyRequestValidation.java
@@ -0,0 +1,66 @@
+/**
+ * ============LICENSE_START=======================================================
+ * org.onap.aai
+ * ================================================================================
+ * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.aai.cacher.service.rest.util;
+
+import com.google.gson.JsonObject;
+import org.onap.aai.cacher.model.CacheKey;
+import org.onap.aai.cacher.service.helper.CacheHelperService;
+import org.onap.aai.cacher.util.AAIConstants;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class CacheKeyRequestValidation {
+ private CacheKeyRequestValidationType type;
+
+ public CacheKeyRequestValidation(CacheKeyRequestValidationType type) {
+ this.type = type;
+ }
+
+ public List<String> validateCacheKeyRequest(JsonObject input, CacheHelperService chs) {
+ ArrayList<String> results = new ArrayList<>();
+ if (input == null) {
+ results.add("Unsupported CacheKey request format, empty payload.");
+ return results;
+ }
+ CacheKey cacheKey = CacheKey.fromJson(input);
+ if ("-1".equals(cacheKey.getCacheKey())) {
+ results.add("Unsupported CacheKey request format, unspecified cacheKey.");
+ return results;
+ }
+ if (type.equals(CacheKeyRequestValidationType.DELETE)) {
+ return results;
+ }
+
+ Boolean keyExists = chs.isKeyPresent(cacheKey, AAIConstants.COLLECTION_CACHEKEY);
+ if (type.equals(CacheKeyRequestValidationType.ADD)) {
+ if (keyExists) {
+ results.add("Invalid request to add cacheKey " + cacheKey.getCacheKey() + ", cacheKey exists.");
+ }
+ } else if (type.equals(CacheKeyRequestValidationType.UPDATE)) {
+ if (!keyExists) {
+ results.add(
+ "Invalid request to update cacheKey " + cacheKey.getCacheKey() + ", cacheKey does not exist.");
+ }
+ }
+ return results;
+ }
+
+} \ No newline at end of file
diff --git a/src/main/java/org/onap/aai/cacher/service/rest/util/CacheKeyRequestValidationType.java b/src/main/java/org/onap/aai/cacher/service/rest/util/CacheKeyRequestValidationType.java
new file mode 100644
index 0000000..932d246
--- /dev/null
+++ b/src/main/java/org/onap/aai/cacher/service/rest/util/CacheKeyRequestValidationType.java
@@ -0,0 +1,26 @@
+/**
+ * ============LICENSE_START=======================================================
+ * org.onap.aai
+ * ================================================================================
+ * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.aai.cacher.service.rest.util;
+
+public enum CacheKeyRequestValidationType {
+
+ ADD, UPDATE, DELETE;
+
+}
diff --git a/src/main/java/org/onap/aai/cacher/service/tasks/ScheduledTaskConfig.java b/src/main/java/org/onap/aai/cacher/service/tasks/ScheduledTaskConfig.java
new file mode 100644
index 0000000..2a9a403
--- /dev/null
+++ b/src/main/java/org/onap/aai/cacher/service/tasks/ScheduledTaskConfig.java
@@ -0,0 +1,74 @@
+/**
+ * ============LICENSE_START=======================================================
+ * org.onap.aai
+ * ================================================================================
+ * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.aai.cacher.service.tasks;
+
+import com.att.eelf.configuration.EELFLogger;
+import com.att.eelf.configuration.EELFManager;
+import org.onap.aai.cacher.service.helper.CacheHelperService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.scheduling.TaskScheduler;
+import org.springframework.scheduling.annotation.SchedulingConfigurer;
+import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
+import org.springframework.scheduling.config.IntervalTask;
+import org.springframework.scheduling.config.ScheduledTaskRegistrar;
+
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+@Configuration
+public class ScheduledTaskConfig {
+
+ private final static EELFLogger EELF_LOGGER = EELFManager.getInstance().getLogger(ScheduledTaskConfig.class);
+ private static final SimpleDateFormat dateFormat = new SimpleDateFormat("HH:mm:ss");
+ private final static int THREAD_POOL_SIZE = 10;
+ private final static String THREAD_POOL_PREFIX = "poolScheduler";
+ private final static int TASK_INTERVAL_TIME = 30000;
+ private final static int TASK_DELAY_TIME = 0;
+
+ @Configuration
+ static class RegisterTaskSchedulerViaSchedulingConfigurer implements SchedulingConfigurer {
+
+ @Autowired
+ protected CacheHelperService chs;
+
+ @Override
+ public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
+ taskRegistrar.setTaskScheduler(poolScheduler());
+ taskRegistrar.addFixedRateTask(new IntervalTask(new Runnable() {
+ @Override
+ public void run() {
+ EELF_LOGGER.info(
+ "Job @ fixed rate " + new Date() + ", Thread name is " + Thread.currentThread().getName());
+ chs.checkAndInitTasks();
+ }
+ }, TASK_INTERVAL_TIME, TASK_DELAY_TIME));
+ }
+
+ @Bean
+ public TaskScheduler poolScheduler() {
+ ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler();
+ scheduler.setThreadNamePrefix(THREAD_POOL_PREFIX);
+ scheduler.setPoolSize(THREAD_POOL_SIZE);
+ return scheduler;
+ }
+ }
+} \ No newline at end of file
diff --git a/src/main/java/org/onap/aai/cacher/service/tasks/ScheduledTasks.java b/src/main/java/org/onap/aai/cacher/service/tasks/ScheduledTasks.java
new file mode 100644
index 0000000..78c88c7
--- /dev/null
+++ b/src/main/java/org/onap/aai/cacher/service/tasks/ScheduledTasks.java
@@ -0,0 +1,148 @@
+/**
+ * ============LICENSE_START=======================================================
+ * org.onap.aai
+ * ================================================================================
+ * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.aai.cacher.service.tasks;
+
+import com.att.eelf.configuration.EELFLogger;
+import com.att.eelf.configuration.EELFManager;
+import org.onap.aai.cacher.common.CacheKeyConfig;
+import org.onap.aai.cacher.dmaap.consumer.AAIDmaapEventProcessor;
+import org.onap.aai.cacher.dmaap.consumer.AAIEventConsumer;
+import org.onap.aai.cacher.dmaap.consumer.DmaapConsumerSingleton;
+import org.onap.aai.cacher.model.CacheKey;
+import org.onap.aai.cacher.service.helper.CacheHelperService;
+import org.onap.aai.cacher.service.helper.RestClientHelperService;
+import org.onap.aai.cacher.util.AAIConstants;
+import org.onap.aai.exceptions.AAIException;
+import org.onap.aai.logging.ErrorLogHelper;
+import org.onap.aai.util.AAIConfig;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.ResponseEntity;
+import org.springframework.scheduling.annotation.Scheduled;
+import org.springframework.stereotype.Component;
+
+import javax.ws.rs.core.Response;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.List;
+
+@Component
+public class ScheduledTasks {
+ private final static EELFLogger LOGGER = EELFManager.getInstance().getLogger(ScheduledTasks.class);
+ private final SimpleDateFormat dateFormat = new SimpleDateFormat("HH:mm:ss");
+
+ private int checkInterval = -1;
+ private boolean cacheLoaded = false;
+
+ @Autowired
+ AAIDmaapEventProcessor aaiDmaapEventProcessor;
+
+ @Autowired
+ CacheHelperService chs;
+
+ @Autowired
+ RestClientHelperService rchs;
+
+ /**
+ * Starts the aaiDmaapEventConsumer task bean init. Will restart 1 min after the
+ * previous one ended.
+ */
+ @Scheduled(fixedDelay = 60000, initialDelay = 0)
+ public void dmaapAAIDmaapEventProcessor() {
+ try {
+ dmaapAAIEventProcessorTask();
+ } catch (Exception e) {
+ LOGGER.error("ERROR: Exception in scheduled task [" + e.getMessage() + "].");
+ ErrorLogHelper.logException(new AAIException("AAI_4000", e));
+ }
+ }
+
+ public void dmaapAAIEventProcessorTask() throws Exception {
+ String methodName = "dmaapAAIEventProcessorTask()";
+
+ LOGGER.info("Started fixed rate job dmaapAAIEventProcessor @ " + dateFormat.format(new Date()));
+ LOGGER.debug("started scheduled task for " + methodName + " checkInterval " + checkInterval);
+ try {
+ int delayCheck = Integer.parseInt(AAIConfig.get("aai.cacher.dmaap.consumer.delayCheck", "0"));
+ if (checkInterval > 0 && checkInterval++ < delayCheck) {
+ return;
+ }
+ checkInterval = 1;
+ if (AAIConfig.get("aai.cacher.dmaap.consumer.enableEventProcessing").equals("true")) {
+ LOGGER.info("aai.cacher.dmaap.consumer.enableEventProcessing set to true, starting AAIEventConsumer.");
+ AAIEventConsumer aec = new AAIEventConsumer("aaiDmaaPEventConsumer.properties", false);
+ aec.startProcessing(aaiDmaapEventProcessor);
+ } else {
+ LOGGER.info(
+ "aai.cacher.dmaap.consumer.enableEventProcessing set to false, not starting AAIDmaapEventConsumer.");
+ }
+ // initialize the cache
+ if (!cacheLoaded) {
+ LOGGER.info("Start loading cache @ " + dateFormat.format(new Date()));
+ init();
+ cacheLoaded = true;
+ }
+
+ } catch (Exception e) {
+ ErrorLogHelper.logException(new AAIException("AAI_4000", e));
+ }
+ LOGGER.info("Completed fixed rate job dmaapAAIEventProcessor @ " + dateFormat.format(new Date()));
+ }
+
+ public void init() throws IOException {
+
+ Path path = Paths.get(AAIConstants.INITIAL_CACHEKEY_CONFIG_FILENAME);
+ String cacheKeyConfigJson = new String(Files.readAllBytes(path));
+ CacheKeyConfig cacheKeyConfig = new CacheKeyConfig(cacheKeyConfigJson);
+ List<CacheKey> cacheKeys = cacheKeyConfig.populateCacheKeyList();
+ chs.bulkAddCacheKeys(cacheKeys);
+
+ for (CacheKey cacheKey : cacheKeys) {
+ if ("onInit".equalsIgnoreCase(cacheKey.getTimingIndicator())) {
+ try {
+ ResponseEntity respEntity = rchs.triggerRestCall(cacheKey);
+ if (respEntity.getStatusCode().is2xxSuccessful()) {
+ Response resp = chs.populateCache(cacheKey, (String) respEntity.getBody());
+ if (resp != null) {
+ if (resp.getStatus() == Response.Status.CREATED.getStatusCode()) {
+ LOGGER.debug("cacheKey " + cacheKey.getCacheKey() + " loaded");
+ } else {
+ LOGGER.error("unexpected 2xx response status for cacheKey " + cacheKey.getCacheKey()
+ + " " + resp.getStatusInfo());
+ }
+ }
+ } else {
+ LOGGER.error("unexpected response status for cacheKey " + cacheKey.getCacheKey() + " "
+ + respEntity.getStatusCode());
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ LOGGER.error("exception caught for cacheKey " + cacheKey.getCacheKey());
+ ErrorLogHelper.logException(new AAIException("AAI_4000", e));
+ }
+ }
+ }
+
+ DmaapConsumerSingleton.getInstance().setProcessEvents(true);
+ }
+}
diff --git a/src/main/java/org/onap/aai/cacher/util/AAIConstants.java b/src/main/java/org/onap/aai/cacher/util/AAIConstants.java
new file mode 100644
index 0000000..b830ecb
--- /dev/null
+++ b/src/main/java/org/onap/aai/cacher/util/AAIConstants.java
@@ -0,0 +1,51 @@
+/**
+ * ============LICENSE_START=======================================================
+ * org.onap.aai
+ * ================================================================================
+ * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.aai.cacher.util;
+
+public final class AAIConstants {
+ public static final String COLLECTION_CACHEKEY = "cacheKey";
+
+ /** Default to unix file separator if system property file.separator is null */
+ public static final String FILESEP = (System.getProperty("file.separator") == null) ? "/"
+ : System.getProperty("file.separator");
+
+ public static final String AAI_BUNDLECONFIG_NAME = (System.getProperty("BUNDLECONFIG_DIR") == null) ? "resources"
+ : System.getProperty("BUNDLECONFIG_DIR");
+ public static final String AAI_HOME_BUNDLECONFIG = (System.getProperty("AJSC_HOME") == null)
+ ? FILESEP + "opt" + FILESEP + "app" + FILESEP + "aai" + FILESEP + AAI_BUNDLECONFIG_NAME
+ : System.getProperty("AJSC_HOME") + FILESEP + AAI_BUNDLECONFIG_NAME;
+
+ public static final String AAI_HOME_ETC = AAI_HOME_BUNDLECONFIG + FILESEP + "etc" + FILESEP;
+ public static final String AAI_HOME_ETC_APP_PROPERTIES = AAI_HOME_ETC + "appprops" + FILESEP;
+ public static final String INITIAL_CACHEKEY_CONFIG_FILENAME = AAI_HOME_ETC_APP_PROPERTIES
+ + "initialcachekeyconfig.json";
+ public static final String AAI_RESOURCES_URI_TEMPLATES = AAI_HOME_ETC_APP_PROPERTIES
+ + "aai-resources-uri-templates.properties";
+ public static final String AAI_HOME_ETC_AUTH = AAI_HOME_ETC + "auth" + FILESEP;
+
+ public static final String AAI_TRUSTSTORE_FILENAME = "aai.truststore.filename";
+ public static final String AAI_TRUSTSTORE_PASSWD = "aai.truststore.passwd";
+ public static final String AAI_KEYSTORE_FILENAME = "aai.keystore.filename";
+ public static final String AAI_KEYSTORE_PASSWD = "aai.keystore.passwd";
+
+ private AAIConstants() {
+ // prevent instantiation
+ }
+}
diff --git a/src/main/java/org/onap/aai/cacher/util/RestClient.java b/src/main/java/org/onap/aai/cacher/util/RestClient.java
new file mode 100644
index 0000000..0caffd3
--- /dev/null
+++ b/src/main/java/org/onap/aai/cacher/util/RestClient.java
@@ -0,0 +1,157 @@
+/**
+ * ============LICENSE_START=======================================================
+ * org.onap.aai
+ * ================================================================================
+ * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.aai.cacher.util;
+
+import org.apache.commons.net.util.Base64;
+import org.apache.http.client.HttpClient;
+import org.apache.http.impl.client.HttpClients;
+import org.apache.http.ssl.SSLContextBuilder;
+import org.onap.aai.util.AAIConfig;
+import org.springframework.boot.web.client.RestTemplateBuilder;
+import org.springframework.context.annotation.Bean;
+import org.springframework.core.env.Environment;
+import org.springframework.http.*;
+import org.springframework.http.client.ClientHttpResponse;
+import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
+import org.springframework.util.ResourceUtils;
+import org.springframework.web.client.ResponseErrorHandler;
+import org.springframework.web.client.RestTemplate;
+
+import javax.net.ssl.SSLContext;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.charset.Charset;
+import java.security.KeyStore;
+import java.util.Collections;
+
+//@Component
+public class RestClient {
+
+ private HttpClient restClient = null;
+
+ private Environment environment;
+
+ public RestClient() {
+ this.restClient = initClient();
+ }
+
+ public HttpClient getRestClient() {
+ return restClient;
+ }
+
+ /**
+ * @return initialized rest client
+ *
+ */
+ private HttpClient initClient() {
+ HttpClient rc;
+
+ try {
+ String truststore_path = AAIConstants.AAI_HOME_ETC_AUTH
+ + AAIConfig.get(AAIConstants.AAI_TRUSTSTORE_FILENAME);
+ String truststore_password = AAIConfig.get(AAIConstants.AAI_TRUSTSTORE_PASSWD);
+ SSLContextBuilder sslContextBuilder = SSLContextBuilder.create();
+
+ SSLContext sslContext = sslContextBuilder
+ .loadTrustMaterial(ResourceUtils.getFile(truststore_path), truststore_password.toCharArray())
+ .build();
+
+ rc = HttpClients.custom().setSSLContext(sslContext).setSSLHostnameVerifier((s, sslSession) -> true).build();
+ } catch (Exception e) {
+ // TODO Handle exceptions/logging
+ rc = null;
+ }
+ return rc;
+ }
+
+ private String getAuth(String baseUrl ) {
+ int startIndex = baseUrl.indexOf("://") + "://".length();
+ int ampersandIndex = baseUrl.indexOf('@');
+ if ( ampersandIndex >= 0 ) {
+ return baseUrl.substring(startIndex, ampersandIndex);
+ }
+ return null;
+ }
+
+ public ResponseEntity get(String baseUrl, String module, String restUri, String sourceName) throws Exception {
+ ResponseEntity responseEntity = null;
+ try {
+
+ RestTemplate restTemplate = restTemplate(new RestTemplateBuilder());
+ String endpoint;
+ if (!module.equals("-1")) {
+ endpoint = module + restUri;
+ } else {
+ endpoint = restUri;
+ }
+ HttpHeaders headers = new HttpHeaders();
+ headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON));
+ headers.setContentType(MediaType.APPLICATION_JSON);
+ headers.add("X-FromAppId", "AAI-CACHER");
+ headers.add("X-TransactionId", "JUNIT");
+ String auth = getAuth(baseUrl);
+ String urlUpdate;
+ if ( auth != null ) {
+ byte[] encodedAuth = Base64.encodeBase64(auth.getBytes(Charset.forName("US-ASCII")));
+ headers.add("Authorization", "Basic " + new String(encodedAuth));
+ urlUpdate = baseUrl.replaceAll(auth + "@", "");
+ } else {
+ urlUpdate = baseUrl;
+ }
+ HttpEntity httpEntity = new HttpEntity(headers);
+ responseEntity = restTemplate.exchange(urlUpdate + endpoint, HttpMethod.GET, httpEntity, String.class);
+ } catch (Exception e) {
+ e.printStackTrace();
+ // TODO handle exceptions
+ }
+ return responseEntity;
+ }
+
+ @Bean
+ RestTemplate restTemplate(RestTemplateBuilder builder) throws Exception {
+ RestTemplate restTemplate = builder.requestFactory(new HttpComponentsClientHttpRequestFactory(restClient))
+ .build();
+
+ restTemplate.setErrorHandler(new ResponseErrorHandler() {
+ @Override
+ public boolean hasError(ClientHttpResponse clientHttpResponse) throws IOException {
+ return clientHttpResponse.getStatusCode() != HttpStatus.OK;
+ }
+
+ @Override
+ public void handleError(ClientHttpResponse clientHttpResponse) throws IOException {
+ // TODO handle the error
+ }
+ });
+
+ return restTemplate;
+ }
+
+ private KeyStore loadPfx(String file, char[] password) throws Exception {
+ KeyStore keyStore = KeyStore.getInstance("PKCS12");
+ File key = ResourceUtils.getFile(file);
+ try (InputStream in = new FileInputStream(key)) {
+ keyStore.load(in, password);
+ }
+ return keyStore;
+ }
+}
diff --git a/src/main/java/org/onap/aai/cacher/web/JerseyConfiguration.java b/src/main/java/org/onap/aai/cacher/web/JerseyConfiguration.java
new file mode 100644
index 0000000..6498f2f
--- /dev/null
+++ b/src/main/java/org/onap/aai/cacher/web/JerseyConfiguration.java
@@ -0,0 +1,132 @@
+/**
+ * ============LICENSE_START=======================================================
+ * org.onap.aai
+ * ================================================================================
+ * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.aai.cacher.web;
+
+import org.glassfish.jersey.filter.LoggingFilter;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.onap.aai.cacher.service.rest.CacheInteractionService;
+import org.onap.aai.cacher.service.rest.CacheKeyService;
+import org.reflections.Reflections;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Profile;
+import org.springframework.core.env.Environment;
+import org.springframework.stereotype.Component;
+
+import javax.annotation.Priority;
+import javax.ws.rs.ApplicationPath;
+import javax.ws.rs.container.ContainerRequestFilter;
+import javax.ws.rs.container.ContainerResponseFilter;
+
+import java.util.List;
+import java.util.Set;
+import java.util.logging.Logger;
+import java.util.stream.Collectors;
+
+@Component
+@ApplicationPath("/aai")
+public class JerseyConfiguration extends ResourceConfig {
+ private static final Logger log = Logger.getLogger(JerseyConfiguration.class.getName());
+
+ private Environment env;
+
+ @Autowired
+ public JerseyConfiguration(Environment env) {
+ this.env = env;
+ register(CacheKeyService.class);
+ register(CacheInteractionService.class);
+ property("jersey.config.servlet.filter.forwardOn404", true);
+ // Request Filters
+ registerFiltersForRequests();
+ // Response Filters
+ registerFiltersForResponses();
+
+ // Following registers the request headers and response headers
+ // If the LoggingFilter second argument is set to true, it will print response
+ // value as well
+ if ("true".equalsIgnoreCase(env.getProperty("aai.request.logging.enabled"))) {
+ register(new LoggingFilter(log, false));
+ }
+ }
+
+ public void registerFiltersForRequests() {
+
+ // Find all the classes within the interceptors package
+ Reflections reflections = new Reflections("org.onap.aai.interceptors");
+ // Filter them based on the clazz that was passed in
+ Set<Class<? extends ContainerRequestFilter>> filters = reflections.getSubTypesOf(ContainerRequestFilter.class);
+
+ // Check to ensure that each of the filter has the @Priority annotation and if
+ // not throw exception
+ for (Class filterClass : filters) {
+ if (filterClass.getAnnotation(Priority.class) == null) {
+ throw new RuntimeException(
+ "Container filter " + filterClass.getName() + " does not have @Priority annotation");
+ }
+ }
+
+ // Turn the set back into a list
+ List<Class<? extends ContainerRequestFilter>> filtersList = filters.stream().filter(f -> {
+ if (f.isAnnotationPresent(Profile.class) && !env.acceptsProfiles(f.getAnnotation(Profile.class).value())) {
+ return false;
+ }
+ return true;
+ }).collect(Collectors.toList());
+
+ // Sort them by their priority levels value
+ filtersList.sort((c1, c2) -> Integer.valueOf(c1.getAnnotation(Priority.class).value())
+ .compareTo(c2.getAnnotation(Priority.class).value()));
+
+ // Then register this to the jersey application
+ filtersList.forEach(this::register);
+ }
+
+ public void registerFiltersForResponses() {
+
+ // Find all the classes within the interceptors package
+ Reflections reflections = new Reflections("org.onap.aai.interceptors");
+ // Filter them based on the clazz that was passed in
+ Set<Class<? extends ContainerResponseFilter>> filters = reflections
+ .getSubTypesOf(ContainerResponseFilter.class);
+
+ // Check to ensure that each of the filter has the @Priority annotation and if
+ // not throw exception
+ for (Class filterClass : filters) {
+ if (filterClass.getAnnotation(Priority.class) == null) {
+ throw new RuntimeException(
+ "Container filter " + filterClass.getName() + " does not have @Priority annotation");
+ }
+ }
+
+ // Turn the set back into a list
+ List<Class<? extends ContainerResponseFilter>> filtersList = filters.stream().filter(f -> {
+ if (f.isAnnotationPresent(Profile.class) && !env.acceptsProfiles(f.getAnnotation(Profile.class).value())) {
+ return false;
+ }
+ return true;
+ }).collect(Collectors.toList());
+
+ // Sort them by their priority levels value
+ filtersList.sort((c1, c2) -> Integer.valueOf(c1.getAnnotation(Priority.class).value())
+ .compareTo(c2.getAnnotation(Priority.class).value()));
+
+ // Then register this to the jersey application
+ filtersList.forEach(this::register);
+ }
+} \ No newline at end of file
diff --git a/src/main/java/org/onap/aai/cacher/web/LocalHostAccessLog.java b/src/main/java/org/onap/aai/cacher/web/LocalHostAccessLog.java
new file mode 100644
index 0000000..81addb5
--- /dev/null
+++ b/src/main/java/org/onap/aai/cacher/web/LocalHostAccessLog.java
@@ -0,0 +1,58 @@
+/**
+ * ============LICENSE_START=======================================================
+ * org.onap.aai
+ * ================================================================================
+ * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.aai.cacher.web;
+
+import ch.qos.logback.access.jetty.RequestLogImpl;
+import org.eclipse.jetty.server.handler.HandlerCollection;
+import org.eclipse.jetty.server.handler.RequestLogHandler;
+import org.springframework.boot.context.embedded.EmbeddedServletContainerFactory;
+import org.springframework.boot.context.embedded.jetty.JettyEmbeddedServletContainerFactory;
+import org.springframework.boot.context.embedded.jetty.JettyServerCustomizer;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+import java.util.Arrays;
+
+@Configuration
+public class LocalHostAccessLog {
+
+ @Bean
+ public EmbeddedServletContainerFactory jettyConfigBean() {
+ JettyEmbeddedServletContainerFactory jef = new JettyEmbeddedServletContainerFactory();
+ jef.addServerCustomizers((JettyServerCustomizer) server -> {
+
+ HandlerCollection handlers = new HandlerCollection();
+
+ Arrays.stream(server.getHandlers()).forEach(handlers::addHandler);
+
+ RequestLogHandler requestLogHandler = new RequestLogHandler();
+ requestLogHandler.setServer(server);
+
+ RequestLogImpl requestLogImpl = new RequestLogImpl();
+ requestLogImpl.setResource("/localhost-access-logback.xml");
+ requestLogImpl.start();
+
+ requestLogHandler.setRequestLog(requestLogImpl);
+ handlers.addHandler(requestLogHandler);
+ server.setHandler(handlers);
+ });
+ return jef;
+ }
+}
diff --git a/src/main/java/org/onap/aai/interceptors/AAIContainerFilter.java b/src/main/java/org/onap/aai/interceptors/AAIContainerFilter.java
new file mode 100644
index 0000000..f1198ae
--- /dev/null
+++ b/src/main/java/org/onap/aai/interceptors/AAIContainerFilter.java
@@ -0,0 +1,41 @@
+/**
+ * ============LICENSE_START=======================================================
+ * org.onap.aai
+ * ================================================================================
+ * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.aai.interceptors;
+
+import org.onap.aai.util.FormatDate;
+
+import java.util.UUID;
+
+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/src/main/java/org/onap/aai/interceptors/AAIHeaderProperties.java b/src/main/java/org/onap/aai/interceptors/AAIHeaderProperties.java
new file mode 100644
index 0000000..65d16e8
--- /dev/null
+++ b/src/main/java/org/onap/aai/interceptors/AAIHeaderProperties.java
@@ -0,0 +1,40 @@
+/**
+ * ============LICENSE_START=======================================================
+ * org.onap.aai
+ * ================================================================================
+ * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * 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 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/src/main/java/org/onap/aai/interceptors/post/AAIResponseFilterPriority.java b/src/main/java/org/onap/aai/interceptors/post/AAIResponseFilterPriority.java
new file mode 100644
index 0000000..ea657bb
--- /dev/null
+++ b/src/main/java/org/onap/aai/interceptors/post/AAIResponseFilterPriority.java
@@ -0,0 +1,40 @@
+/**
+ * ============LICENSE_START=======================================================
+ * org.onap.aai
+ * ================================================================================
+ * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.aai.interceptors.post;
+
+/**
+ * Response Filter order is done reverse sorted so in the following case the
+ * first response filter would be HEADER_MANIPULATION, RESPONSE_TRANS_LOGGING,
+ * RESET_LOGGING_CONTEXT, and INVALID_RESPONSE_STATUS
+ */
+public final class AAIResponseFilterPriority {
+
+ private AAIResponseFilterPriority() {
+ }
+
+ public static final int INVALID_RESPONSE_STATUS = 1000;
+
+ public static final int RESET_LOGGING_CONTEXT = 2000;
+
+ public static final int RESPONSE_TRANS_LOGGING = 3000;
+
+ public static final int HEADER_MANIPULATION = 4000;
+
+}
diff --git a/src/main/java/org/onap/aai/interceptors/post/ResponseTransactionLogging.java b/src/main/java/org/onap/aai/interceptors/post/ResponseTransactionLogging.java
new file mode 100644
index 0000000..20fe32a
--- /dev/null
+++ b/src/main/java/org/onap/aai/interceptors/post/ResponseTransactionLogging.java
@@ -0,0 +1,118 @@
+/**
+ * ============LICENSE_START=======================================================
+ * org.onap.aai
+ * ================================================================================
+ * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.aai.interceptors.post;
+
+import com.att.eelf.configuration.EELFLogger;
+import com.att.eelf.configuration.EELFManager;
+import com.google.gson.JsonObject;
+import org.onap.aai.interceptors.AAIContainerFilter;
+import org.onap.aai.interceptors.AAIHeaderProperties;
+import org.onap.aai.logging.ErrorLogHelper;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.core.env.Environment;
+
+import javax.annotation.Priority;
+import javax.servlet.http.HttpServletResponse;
+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;
+
+@Priority(AAIResponseFilterPriority.RESPONSE_TRANS_LOGGING)
+public class ResponseTransactionLogging extends AAIContainerFilter implements ContainerResponseFilter {
+
+ private static final EELFLogger TRANSACTION_LOGGER = EELFManager.getInstance()
+ .getLogger(ResponseTransactionLogging.class);
+
+ @Autowired
+ private HttpServletResponse httpServletResponse;
+
+ @Autowired
+ private Environment env;
+
+ @Override
+ public void filter(ContainerRequestContext requestContext, ContainerResponseContext responseContext)
+ throws IOException {
+
+ this.transLogging(requestContext, responseContext);
+
+ }
+
+ private void transLogging(ContainerRequestContext requestContext, ContainerResponseContext responseContext) {
+
+ String logValue = env.getProperty("aai.transaction.logging");
+ String getValue = env.getProperty("aai.transaction.logging.get");
+ String postValue = env.getProperty("aai.transaction.logging.post");
+
+ 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 httpMethod = requestContext.getMethod();
+
+ String status = Integer.toString(responseContext.getStatus());
+
+ String request = (String) requestContext.getProperty(AAIHeaderProperties.AAI_REQUEST);
+ String response = this.getResponseString(responseContext);
+
+ if (!Boolean.parseBoolean(logValue)) {
+ } else if (!Boolean.parseBoolean(getValue) && "GET".equals(httpMethod)) {
+ } else if (!Boolean.parseBoolean(postValue) && "POST".equals(httpMethod)) {
+ } else {
+
+ JsonObject logEntry = new JsonObject();
+ logEntry.addProperty("transactionId", transId);
+ logEntry.addProperty("status", status);
+ logEntry.addProperty("rqstDate", requestTs);
+ logEntry.addProperty("respDate", this.genDate());
+ logEntry.addProperty("sourceId", fromAppId + ":" + transId);
+ logEntry.addProperty("resourceId", fullUri);
+ logEntry.addProperty("resourceType", httpMethod);
+ logEntry.addProperty("rqstBuf", Objects.toString(request, ""));
+ logEntry.addProperty("respBuf", Objects.toString(response, ""));
+
+ try {
+ TRANSACTION_LOGGER.debug(logEntry.toString());
+ } catch (Exception e) {
+ ErrorLogHelper.logError("AAI_4000", "Exception writing transaction log.");
+ }
+ }
+
+ }
+
+ private String getResponseString(ContainerResponseContext responseContext) {
+ JsonObject response = new JsonObject();
+ response.addProperty("ID", responseContext.getHeaderString(AAIHeaderProperties.AAI_TX_ID));
+ response.addProperty("Content-Type", this.httpServletResponse.getContentType());
+ response.addProperty("Response-Code", responseContext.getStatus());
+ response.addProperty("Headers", responseContext.getHeaders().toString());
+ Optional<Object> entityOptional = Optional.ofNullable(responseContext.getEntity());
+ if (entityOptional.isPresent()) {
+ response.addProperty("Entity", entityOptional.get().toString());
+ } else {
+ response.addProperty("Entity", "");
+ }
+ return response.toString();
+ }
+
+}
diff --git a/src/main/java/org/onap/aai/interceptors/pre/AAIRequestFilterPriority.java b/src/main/java/org/onap/aai/interceptors/pre/AAIRequestFilterPriority.java
new file mode 100644
index 0000000..140165b
--- /dev/null
+++ b/src/main/java/org/onap/aai/interceptors/pre/AAIRequestFilterPriority.java
@@ -0,0 +1,38 @@
+/**
+ * ============LICENSE_START=======================================================
+ * org.onap.aai
+ * ================================================================================
+ * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * 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;
+
+ public static final int HTTP_HEADER = 4000;
+
+ public static final int AUTHORIZATION = 4500;
+
+ public static final int HEADER_MANIPULATION = 6000;
+
+}
diff --git a/src/main/java/org/onap/aai/interceptors/pre/HeaderValidation.java b/src/main/java/org/onap/aai/interceptors/pre/HeaderValidation.java
new file mode 100644
index 0000000..dfc4376
--- /dev/null
+++ b/src/main/java/org/onap/aai/interceptors/pre/HeaderValidation.java
@@ -0,0 +1,87 @@
+/**
+ * ============LICENSE_START=======================================================
+ * org.onap.aai
+ * ================================================================================
+ * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * 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.Optional;
+import java.util.UUID;
+
+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.MediaType;
+import javax.ws.rs.core.Response;
+
+import org.onap.aai.exceptions.AAIException;
+import org.onap.aai.interceptors.AAIContainerFilter;
+import org.onap.aai.interceptors.AAIHeaderProperties;
+import org.onap.aai.logging.ErrorLogHelper;
+
+@PreMatching
+@Priority(AAIRequestFilterPriority.HEADER_VALIDATION)
+public class HeaderValidation extends AAIContainerFilter implements ContainerRequestFilter {
+
+ @Override
+ public void filter(ContainerRequestContext requestContext) throws IOException {
+
+ Optional<Response> oResp;
+
+ String transId = requestContext.getHeaderString(AAIHeaderProperties.TRANSACTION_ID);
+ String fromAppId = requestContext.getHeaderString(AAIHeaderProperties.FROM_APP_ID);
+
+ List<MediaType> acceptHeaderValues = requestContext.getAcceptableMediaTypes();
+
+ oResp = this.validateHeaderValuePresence(fromAppId, "AAI_4009", acceptHeaderValues);
+ if (oResp.isPresent()) {
+ requestContext.abortWith(oResp.get());
+ return;
+ }
+ oResp = this.validateHeaderValuePresence(transId, "AAI_4010", acceptHeaderValues);
+ if (oResp.isPresent()) {
+ requestContext.abortWith(oResp.get());
+ return;
+ }
+
+ if (!this.isValidUUID(transId)) {
+ transId = UUID.randomUUID().toString();
+ requestContext.getHeaders().get(AAIHeaderProperties.TRANSACTION_ID).clear();
+ requestContext.getHeaders().add(AAIHeaderProperties.TRANSACTION_ID, transId);
+ }
+
+ }
+
+ private Optional<Response> validateHeaderValuePresence(String value, String errorCode,
+ List<MediaType> acceptHeaderValues) {
+ Response response = null;
+ AAIException aaie;
+ if (value == null) {
+ aaie = new AAIException(errorCode);
+ return Optional.of(Response.status(aaie.getErrorObject().getHTTPResponseCode())
+ .entity(ErrorLogHelper.getRESTAPIErrorResponse(acceptHeaderValues, aaie, new ArrayList<>()))
+ .build());
+ }
+
+ return Optional.ofNullable(response);
+ }
+
+}
diff --git a/src/main/java/org/onap/aai/interceptors/pre/OneWaySslAuthorization.java b/src/main/java/org/onap/aai/interceptors/pre/OneWaySslAuthorization.java
new file mode 100644
index 0000000..c627b85
--- /dev/null
+++ b/src/main/java/org/onap/aai/interceptors/pre/OneWaySslAuthorization.java
@@ -0,0 +1,79 @@
+/**
+ * ============LICENSE_START=======================================================
+ * org.onap.aai
+ * ================================================================================
+ * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.aai.interceptors.pre;
+
+import org.onap.aai.cacher.Profiles;
+import org.onap.aai.exceptions.AAIException;
+import org.onap.aai.interceptors.AAIContainerFilter;
+import org.onap.aai.logging.ErrorLogHelper;
+import org.onap.aai.cacher.service.AuthorizationService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Profile;
+
+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.MediaType;
+import javax.ws.rs.core.Response;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Optional;
+
+@Profile(Profiles.ONE_WAY_SSL)
+@PreMatching
+@Priority(AAIRequestFilterPriority.AUTHORIZATION)
+public class OneWaySslAuthorization extends AAIContainerFilter implements ContainerRequestFilter {
+
+ @Autowired
+ private AuthorizationService authorizationService;
+
+ @Override
+ public void filter(ContainerRequestContext containerRequestContext) throws IOException
+ {
+
+ String basicAuth = containerRequestContext.getHeaderString("Authorization");
+ List<MediaType> acceptHeaderValues = containerRequestContext.getAcceptableMediaTypes();
+
+ if(basicAuth == null || !basicAuth.startsWith("Basic ")){
+ Optional<Response> responseOptional = errorResponse("AAI_3300", acceptHeaderValues);
+ containerRequestContext.abortWith(responseOptional.get());
+ return;
+ }
+
+ basicAuth = basicAuth.replaceAll("Basic ", "");
+
+ if(!authorizationService.checkIfUserAuthorized(basicAuth)){
+ Optional<Response> responseOptional = errorResponse("AAI_3300", acceptHeaderValues);
+ containerRequestContext.abortWith(responseOptional.get());
+ return;
+ }
+
+ }
+
+ private Optional<Response> errorResponse(String errorCode, List<MediaType> acceptHeaderValues) {
+ AAIException aaie = new AAIException(errorCode);
+ return Optional.of(Response.status(aaie.getErrorObject().getHTTPResponseCode())
+ .entity(ErrorLogHelper.getRESTAPIErrorResponse(acceptHeaderValues, aaie, new ArrayList<>()))
+ .build());
+
+ }
+}
diff --git a/src/main/java/org/onap/aai/interceptors/pre/RequestHeaderManipulation.java b/src/main/java/org/onap/aai/interceptors/pre/RequestHeaderManipulation.java
new file mode 100644
index 0000000..1d9063f
--- /dev/null
+++ b/src/main/java/org/onap/aai/interceptors/pre/RequestHeaderManipulation.java
@@ -0,0 +1,60 @@
+/**
+ * ============LICENSE_START=======================================================
+ * org.onap.aai
+ * ================================================================================
+ * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.aai.interceptors.pre;
+
+import java.io.IOException;
+import java.util.Collections;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import javax.annotation.Priority;
+import javax.servlet.http.HttpServletRequest;
+import javax.ws.rs.container.ContainerRequestContext;
+import javax.ws.rs.container.ContainerRequestFilter;
+import javax.ws.rs.container.PreMatching;
+import javax.ws.rs.core.MultivaluedMap;
+
+import org.onap.aai.interceptors.AAIContainerFilter;
+import org.onap.aai.interceptors.AAIHeaderProperties;
+import org.springframework.beans.factory.annotation.Autowired;
+
+@PreMatching
+@Priority(AAIRequestFilterPriority.HEADER_MANIPULATION)
+public class RequestHeaderManipulation extends AAIContainerFilter implements ContainerRequestFilter {
+
+ @Override
+ public void filter(ContainerRequestContext requestContext) {
+
+ String uri = requestContext.getUriInfo().getPath();
+ this.addRequestContext(uri, requestContext.getHeaders());
+
+ }
+
+ private void addRequestContext(String uri, MultivaluedMap<String, String> requestHeaders) {
+
+ String rc = "";
+
+ if (requestHeaders.containsKey(AAIHeaderProperties.REQUEST_CONTEXT)) {
+ requestHeaders.remove(AAIHeaderProperties.REQUEST_CONTEXT);
+ }
+ requestHeaders.put(AAIHeaderProperties.REQUEST_CONTEXT, Collections.singletonList(rc));
+ }
+
+}
diff --git a/src/main/java/org/onap/aai/interceptors/pre/RequestTransactionLogging.java b/src/main/java/org/onap/aai/interceptors/pre/RequestTransactionLogging.java
new file mode 100644
index 0000000..f9976c2
--- /dev/null
+++ b/src/main/java/org/onap/aai/interceptors/pre/RequestTransactionLogging.java
@@ -0,0 +1,131 @@
+/**
+ * ============LICENSE_START=======================================================
+ * org.onap.aai
+ * ================================================================================
+ * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.aai.interceptors.pre;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Random;
+import java.util.UUID;
+import java.security.SecureRandom;
+
+import javax.annotation.Priority;
+import javax.servlet.http.HttpServletRequest;
+import javax.ws.rs.container.ContainerRequestContext;
+import javax.ws.rs.container.ContainerRequestFilter;
+import javax.ws.rs.container.PreMatching;
+import javax.ws.rs.core.MediaType;
+
+import org.glassfish.jersey.message.internal.ReaderWriter;
+import org.glassfish.jersey.server.ContainerException;
+import org.onap.aai.exceptions.AAIException;
+import org.onap.aai.interceptors.AAIContainerFilter;
+import org.onap.aai.interceptors.AAIHeaderProperties;
+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";
+
+ @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(StringUtils.isEmpty(acceptType) || acceptType.contains(TEXT_PLAIN)){
+ 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/src/main/java/org/onap/aai/interceptors/pre/SetLoggingContext.java b/src/main/java/org/onap/aai/interceptors/pre/SetLoggingContext.java
new file mode 100644
index 0000000..368d071
--- /dev/null
+++ b/src/main/java/org/onap/aai/interceptors/pre/SetLoggingContext.java
@@ -0,0 +1,70 @@
+/**
+ * ============LICENSE_START=======================================================
+ * org.onap.aai
+ * ================================================================================
+ * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.aai.interceptors.pre;
+
+import java.io.IOException;
+
+import javax.annotation.Priority;
+import javax.servlet.http.HttpServletRequest;
+import javax.ws.rs.container.ContainerRequestContext;
+import javax.ws.rs.container.ContainerRequestFilter;
+import javax.ws.rs.container.PreMatching;
+
+import org.onap.aai.interceptors.AAIContainerFilter;
+import org.onap.aai.interceptors.AAIHeaderProperties;
+import org.onap.aai.logging.LoggingContext;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.core.env.Environment;
+
+@PreMatching
+@Priority(AAIRequestFilterPriority.SET_LOGGING_CONTEXT)
+public class SetLoggingContext extends AAIContainerFilter implements ContainerRequestFilter {
+
+ @Autowired
+ private Environment environment;
+
+ @Autowired
+ private HttpServletRequest httpServletRequest;
+
+ @Override
+ public void filter(ContainerRequestContext requestContext) throws IOException {
+
+ String uri = httpServletRequest.getRequestURI();
+ String queryString = httpServletRequest.getQueryString();
+
+ if(queryString != null && !queryString.isEmpty()){
+ uri = uri + "?" + queryString;
+ }
+
+ String httpMethod = requestContext.getMethod();
+ String transId = requestContext.getHeaderString(AAIHeaderProperties.TRANSACTION_ID);
+ String fromAppId = requestContext.getHeaderString(AAIHeaderProperties.FROM_APP_ID);
+
+ LoggingContext.init();
+ LoggingContext.requestId(transId);
+ LoggingContext.partnerName(fromAppId);
+ LoggingContext.targetEntity(environment.getProperty("spring.application.name"));
+ LoggingContext.component(fromAppId);
+ LoggingContext.serviceName(httpMethod + " " + uri);
+ LoggingContext.targetServiceName(httpMethod + " " + uri);
+ LoggingContext.statusCode(LoggingContext.StatusCode.COMPLETE);
+ }
+
+}