aboutsummaryrefslogtreecommitdiffstats
path: root/dcae_dmaapbc_webapp/dbca-common/src/main/java/org/onap/dcae/dmaapbc/dbcapp/controller
diff options
context:
space:
mode:
Diffstat (limited to 'dcae_dmaapbc_webapp/dbca-common/src/main/java/org/onap/dcae/dmaapbc/dbcapp/controller')
-rw-r--r--dcae_dmaapbc_webapp/dbca-common/src/main/java/org/onap/dcae/dmaapbc/dbcapp/controller/DataBusHomeController.java35
-rw-r--r--dcae_dmaapbc_webapp/dbca-common/src/main/java/org/onap/dcae/dmaapbc/dbcapp/controller/DataRouterController.java321
-rw-r--r--dcae_dmaapbc_webapp/dbca-common/src/main/java/org/onap/dcae/dmaapbc/dbcapp/controller/DbcappRestrictedBaseController.java968
-rw-r--r--dcae_dmaapbc_webapp/dbca-common/src/main/java/org/onap/dcae/dmaapbc/dbcapp/controller/DmaapAccessController.java356
-rw-r--r--dcae_dmaapbc_webapp/dbca-common/src/main/java/org/onap/dcae/dmaapbc/dbcapp/controller/HealthCheckController.java142
-rw-r--r--dcae_dmaapbc_webapp/dbca-common/src/main/java/org/onap/dcae/dmaapbc/dbcapp/controller/MessageRouterController.java207
6 files changed, 2029 insertions, 0 deletions
diff --git a/dcae_dmaapbc_webapp/dbca-common/src/main/java/org/onap/dcae/dmaapbc/dbcapp/controller/DataBusHomeController.java b/dcae_dmaapbc_webapp/dbca-common/src/main/java/org/onap/dcae/dmaapbc/dbcapp/controller/DataBusHomeController.java
new file mode 100644
index 0000000..8ac462d
--- /dev/null
+++ b/dcae_dmaapbc_webapp/dbca-common/src/main/java/org/onap/dcae/dmaapbc/dbcapp/controller/DataBusHomeController.java
@@ -0,0 +1,35 @@
+package org.onap.dcae.dmaapbc.dbcapp.controller;
+
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.servlet.ModelAndView;
+
+/**
+ * This controller maps requests for the DMaaP-BC-App's landing page, which is
+ * an Angular single-page application.
+ */
+@Controller
+@RequestMapping("/")
+public class DataBusHomeController extends DbcappRestrictedBaseController {
+
+ public static final String APP_NAME = "dmaap-bc-app";
+ public static final DateFormat logDateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSXXX");
+
+ /**
+ * At one time I published the landing page as simply "/dbc", but it can
+ * also be accessed with a default suffix; e.g., "/dbc.htm".
+ *
+ * @return View name key, which is resolved to a file using an Apache tiles
+ * "definitions.xml" file.
+ */
+ @RequestMapping(value = { "/dbc" }, method = RequestMethod.GET)
+ public ModelAndView dbcDefaultController() {
+ // a model is only useful for JSP; this app is angular.
+ return new ModelAndView("dbc_home_tdkey");
+ }
+
+}
diff --git a/dcae_dmaapbc_webapp/dbca-common/src/main/java/org/onap/dcae/dmaapbc/dbcapp/controller/DataRouterController.java b/dcae_dmaapbc_webapp/dbca-common/src/main/java/org/onap/dcae/dmaapbc/dbcapp/controller/DataRouterController.java
new file mode 100644
index 0000000..c2fbb26
--- /dev/null
+++ b/dcae_dmaapbc_webapp/dbca-common/src/main/java/org/onap/dcae/dmaapbc/dbcapp/controller/DataRouterController.java
@@ -0,0 +1,321 @@
+package org.onap.dcae.dmaapbc.dbcapp.controller;
+
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.onap.dcae.dmaapbc.dbcapp.util.DbcappProperties;
+import org.openecomp.portalsdk.core.logging.logic.EELFLoggerDelegate;
+import org.openecomp.portalsdk.core.util.SystemProperties;
+import org.slf4j.MDC;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.ResponseBody;
+
+/**
+ * Data Router controller: serves Ajax requests made by Angular scripts on pages
+ * that show feeds, publishers and subscribers.
+ */
+@Controller
+@RequestMapping("/")
+public class DataRouterController extends DbcappRestrictedBaseController {
+
+ private static EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(DataRouterController.class);
+
+ /**
+ * Application properties - NOT available to constructor.
+ */
+ @Autowired
+ private DbcappProperties appProperties;
+
+ private static final String FEED_PATH = "/dr_feed";
+ private static final String PUB_PATH = "/dr_pub";
+ private static final String SUB_PATH = "/dr_sub";
+
+ public DataRouterController() {
+ }
+
+ /**
+ * Answers a request for one page of data router feeds.
+ *
+ * @param request
+ * HttpServletRequest
+ * @return Result of
+ * {@link #getItemListForPageWrapper(HttpServletRequest, DmaapDataItem)}
+ */
+ @RequestMapping(value = { FEED_PATH }, method = RequestMethod.GET, produces = "application/json")
+ @ResponseBody
+ public String getDRFeedsByPage(HttpServletRequest request) {
+ MDC.put(SystemProperties.AUDITLOG_BEGIN_TIMESTAMP, DataBusHomeController.logDateFormat.format(new Date()));
+ logger.setRequestBasedDefaultsIntoGlobalLoggingContext(request, DataBusHomeController.APP_NAME);
+ String response = getItemListForPageWrapper(request, DmaapDataItem.DR_FEED);
+ MDC.put(SystemProperties.AUDITLOG_END_TIMESTAMP, DataBusHomeController.logDateFormat.format(new Date()));
+ logger.info(EELFLoggerDelegate.auditLogger, request.getMethod() + request.getRequestURI());
+ return response;
+ }
+
+ /**
+ * Answers a request for one page of data router publishers.
+ *
+ * @param request
+ * HttpServletRequest
+ * @return Result of
+ * {@link #getItemListForPageWrapper(HttpServletRequest, DmaapDataItem)}
+ */
+ @RequestMapping(value = { PUB_PATH }, method = RequestMethod.GET, produces = "application/json")
+ @ResponseBody
+ public String getDRPubsByPage(HttpServletRequest request) {
+ MDC.put(SystemProperties.AUDITLOG_BEGIN_TIMESTAMP, DataBusHomeController.logDateFormat.format(new Date()));
+ logger.setRequestBasedDefaultsIntoGlobalLoggingContext(request, DataBusHomeController.APP_NAME);
+ String response = getItemListForPageWrapper(request, DmaapDataItem.DR_PUB);
+ MDC.put(SystemProperties.AUDITLOG_END_TIMESTAMP, DataBusHomeController.logDateFormat.format(new Date()));
+ logger.info(EELFLoggerDelegate.auditLogger, request.getMethod() + request.getRequestURI());
+ return response;
+ }
+
+ /**
+ * Answers a request for one page of data router subscribers.
+ *
+ * @param request
+ * HttpServletRequest
+ * @return Result of
+ * {@link #getItemListForPageWrapper(HttpServletRequest, DmaapDataItem)}
+ */
+ @RequestMapping(value = { SUB_PATH }, method = RequestMethod.GET, produces = "application/json")
+ @ResponseBody
+ public String getDRSubsByPage(HttpServletRequest request) {
+ MDC.put(SystemProperties.AUDITLOG_BEGIN_TIMESTAMP, DataBusHomeController.logDateFormat.format(new Date()));
+ logger.setRequestBasedDefaultsIntoGlobalLoggingContext(request, DataBusHomeController.APP_NAME);
+ String response = getItemListForPageWrapper(request, DmaapDataItem.DR_SUB);
+ MDC.put(SystemProperties.AUDITLOG_END_TIMESTAMP, DataBusHomeController.logDateFormat.format(new Date()));
+ logger.info(EELFLoggerDelegate.auditLogger, request.getMethod() + request.getRequestURI());
+ return response;
+ }
+
+ /**
+ * Adds a feed with the specified information. Expects a JSON block in the
+ * request body - a Feed object.
+ *
+ * @param request
+ * HttpServletRequest
+ * @return a JSON object; on success it has a "status" and possibly a "data"
+ * item; on failure, also has an "error" item.
+ */
+ @RequestMapping(value = { FEED_PATH }, method = RequestMethod.POST, produces = "application/json")
+ @ResponseBody
+ public String addDRFeed(HttpServletRequest request) {
+ MDC.put(SystemProperties.AUDITLOG_BEGIN_TIMESTAMP, DataBusHomeController.logDateFormat.format(new Date()));
+ logger.setRequestBasedDefaultsIntoGlobalLoggingContext(request, DataBusHomeController.APP_NAME);
+ String response = addItem(request, DmaapDataItem.DR_FEED, null);
+ MDC.put(SystemProperties.AUDITLOG_END_TIMESTAMP, DataBusHomeController.logDateFormat.format(new Date()));
+ logger.info(EELFLoggerDelegate.auditLogger, request.getMethod() + request.getRequestURI());
+ return response;
+ }
+
+ /**
+ * Adds a publisher with the specified information. Expects a JSON block in
+ * the request body - a DR_Pub object.
+ *
+ * @param request
+ * HttpServletRequest
+ * @return a JSON object; on success it has a "status" and possibly a "data"
+ * item; on failure, also has an "error" item.
+ */
+ @RequestMapping(value = { PUB_PATH }, method = RequestMethod.POST, produces = "application/json")
+ @ResponseBody
+ public String addDRPub(HttpServletRequest request) {
+ MDC.put(SystemProperties.AUDITLOG_BEGIN_TIMESTAMP, DataBusHomeController.logDateFormat.format(new Date()));
+ logger.setRequestBasedDefaultsIntoGlobalLoggingContext(request, DataBusHomeController.APP_NAME);
+ String response = addItem(request, DmaapDataItem.DR_PUB, HttpServletResponse.SC_CREATED);
+ MDC.put(SystemProperties.AUDITLOG_END_TIMESTAMP, DataBusHomeController.logDateFormat.format(new Date()));
+ logger.info(EELFLoggerDelegate.auditLogger, request.getMethod() + request.getRequestURI());
+ return response;
+ }
+
+ /**
+ * Adds a subscriber with the specified information. Expects a JSON block in
+ * the request body - a DR_Sub object.
+ *
+ * @param request
+ * HttpServletRequest
+ * @return a JSON object; on success it has a "status" and possibly a "data"
+ * item; on failure, also has an "error" item.
+ */
+ @RequestMapping(value = { SUB_PATH }, method = RequestMethod.POST, produces = "application/json")
+ @ResponseBody
+ public String addDRSub(HttpServletRequest request) {
+ MDC.put(SystemProperties.AUDITLOG_BEGIN_TIMESTAMP, DataBusHomeController.logDateFormat.format(new Date()));
+ logger.setRequestBasedDefaultsIntoGlobalLoggingContext(request, DataBusHomeController.APP_NAME);
+ String response = addItem(request, DmaapDataItem.DR_SUB, HttpServletResponse.SC_CREATED);
+ MDC.put(SystemProperties.AUDITLOG_END_TIMESTAMP, DataBusHomeController.logDateFormat.format(new Date()));
+ logger.info(EELFLoggerDelegate.auditLogger, request.getMethod() + request.getRequestURI());
+ return response;
+ }
+
+ /**
+ * Updates a feed with the specified information. Expects a JSON block in
+ * the request body - a Feed object.
+ *
+ * @param id
+ * Path parameter with object ID
+ * @param request
+ * HttpServletRequest
+ * @return a JSON object; on success it has a "status" and possibly a "data"
+ * item; on failure, also has an "error" item.
+ */
+ @RequestMapping(value = { FEED_PATH + "/{id}" }, method = RequestMethod.PUT, produces = "application/json")
+ @ResponseBody
+ public String updateFeed(@PathVariable("id") long id, HttpServletRequest request) {
+ MDC.put(SystemProperties.AUDITLOG_BEGIN_TIMESTAMP, DataBusHomeController.logDateFormat.format(new Date()));
+ logger.setRequestBasedDefaultsIntoGlobalLoggingContext(request, DataBusHomeController.APP_NAME);
+ String response = updateItem(request, DmaapDataItem.DR_FEED, Long.toString(id), null);
+ MDC.put(SystemProperties.AUDITLOG_END_TIMESTAMP, DataBusHomeController.logDateFormat.format(new Date()));
+ logger.info(EELFLoggerDelegate.auditLogger, request.getMethod() + request.getRequestURI());
+ return response;
+ }
+
+ /**
+ * Updates a publisher with the specified information. Expects a JSON block
+ * in the request body - a DR_Pub object.
+ *
+ * The pubId may have a dot in it. Spring, in its infinite wisdom, truncates
+ * extensions on dotted path parameters; e.g., "foo.json" becomes "foo".
+ * Avoid truncation here with the extra ":.+" incantation at the end.
+ *
+ * @param id
+ * Path parameter with object ID
+ * @param request
+ * HttpServletRequest
+ * @return a JSON object; on success it has a "status" and possibly a "data"
+ * item; on failure, also has an "error" item.
+ */
+ @RequestMapping(value = { PUB_PATH + "/{id:.+}" }, method = RequestMethod.PUT, produces = "application/json")
+ @ResponseBody
+ public String updateDRPub(@PathVariable("id") String id, HttpServletRequest request) {
+ MDC.put(SystemProperties.AUDITLOG_BEGIN_TIMESTAMP, DataBusHomeController.logDateFormat.format(new Date()));
+ logger.setRequestBasedDefaultsIntoGlobalLoggingContext(request, DataBusHomeController.APP_NAME);
+ String response = updateItem(request, DmaapDataItem.DR_PUB, id, null);
+ MDC.put(SystemProperties.AUDITLOG_END_TIMESTAMP, DataBusHomeController.logDateFormat.format(new Date()));
+ logger.info(EELFLoggerDelegate.auditLogger, request.getMethod() + request.getRequestURI());
+ return response;
+ }
+
+ /**
+ * Updates a subscriber with the specified information. Expects a JSON block
+ * in the request body - a DR_Sub object.
+ *
+ * @param id
+ * Path parameter with object ID
+ * @param request
+ * HttpServletRequest
+ * @return a JSON object; on success it has a "status" and possibly a "data"
+ * item; on failure, also has an "error" item.
+ */
+ @RequestMapping(value = { SUB_PATH + "/{id}" }, method = RequestMethod.PUT, produces = "application/json")
+ @ResponseBody
+ public String updateDRSub(@PathVariable("id") long id, HttpServletRequest request) {
+ MDC.put(SystemProperties.AUDITLOG_BEGIN_TIMESTAMP, DataBusHomeController.logDateFormat.format(new Date()));
+ logger.setRequestBasedDefaultsIntoGlobalLoggingContext(request, DataBusHomeController.APP_NAME);
+ String response = updateItem(request, DmaapDataItem.DR_SUB, Long.toString(id), null);
+ MDC.put(SystemProperties.AUDITLOG_END_TIMESTAMP, DataBusHomeController.logDateFormat.format(new Date()));
+ logger.info(EELFLoggerDelegate.auditLogger, request.getMethod() + request.getRequestURI());
+ return response;
+ }
+
+ /**
+ * Deletes a feed with the ID specified as a path parameter. On successful
+ * delete the endpoint returns 204 (confusingly).
+ *
+ * @param id
+ * Path parameter with object ID
+ * @param request
+ * HttpServletRequest
+ * @return A JSON object as an HTTP response; on success it only has
+ * "status" item; on failure, also has an "error" item.
+ */
+ @RequestMapping(value = { FEED_PATH + "/{id}" }, method = RequestMethod.DELETE, produces = "application/json")
+ @ResponseBody
+ public String deleteDRFeed(@PathVariable("id") long id, HttpServletRequest request) {
+ MDC.put(SystemProperties.AUDITLOG_BEGIN_TIMESTAMP, DataBusHomeController.logDateFormat.format(new Date()));
+ logger.setRequestBasedDefaultsIntoGlobalLoggingContext(request, DataBusHomeController.APP_NAME);
+ String response = deleteItem(request, DmaapDataItem.DR_FEED, Long.toString(id), 204);
+ MDC.put(SystemProperties.AUDITLOG_END_TIMESTAMP, DataBusHomeController.logDateFormat.format(new Date()));
+ logger.info(EELFLoggerDelegate.auditLogger, request.getMethod() + request.getRequestURI());
+ return response;
+ }
+
+ /**
+ * Deletes the publisher with the ID specified as a path parameter.
+ *
+ * The pubId may have a dot in it. Spring, in its infinite wisdom, truncates
+ * extensions on dotted path parameters; e.g., "foo.json" becomes "foo".
+ * Avoid truncation here with the extra ":.+" incantation at the end.
+ *
+ * @param id
+ * Path parameter with object ID
+ * @param request
+ * HttpServletRequest
+ * @return a JSON object; on success it only has "status" item; on failure,
+ * also has an "error" item.
+ */
+ @RequestMapping(value = { PUB_PATH + "/{id:.+}" }, method = RequestMethod.DELETE, produces = "application/json")
+ @ResponseBody
+ public String deleteDRPub(@PathVariable("id") String id, HttpServletRequest request) {
+ MDC.put(SystemProperties.AUDITLOG_BEGIN_TIMESTAMP, DataBusHomeController.logDateFormat.format(new Date()));
+ logger.setRequestBasedDefaultsIntoGlobalLoggingContext(request, DataBusHomeController.APP_NAME);
+ String response = deleteItem(request, DmaapDataItem.DR_PUB, id, null);
+ MDC.put(SystemProperties.AUDITLOG_END_TIMESTAMP, DataBusHomeController.logDateFormat.format(new Date()));
+ logger.info(EELFLoggerDelegate.auditLogger, request.getMethod() + request.getRequestURI());
+ return response;
+ }
+
+ /**
+ * Deletes the subscriber with the ID specified as a path parameter.
+ *
+ * @param id
+ * Path parameter with object ID
+ * @param request
+ * HttpServletRequest
+ * @return A JSON object; on success it only has "status" item; on failure,
+ * also has an "error" item.
+ */
+ @RequestMapping(value = { SUB_PATH + "/{id}" }, method = RequestMethod.DELETE, produces = "application/json")
+ @ResponseBody
+ public String deleteDRSub(@PathVariable("id") long id, HttpServletRequest request) {
+ MDC.put(SystemProperties.AUDITLOG_BEGIN_TIMESTAMP, DataBusHomeController.logDateFormat.format(new Date()));
+ logger.setRequestBasedDefaultsIntoGlobalLoggingContext(request, DataBusHomeController.APP_NAME);
+ String response = deleteItem(request, DmaapDataItem.DR_SUB, Long.toString(id), 204);
+ MDC.put(SystemProperties.AUDITLOG_END_TIMESTAMP, DataBusHomeController.logDateFormat.format(new Date()));
+ logger.info(EELFLoggerDelegate.auditLogger, request.getMethod() + request.getRequestURI());
+ return response;
+ }
+
+ /**
+ * Answers a request for data router feed classification labels, such as
+ * "Customer Proprietary", which are read from properties.
+ *
+ * @param request
+ * HttpServletRequest
+ * @return List of string values
+ */
+ @RequestMapping(value = { FEED_PATH + "_pii_types" }, method = RequestMethod.GET, produces = "application/json")
+ @ResponseBody
+ public List<String> getDRFeedPiiType(HttpServletRequest request) {
+ MDC.put(SystemProperties.AUDITLOG_BEGIN_TIMESTAMP, DataBusHomeController.logDateFormat.format(new Date()));
+ logger.setRequestBasedDefaultsIntoGlobalLoggingContext(request, DataBusHomeController.APP_NAME);
+ ArrayList<String> response = new ArrayList<>();
+ String[] propKeys = appProperties.getCsvListProperty(DbcappProperties.DMAAP_PII_TYPE_LIST);
+ for (String key : propKeys)
+ response.add(appProperties.getProperty(key));
+ MDC.put(SystemProperties.AUDITLOG_END_TIMESTAMP, DataBusHomeController.logDateFormat.format(new Date()));
+ logger.info(EELFLoggerDelegate.auditLogger, request.getMethod() + request.getRequestURI());
+ return response;
+ }
+
+}
diff --git a/dcae_dmaapbc_webapp/dbca-common/src/main/java/org/onap/dcae/dmaapbc/dbcapp/controller/DbcappRestrictedBaseController.java b/dcae_dmaapbc_webapp/dbca-common/src/main/java/org/onap/dcae/dmaapbc/dbcapp/controller/DbcappRestrictedBaseController.java
new file mode 100644
index 0000000..7964e45
--- /dev/null
+++ b/dcae_dmaapbc_webapp/dbca-common/src/main/java/org/onap/dcae/dmaapbc/dbcapp/controller/DbcappRestrictedBaseController.java
@@ -0,0 +1,968 @@
+package org.onap.dcae.dmaapbc.dbcapp.controller;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.onap.dcae.dmaapbc.client.DmaapBcRestClient;
+import org.onap.dcae.dmaapbc.client.HttpStatusAndResponse;
+import org.onap.dcae.dmaapbc.dbcapp.domain.DmaapAccess;
+import org.onap.dcae.dmaapbc.dbcapp.rest.DbcUsvcRestClient;
+import org.onap.dcae.dmaapbc.dbcapp.service.DmaapAccessService;
+import org.onap.dcae.dmaapbc.dbcapp.util.DbcappProperties;
+import org.onap.dcae.dmaapbc.model.DR_Pub;
+import org.onap.dcae.dmaapbc.model.DR_Sub;
+import org.onap.dcae.dmaapbc.model.DcaeLocation;
+import org.onap.dcae.dmaapbc.model.Dmaap;
+import org.onap.dcae.dmaapbc.model.DmaapObject;
+import org.onap.dcae.dmaapbc.model.ErrorResponse;
+import org.onap.dcae.dmaapbc.model.Feed;
+import org.onap.dcae.dmaapbc.model.MR_Client;
+import org.onap.dcae.dmaapbc.model.Topic;
+import org.openecomp.portalsdk.core.controller.RestrictedBaseController;
+import org.openecomp.portalsdk.core.domain.User;
+import org.openecomp.portalsdk.core.logging.logic.EELFLoggerDelegate;
+import org.openecomp.portalsdk.core.onboarding.util.CipherUtil;
+import org.openecomp.portalsdk.core.web.support.UserUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+/**
+ * This base class provides utility methods to child controllers. All of the
+ * requests are forwarded on to a remote REST API, so there's a large degree of
+ * commonality among the implementations. Combining them kept the lines-of-code
+ * count down, at the expense of some complexity.
+ */
+public class DbcappRestrictedBaseController extends RestrictedBaseController {
+
+ /**
+ * Query parameter for desired page number
+ */
+ protected static final String PAGE_NUM_QUERY_PARAM = "pageNum";
+
+ /**
+ * Query parameter for desired items per page
+ */
+ protected static final String VIEW_PER_PAGE_QUERY_PARAM = "viewPerPage";
+
+ /**
+ * Tag for status code in JSON responses - ALWAYS PRESENT.
+ */
+ protected static final String STATUS_RESPONSE_KEY = "status";
+
+ /**
+ * Tag for data in JSON responses.
+ */
+ protected static final String DATA_RESPONSE_KEY = "data";
+
+ /**
+ * Tag for error message in JSON responses; absent on success.
+ */
+ protected static final String ERROR_RESPONSE_KEY = "error";
+
+ /**
+ * Tag for response integer, pages required to display complete result list
+ */
+ protected static final String TOTAL_PAGES_RESPONSE_KEY = "totalPages";
+
+ /**
+ * Tag for DMaaP name obtained from REST client.
+ */
+ protected static final String PROFILE_NAME_RESPONSE_KEY = "profileName";
+
+ /**
+ * Tag for DMaaP name obtained from REST client.
+ */
+ protected static final String DMAAP_NAME_RESPONSE_KEY = "dmaapName";
+
+ /**
+ * Tag for DCAE location name list obtained from REST client.
+ */
+ protected static final String DCAE_LOCATIONS_RESPONSE_KEY = "dcaeLocations";
+
+ /**
+ * Logger that conforms with ECOMP guidelines
+ */
+ private static EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(DbcappRestrictedBaseController.class);
+
+ /**
+ * For general use in these methods and subclasses
+ */
+ protected final ObjectMapper mapper = new ObjectMapper();
+
+ /**
+ * DAO accesses the profiles via a local database. REST accesses the
+ * profiles via a remote REST service.
+ */
+ public enum AccessMethod {
+ DAO, REST
+ };
+
+ /**
+ * Enum for selecting an item type.
+ */
+ public enum DmaapDataItem {
+ DR_FEED, DR_PUB, DR_SUB, MR_TOPIC, MR_CLIENT;
+ }
+
+ /**
+ * Application properties - NOT available to constructor.
+ */
+ @Autowired
+ private DbcappProperties appProperties;
+
+ /**
+ * Database access - which might not be used.
+ */
+ @Autowired
+ private DmaapAccessService dmaapAccessDaoServiceAuto;
+
+ /**
+ * Read from application properties.
+ */
+ private String mechIdName, mechIdPass;
+
+ /**
+ * This is set by {@link #getDmaapAccessService()} to the DAO or REST
+ * implementation as configured in properties.
+ */
+ private DmaapAccessService dmaapAccessService;
+
+ /**
+ * Hello Spring, here's your no-arg constructor.
+ */
+ public DbcappRestrictedBaseController() {
+ // Do not serialize null values
+ mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
+ }
+
+ /**
+ * Access method for subclasses.
+ *
+ * @return DbcappProperties object that was autowired by Spring.
+ */
+ protected DbcappProperties getAppProperties() {
+ return appProperties;
+ }
+
+ /**
+ * Lazy initialization. As a side effect, caches mech ID and password.
+ *
+ * @return Either DAO or REST client that implements the access service
+ * interface.
+ */
+ protected DmaapAccessService getDmaapAccessService() {
+ if (dmaapAccessService != null)
+ return dmaapAccessService;
+
+ // Get the application's mechid
+ mechIdName = appProperties.getProperty(DbcappProperties.DMAAP_MECHID_NAME);
+ // This is encrypted
+ String cipher = appProperties.getProperty(DbcappProperties.DMAAP_MECHID_PASSWORD);
+ if (mechIdName == null || cipher == null)
+ throw new RuntimeException("Failed to get MECH_ID name and/or password from properties");
+ try {
+ mechIdPass = CipherUtil.decrypt(cipher);
+ } catch (Exception ex) {
+ throw new RuntimeException("Failed to decrypt password from config file", ex);
+ }
+
+ String accessMethod = appProperties.getProperty(DbcappProperties.PROFILE_ACCESS_METHOD);
+ if (accessMethod == null)
+ throw new RuntimeException("Failed to get property " + DbcappProperties.PROFILE_ACCESS_METHOD);
+ AccessMethod profileAccessMethod = AccessMethod.valueOf(accessMethod.toUpperCase());
+ if (AccessMethod.DAO == profileAccessMethod) {
+ // Spring auto-wired this field
+ dmaapAccessService = dmaapAccessDaoServiceAuto;
+ } else {
+ String url = appProperties.getProperty(DbcappProperties.PROFILE_USVC_URL);
+ String user = appProperties.getProperty(DbcappProperties.PROFILE_USVC_USER);
+ String pass = appProperties.getProperty(DbcappProperties.PROFILE_USVC_PASS);
+ if (url == null || user == null || pass == null)
+ throw new RuntimeException("getDmaapAccessService: missing property: one of url, user, pass");
+ String clearText = null;
+ try {
+ clearText = CipherUtil.decrypt(pass);
+ } catch (Exception ex) {
+ throw new RuntimeException("getDmaapAccessService: failed to decrypt password from config");
+ }
+ dmaapAccessService = new DbcUsvcRestClient(url, user, clearText);
+ }
+ return dmaapAccessService;
+ }
+
+ /**
+ * Creates a REST client with appropriate credentials, the user/pass from
+ * the access profile if present, otherwise with the default mech ID and
+ * password.
+ *
+ * @param dmaapAccess
+ * Profile
+ * @return REST client.
+ */
+ protected DmaapBcRestClient getDmaapBcRestClient(DmaapAccess dmaapAccess) {
+ DmaapBcRestClient restClient = null;
+ if (dmaapAccess.getMechId() == null || dmaapAccess.getMechId().length() == 0)
+ restClient = new DmaapBcRestClient(dmaapAccess.getDmaapUrl(), mechIdName, mechIdPass);
+ else
+ restClient = new DmaapBcRestClient(dmaapAccess.getDmaapUrl(), dmaapAccess.getMechId(),
+ dmaapAccess.getPassword());
+ return restClient;
+ }
+
+ /**
+ * Pulls out of the specified list the appropriate items for the page of
+ * results specified by the page number and view-per-page parameters.
+ *
+ * @param pageNum
+ * Page number requested by user
+ * @param viewPerPage
+ * Number of items per page
+ * @param itemList
+ * List of items available
+ * @return List of items to display
+ */
+ @SuppressWarnings("rawtypes")
+ private static List shrinkListToPage(final int pageNum, final int viewPerPage, final List itemList) {
+ // user-friendly page numbers index from 1
+ int firstIndexOnThisPage = viewPerPage * (pageNum - 1);
+ int firstIndexOnNextPage = viewPerPage * pageNum;
+ int fromIndex = firstIndexOnThisPage < itemList.size() ? firstIndexOnThisPage : itemList.size();
+ int toIndex = firstIndexOnNextPage < itemList.size() ? firstIndexOnNextPage : itemList.size();
+ // answers empty list if from==to
+ return itemList.subList(fromIndex, toIndex);
+ }
+
+ /**
+ * Gets the body of a HTTP request assuming UTF-8 encoding.
+ *
+ * @param request
+ * HttpServletRequest
+ * @return String version of request body
+ * @throws IOException
+ * If the read fails
+ */
+ protected static String getBody(HttpServletRequest request) throws IOException {
+ StringBuilder stringBuilder = new StringBuilder();
+ BufferedReader bufferedReader = null;
+ try {
+ InputStream inputStream = request.getInputStream();
+ if (inputStream != null) {
+ bufferedReader = new BufferedReader(new InputStreamReader(inputStream, "UTF-8"));
+ char[] charBuffer = new char[512];
+ int bytesRead = -1;
+ while ((bytesRead = bufferedReader.read(charBuffer)) > 0) {
+ stringBuilder.append(charBuffer, 0, bytesRead);
+ }
+ } else {
+ stringBuilder.append("");
+ }
+ } finally {
+ if (bufferedReader != null) {
+ try {
+ bufferedReader.close();
+ } catch (IOException ex) {
+ throw ex;
+ }
+ }
+
+ }
+ return stringBuilder.toString();
+ }
+
+ /**
+ * Builds a JSON success response from the specified inputs.
+ *
+ * @param statusCode
+ * e.g., 200 for OK
+ * @param dataPojo
+ * Plain old Java object to serialize as JSON; ignored if null.
+ * @throws JsonProcessingException
+ * If the POJO cannot be serialized
+ * @return JSON block with items "status" : 200 and "data" : (data..)
+ */
+ protected String buildJsonSuccess(int statusCode, Object dataPojo) throws JsonProcessingException {
+ Map<String, Object> model = new HashMap<String, Object>();
+ model.put(STATUS_RESPONSE_KEY, statusCode);
+ if (dataPojo != null)
+ model.put(DATA_RESPONSE_KEY, dataPojo);
+ String json = mapper.writeValueAsString(model);
+ return json;
+ }
+
+ /**
+ * Builds a JSON error response from the specified inputs.
+ *
+ * @param statusCode
+ * e.g., 500 for internal server error
+ * @param errMsg
+ * Information about the operation that failed
+ * @param exception
+ * Converted to string; ignored if null.
+ * @return JSON block with tags "status" and "error".
+ */
+ protected String buildJsonError(int statusCode, String errMsg, Exception exception) {
+ Map<String, Object> model = new HashMap<String, Object>();
+ model.put(STATUS_RESPONSE_KEY, new Integer(500));
+ if (exception == null) {
+ model.put(ERROR_RESPONSE_KEY, errMsg);
+ } else {
+ final int enough = 512;
+ String exString = exception.toString();
+ String exceptionMsg = exString.length() > enough ? exString.substring(0, enough) : exString;
+ model.put(ERROR_RESPONSE_KEY, errMsg + ": " + exceptionMsg);
+ }
+ String json = null;
+ try {
+ json = mapper.writeValueAsString(model);
+ } catch (JsonProcessingException ex) {
+ // serializing the trivial map should never fail
+ String err = "buildJsonError: failed to serialize";
+ logger.error(EELFLoggerDelegate.errorLogger, err, ex);
+ throw new RuntimeException(err, ex);
+ }
+ return json;
+ }
+
+ /**
+ * Gets a list of DMaaP access profiles for this user from the database. The
+ * profiles have passwords in the clear - this method decrypts the database
+ * entries.
+ *
+ * Initializes the list for new users and/or configuration changes. Checks
+ * the database list against the configured list of URLs, and creates new
+ * rows for any configured URLs not present for the user. Most environments
+ * are expected to have exactly one valid URL, and the webapp uses a fixed
+ * MechID to authenticate itself to the DMaaP bus controller, so this
+ * approach means new users can start without any setup of URLs.
+ *
+ * @param userId
+ * User ID
+ * @return List of DmaapAccess objects
+ * @throws Exception
+ * If the URL list is not available in properties
+ */
+ protected List<DmaapAccess> getOrInitDmaapAccessList(String userId) throws Exception {
+ String[] configUrls = getAppProperties().getCsvListProperty(DbcappProperties.DMAAP_REST_URL_LIST);
+ if (configUrls == null || configUrls.length == 0)
+ throw new Exception("getOrInitDmaapAccessList: Failed to get DMAAP REST URL list");
+ // Update this list to track which URLs are in the database.
+ List<String> configUrlList = new ArrayList<String>(configUrls.length);
+ for (String c : configUrls) {
+ // Validate URL to detect config botches
+ URL url = new URL(c);
+ configUrlList.add(url.toExternalForm());
+ }
+
+ List<DmaapAccess> dbAccessList = getDmaapAccessService().getDmaapAccessList(userId);
+
+ // Check the database entries against the configuration. Also
+ // build a list of non-DAO objects with clear-text passwords.
+ List<DmaapAccess> clearList = new ArrayList<DmaapAccess>(dbAccessList.size());
+ for (DmaapAccess dmaapAccess : dbAccessList) {
+ // drop this URL from the list.
+ // If it's not known to config, complain because that's a bogus row.
+ if (!configUrlList.remove(dmaapAccess.getDmaapUrl()))
+ logger.warn(EELFLoggerDelegate.errorLogger, "getOrInitDmaapAccessList: detected extra URL {}",
+ dmaapAccess.getDmaapUrl());
+ // Return cleartext in JSON
+ DmaapAccess clone = new DmaapAccess(dmaapAccess);
+ clone.setPassword(clone.decryptPassword());
+ clearList.add(clone);
+ }
+
+ // Create new rows for any configured URLs not found for this user.
+ for (int i = 0; i < configUrlList.size(); ++i) {
+ String missUrl = configUrlList.get(i);
+ logger.debug(EELFLoggerDelegate.debugLogger, "getOrInitDmaapAccessList: adding missing URL {}", missUrl);
+ DmaapAccess newDmaapAccess = new DmaapAccess();
+ // Create a semi-reasonable name for the table
+ newDmaapAccess.setName("dmaap-" + Integer.toString(i + 1));
+ newDmaapAccess.setUserId(userId);
+ newDmaapAccess.setDmaapUrl(missUrl);
+ // Write to db.
+ getDmaapAccessService().saveDmaapAccess(newDmaapAccess);
+ // Add to response, which assumes the write was successful.
+ clearList.add(newDmaapAccess);
+ }
+
+ return clearList;
+ }
+
+ /**
+ * Gets the user's selected DMaaP access profile.
+ *
+ * @param userId
+ * User ID
+ * @return DmaapAccess object that is currently selected, or the first one
+ * found if none are selected; null if no access profiles are
+ * configured.
+ * @throws Exception
+ * If the profile is not found
+ */
+ protected DmaapAccess getSelectedDmaapAccess(String userId) throws Exception {
+ List<DmaapAccess> profiles = getOrInitDmaapAccessList(userId);
+ if (profiles.size() == 0) {
+ logger.debug("getSelectedDmaapAccess: no rows found, returning null");
+ return null;
+ }
+
+ // Return the first one by default if nothing is selected.
+ DmaapAccess selected = profiles.get(0);
+ for (DmaapAccess da : profiles)
+ if (da.getSelected())
+ selected = da;
+
+ return selected;
+ }
+
+ /**
+ * Supports sorting a list of feeds by the first column displayed: ID
+ */
+ private static Comparator<DmaapObject> feedComparator = new Comparator<DmaapObject>() {
+ @Override
+ public int compare(DmaapObject o1, DmaapObject o2) {
+ Feed f1 = (Feed) o1;
+ Feed f2 = (Feed) o2;
+ // sort these numbers lexicographically, same as the front end
+ // table.
+ return f1.getFeedId().compareTo(f2.getFeedId());
+ }
+ };
+
+ /**
+ * Supports sorting a list of publishers by the first column displayed: pub
+ * ID
+ */
+ private static Comparator<DmaapObject> pubComparator = new Comparator<DmaapObject>() {
+ @Override
+ public int compare(DmaapObject o1, DmaapObject o2) {
+ DR_Pub p1 = (DR_Pub) o1;
+ DR_Pub p2 = (DR_Pub) o2;
+ return p1.getPubId().compareTo(p2.getPubId());
+ }
+ };
+
+ /**
+ * Supports sorting a list of subscribers by the first column displayed: sub
+ * ID
+ */
+ private static Comparator<DmaapObject> subComparator = new Comparator<DmaapObject>() {
+ @Override
+ public int compare(DmaapObject o1, DmaapObject o2) {
+ DR_Sub s1 = (DR_Sub) o1;
+ DR_Sub s2 = (DR_Sub) o2;
+ // sort these numbers lexicographically, same as the front end
+ // table.
+ return s1.getSubId().compareTo(s2.getSubId());
+ }
+ };
+
+ /**
+ * Supports sorting a list of topics by the first column displayed: FQTN
+ */
+ private static Comparator<DmaapObject> topicComparator = new Comparator<DmaapObject>() {
+ @Override
+ public int compare(DmaapObject o1, DmaapObject o2) {
+ Topic t1 = (Topic) o1;
+ Topic t2 = (Topic) o2;
+ return t1.getFqtn().compareTo(t2.getFqtn());
+ }
+ };
+
+ /**
+ * Supports sorting a list of clients by the first column displayed: client
+ * ID.
+ */
+ private static Comparator<DmaapObject> clientComparator = new Comparator<DmaapObject>() {
+ @Override
+ public int compare(DmaapObject o1, DmaapObject o2) {
+ MR_Client c1 = (MR_Client) o1;
+ MR_Client c2 = (MR_Client) o2;
+ // sort these numbers lexicographically, same as the front end
+ // table.
+ return c1.getMrClientId().compareTo(c2.getMrClientId());
+ }
+ };
+
+ /**
+ * Gets one page of DMaaP objects and supporting information via the Bus
+ * Controller REST client. On success, returns a JSON object as String with
+ * the following tags:
+ * <UL>
+ * <LI>status: Integer; HTTP status code 200.
+ * <LI>dmaapName: String, name returned by the remote DMaaP instance.
+ * <LI>dcaeLocations: Array of string, locations returned by the remote
+ * DMaaP instance.
+ * <LI>data: Array of the desired items; e.g., data router feeds.
+ * <LI>totalPages: Integer, the number of pages required to display the
+ * complete list of items using the submitted page size
+ * </UL>
+ *
+ * This duplicates all of {@link #buildJsonSuccess(int, Object)}.
+ *
+ * @param dmaapAccess
+ * Access details for the DMaaP REST API
+ * @param option
+ * Specifies which item list type to get: data router feeds, etc.
+ * @param pageNum
+ * Page number of results
+ * @param viewPerPage
+ * Number of items per page
+ * @return JSON block as String, see above.
+ * @throws Exception
+ * On any error
+ */
+ private String getItemListForPage(DmaapAccess dmaapAccess, DmaapDataItem option, int pageNum, int viewPerPage)
+ throws Exception {
+ DmaapBcRestClient restClient = getDmaapBcRestClient(dmaapAccess);
+ // Get the instance so the page can display its name
+ DmaapObject dmaap = restClient.getDmaap();
+ if (dmaap instanceof ErrorResponse) {
+ // Bad password is caught here.
+ ErrorResponse err = (ErrorResponse) dmaap;
+ throw new Exception(err.getMessage());
+ }
+ // Get locations for editing
+ List<DmaapObject> dcaeLocations = restClient.getDcaeLocations();
+ if (dcaeLocations.size() == 1 && dcaeLocations.get(0) instanceof ErrorResponse) {
+ // Should never happen - bad password is caught right above - but be
+ // careful.
+ ErrorResponse err = (ErrorResponse) dcaeLocations.get(0);
+ throw new Exception(err.getMessage());
+ }
+ // Pass them back as String array
+ String[] dcaeLocs = new String[dcaeLocations.size()];
+ for (int i = 0; i < dcaeLocs.length; ++i) {
+ DcaeLocation dcaeLoc = (DcaeLocation) dcaeLocations.get(i);
+ dcaeLocs[i] = dcaeLoc.getDcaeLocationName();
+ }
+ // Get the requested item list
+ List<DmaapObject> itemList = null;
+ switch (option) {
+ case DR_FEED:
+ itemList = restClient.getFeeds();
+ // size 1 may be error response
+ if (itemList.size() > 1)
+ Collections.sort(itemList, feedComparator);
+ break;
+ case DR_PUB:
+ itemList = restClient.getDRPubs();
+ // size 1 may be error response
+ if (itemList.size() > 1)
+ Collections.sort(itemList, pubComparator);
+ break;
+ case DR_SUB:
+ itemList = restClient.getDRSubs();
+ // size 1 may be error response
+ if (itemList.size() > 1)
+ Collections.sort(itemList, subComparator);
+ break;
+ case MR_TOPIC:
+ itemList = restClient.getTopics();
+ // size 1 may be error response
+ if (itemList.size() > 1)
+ Collections.sort(itemList, topicComparator);
+ break;
+ case MR_CLIENT:
+ itemList = restClient.getMRClients();
+ // size 1 may be error response
+ if (itemList.size() > 1)
+ Collections.sort(itemList, clientComparator);
+ break;
+ default:
+ throw new Exception("getItemListForPage: pgmr error, unimplemented case: " + option.name());
+ }
+
+ logger.debug("getItemListForPage: list size is {}", itemList.size());
+ int pageCount = (int) Math.ceil((double) itemList.size() / viewPerPage);
+ @SuppressWarnings("unchecked")
+ List<DmaapObject> subList = shrinkListToPage(pageNum, viewPerPage, itemList);
+ itemList = subList;
+ // Build response here
+ Map<String, Object> model = new HashMap<String, Object>();
+ model.put(STATUS_RESPONSE_KEY, new Integer(200));
+ model.put(PROFILE_NAME_RESPONSE_KEY, dmaapAccess.getName());
+ model.put(DMAAP_NAME_RESPONSE_KEY, ((Dmaap) dmaap).getDmaapName());
+ model.put(DCAE_LOCATIONS_RESPONSE_KEY, dcaeLocs);
+ model.put(DATA_RESPONSE_KEY, itemList);
+ model.put(TOTAL_PAGES_RESPONSE_KEY, pageCount);
+
+ // build the response
+ String outboundJson = null;
+ try {
+ outboundJson = mapper.writeValueAsString(model);
+ } catch (Exception ex) {
+ // should never happen
+ logger.error("getItemListForPage: failed to serialize model: ", ex);
+ throw new Exception("sendItemListForPage", ex);
+ }
+
+ return outboundJson;
+ }
+
+ /**
+ * Gets a page of the specified DMaaP items. This method traps errors and
+ * constructs an appropriate JSON block if an error happens.
+ *
+ * See {@link #getItemListForPage(DmaapAccess, DmaapDataItem, int, int)}.
+ *
+ * @param request
+ * Inbound request
+ * @param option
+ * DMaaP item type to get
+ * @return JSON with list of serialized objects, or an error.
+ */
+ protected String getItemListForPageWrapper(HttpServletRequest request, DmaapDataItem option) {
+ String outboundJson = null;
+ try {
+ User appUser = UserUtils.getUserSession(request);
+ if (appUser == null || appUser.getLoginId() == null || appUser.getLoginId().length() == 0)
+ throw new Exception("getItemListForPageWrapper: Failed to get Login UID");
+ DmaapAccess selected = getSelectedDmaapAccess(appUser.getLoginId());
+ if (selected == null) // leap into exception handler
+ throw new Exception("No DMaaP access profiles are configured.");
+ int pageNum = Integer.parseInt(request.getParameter(PAGE_NUM_QUERY_PARAM));
+ int viewPerPage = Integer.parseInt(request.getParameter(VIEW_PER_PAGE_QUERY_PARAM));
+ outboundJson = getItemListForPage(selected, option, pageNum, viewPerPage);
+ } catch (Exception ex) {
+ outboundJson = buildJsonError(500, "Failed to get DMaaP item type " + option.name(), ex);
+ }
+ return outboundJson;
+ }
+
+ /**
+ * Adds an item of the specified type with the specified content. Constructs
+ * an object by deserializing the JSON block, but ignores any ID field that
+ * is supplied.
+ *
+ * On success, returns a JSON block as String with any data returned by the
+ * REST client. Throws an exception on any failure.
+ *
+ * @param dmaapAccess
+ * Access details for the DMaaP REST API
+ * @param userId
+ * The login ID of the user making the request
+ * @param itemType
+ * DMaaP item type to add
+ * @param itemContent
+ * JSON block to deserialize as an object
+ * @param scAddlStatus
+ * HTTP status code 200 is always accepted. If this parameter is
+ * not null, the value is also considered a valid HTTP status
+ * code on success; e.g., 204.
+ * @return JSON object with result of the operation
+ * @throws Exception
+ * on any problem
+ */
+ private String addDmaapItem(DmaapAccess dmaapAccess, String userId, DmaapDataItem itemType, String itemContent,
+ Integer scAddlStatus) throws Exception {
+ DmaapBcRestClient restClient = getDmaapBcRestClient(dmaapAccess);
+ HttpStatusAndResponse<Object> hsr = null;
+ switch (itemType) {
+ case DR_FEED:
+ Feed feed = mapper.readValue(itemContent, Feed.class);
+ logger.debug("addDmaapItem: received feed: {} ", feed);
+ // Null out any ID to get an auto-generated ID
+ feed.setFeedId(null);
+ // Assign the owner to be the webapp user
+ feed.setOwner(userId);
+ hsr = restClient.postFeed(feed);
+ break;
+ case DR_PUB:
+ DR_Pub pub = mapper.readValue(itemContent, DR_Pub.class);
+ logger.debug("addDmaapItem: received pub: {} ", pub);
+ // Null out any ID to get an auto-generated ID
+ pub.setPubId(null);
+ hsr = restClient.postDRPub(pub);
+ break;
+ case DR_SUB:
+ DR_Sub sub = mapper.readValue(itemContent, DR_Sub.class);
+ logger.debug("addDmaapItem: received sub: {} ", sub);
+ // Null out any ID to get an auto-generated ID
+ sub.setSubId(null);
+ // Assign the owner to be the webapp user
+ sub.setOwner(userId);
+ hsr = restClient.postDRSub(sub);
+ break;
+ case MR_TOPIC:
+ Topic topic = mapper.readValue(itemContent, Topic.class);
+ logger.debug("addDmaapItem: received topic: {} ", topic);
+ // No ID on topic
+ topic.setOwner(userId);
+ hsr = restClient.postTopic(topic);
+ break;
+ case MR_CLIENT:
+ MR_Client client = mapper.readValue(itemContent, MR_Client.class);
+ logger.debug("addDmaapItem: received client: {} ", client);
+ client.setMrClientId(null);
+ hsr = restClient.postMRClient(client);
+ break;
+ default:
+ throw new Exception("addDmaapItem: pgmr error, unimplemented case: " + itemType.name());
+ }
+
+ // Build result here
+ String outboundJson = null;
+ if (hsr.getStatusCode() == HttpServletResponse.SC_OK
+ || (scAddlStatus != null && hsr.getStatusCode() == scAddlStatus)) {
+ outboundJson = buildJsonSuccess(hsr.getStatusCode(), hsr.getResponseString());
+ } else {
+ throw new Exception("Unexpected HTTP response code " + Integer.toString(hsr.getStatusCode())
+ + " with content " + hsr.getResponseString());
+ }
+ return outboundJson;
+ }
+
+ /**
+ * Adds the specified DMaaP item that is read from the request body. This
+ * method traps errors and constructs an appropriate JSON block if an error
+ * happens.
+ *
+ * @param request
+ * Used to obtain user info from the active session
+ * @param itemType
+ * DMaaP item type to add
+ * @param scAddlStatus
+ * HTTP status code 200 is always accepted. If this parameter is
+ * not null, the value is also considered a valid HTTP status
+ * code on success; e.g., 204.
+ * @return JSON block with success or failure object
+ */
+ protected String addItem(HttpServletRequest request, DmaapDataItem itemType, Integer scAddlStatus) {
+ String outboundJson = null;
+ try {
+ User appUser = UserUtils.getUserSession(request);
+ if (appUser == null || appUser.getLoginId() == null || appUser.getLoginId().length() == 0)
+ throw new Exception("addDmaapItem: Failed to get Login ID");
+
+ DmaapAccess access = getSelectedDmaapAccess(appUser.getLoginId());
+ if (access == null) // leap into exception handler
+ throw new Exception("No DMaaP access profiles are configured.");
+ String jsonContent = getBody(request);
+ outboundJson = addDmaapItem(access, appUser.getLoginId(), itemType, jsonContent, scAddlStatus);
+ } catch (Exception ex) {
+ outboundJson = buildJsonError(500, "Failed to add DMaaP item " + itemType.name(), ex);
+ }
+
+ return outboundJson;
+ }
+
+ /**
+ * Updates an item of the specified type with the specified content.
+ * Constructs an object by deserializing the JSON block.
+ *
+ * On success, returns a JSON block as String with any data returned by the
+ * REST client. Throws an exception on any failure.
+ *
+ * @param dmaapAccess
+ * Access details for the DMaaP REST API
+ * @param userId
+ * The Login ID of the user making the request
+ * @param itemType
+ * DMaaP item type to update
+ * @param itemId
+ * Item identification
+ * @param itemContent
+ * JSON block to deserialize as an object
+ * @param scAddlStatus
+ * HTTP status code 200 is always accepted. If this parameter is
+ * not null, the value is also considered a valid HTTP status
+ * code on success; e.g., 204.
+ * @return JSON object with result of the operation
+ * @throws Exception
+ * on any problem
+ */
+ private String updateDmaapItem(DmaapAccess dmaapAccess, String userId, DmaapDataItem itemType, String itemId,
+ String itemContent, Integer scAddlStatus) throws Exception {
+ DmaapBcRestClient restClient = getDmaapBcRestClient(dmaapAccess);
+ HttpStatusAndResponse<Object> hsr = null;
+ switch (itemType) {
+ case DR_FEED:
+ Feed feed = mapper.readValue(itemContent, Feed.class);
+ logger.debug("updateDmaapItem: received feed: {} ", feed);
+ // Ensure the owner is the webapp user
+ feed.setOwner(userId);
+ hsr = restClient.putFeed(feed);
+ break;
+ case DR_PUB:
+ DR_Pub pub = mapper.readValue(itemContent, DR_Pub.class);
+ logger.debug("updateDmaapItem: received pub: {} ", pub);
+ hsr = restClient.putDRPub(pub);
+ break;
+ case DR_SUB:
+ DR_Sub sub = mapper.readValue(itemContent, DR_Sub.class);
+ logger.debug("updateDmaapItem: received sub: {} ", sub);
+ // Ensure the owner is the webapp user
+ sub.setOwner(userId);
+ hsr = restClient.putDRSub(sub);
+ break;
+ case MR_TOPIC:
+ Topic topic = mapper.readValue(itemContent, Topic.class);
+ logger.debug("updateDmaapItem: received topic: {} ", topic);
+ // Ensure the owner is the webapp user
+ topic.setOwner(userId);
+ // DCAE backend may implement PUT someday.
+ if (true && userId != null)
+ throw new UnsupportedOperationException("put topic not supported (yet)");
+ break;
+ case MR_CLIENT:
+ MR_Client client = mapper.readValue(itemContent, MR_Client.class);
+ logger.debug("updateDmaapItem: received client: {} ", client);
+ hsr = restClient.putMRClient(client);
+ break;
+ default:
+ throw new Exception("updateDmaapItem: pgmr error, unimplemented case: " + itemType.name());
+ }
+
+ // Build result here
+ String outboundJson = null;
+ if (hsr.getStatusCode() == HttpServletResponse.SC_OK
+ || (scAddlStatus != null && hsr.getStatusCode() == scAddlStatus)) {
+ outboundJson = buildJsonSuccess(hsr.getStatusCode(), hsr.getResponseString());
+ } else {
+ throw new Exception("Unexpected HTTP response code " + Integer.toString(hsr.getStatusCode())
+ + " with content " + hsr.getResponseString());
+ }
+ return outboundJson;
+ }
+
+ /**
+ * Updates the specified DMaaP item that is read from the request body. This
+ * method traps errors and constructs an appropriate JSON block if an error
+ * happens.
+ *
+ * @param request
+ * Used to obtain user info from the active session
+ * @param itemType
+ * DMaaP item type to update
+ * @param itemId
+ * Item identification to update
+ * @param scUpdatelStatus
+ * HTTP status code 200 is always accepted. If this parameter is
+ * not null, the value is also considered a valid HTTP status
+ * code on success; e.g., 204.
+ * @return JSON object with success or error information.
+ */
+ protected String updateItem(HttpServletRequest request, DmaapDataItem itemType, String itemId,
+ Integer scUpdatelStatus) {
+ String outboundJson = null;
+ try {
+ User appUser = UserUtils.getUserSession(request);
+ if (appUser == null || appUser.getLoginId() == null || appUser.getLoginId().length() == 0)
+ throw new Exception("updateItem: Failed to get Login ID");
+ DmaapAccess access = getSelectedDmaapAccess(appUser.getLoginId());
+ if (access == null) // leap into exception handler
+ throw new Exception("No DMaaP access profiles are configured.");
+ String jsonContent = getBody(request);
+ outboundJson = updateDmaapItem(access, appUser.getLoginId(), itemType, itemId, jsonContent,
+ scUpdatelStatus);
+ } catch (Exception ex) {
+ outboundJson = buildJsonError(500, "Failed to update DMaaP item " + itemType.name(), ex);
+ }
+
+ return outboundJson;
+ }
+
+ /**
+ * Deletes an item of the specified type with the specified ID.
+ *
+ * @param dmaapAccess
+ * Access details for the DMaaP REST API
+ * @param itemType
+ * DMaaP item type to delete
+ * @param itemId
+ * Item identification
+ * @param scAddlStatus
+ * HTTP status code 200 is always accepted. If this parameter is
+ * not null, the value is also considered a valid HTTP status
+ * code on success; e.g., 204.
+ * @return On success, returns a JSON block as String with any data returned
+ * by the REST client.
+ * @throws Exception
+ * On any failure.
+ */
+ private String deleteDmaapItem(DmaapAccess dmaapAccess, DmaapDataItem itemType, String itemId, Integer scAddlStatus)
+ throws Exception {
+ DmaapBcRestClient restClient = getDmaapBcRestClient(dmaapAccess);
+ HttpStatusAndResponse<Object> hsr = null;
+ switch (itemType) {
+ case DR_FEED:
+ hsr = restClient.deleteFeed(itemId);
+ break;
+ case DR_PUB:
+ hsr = restClient.deleteDRPub(itemId);
+ break;
+ case DR_SUB:
+ hsr = restClient.deleteDRSub(itemId);
+ break;
+ case MR_TOPIC:
+ hsr = restClient.deleteTopic(itemId);
+ break;
+ case MR_CLIENT:
+ hsr = restClient.deleteMRClient(itemId);
+ break;
+ default:
+ throw new Exception("deleteDmaapItem: pgmr error, unimplemented case: " + itemType.name());
+ }
+
+ // Build result here
+ String outboundJson = null;
+ if (hsr.getStatusCode() == HttpServletResponse.SC_OK
+ || (scAddlStatus != null && hsr.getStatusCode() == scAddlStatus)) {
+ outboundJson = buildJsonSuccess(hsr.getStatusCode(), hsr.getResponseString());
+ } else {
+ throw new Exception("Unexpected HTTP response code " + Integer.toString(hsr.getStatusCode())
+ + " with content " + hsr.getResponseString());
+ }
+ return outboundJson;
+ }
+
+ /**
+ * Deletes the specified DMaaP item. This method traps errors and constructs
+ * an appropriate JSON block if an error happens.
+ *
+ * @param request
+ * Used to obtain user info from the active session
+ * @param itemType
+ * DMaaP item type to delete
+ * @param itemId
+ * item ID to delete
+ * @param scAddlStatus
+ * HTTP status code 200 is always accepted. If this parameter is
+ * not null, the value is also considered a valid HTTP status
+ * code on success; e.g., 204.
+ * @return JSON object with success or error information.
+ */
+ protected String deleteItem(HttpServletRequest request, DmaapDataItem itemType, String itemId,
+ Integer scAddlStatus) {
+ String outboundJson = null;
+ try {
+ User appUser = UserUtils.getUserSession(request);
+ if (appUser == null || appUser.getLoginId() == null || appUser.getLoginId().length() == 0)
+ throw new Exception("deleteItem: Failed to get Login ID");
+ DmaapAccess selected = getSelectedDmaapAccess(appUser.getLoginId());
+ if (selected == null) // leap into exception handler
+ throw new Exception("No DMaaP access profiles are configured.");
+ outboundJson = deleteDmaapItem(selected, itemType, itemId, scAddlStatus);
+ } catch (Exception ex) {
+ outboundJson = buildJsonError(500, "Failed to delete DMaaP item " + itemType.name() + " ID " + itemId, ex);
+ }
+ return outboundJson;
+ }
+
+}
diff --git a/dcae_dmaapbc_webapp/dbca-common/src/main/java/org/onap/dcae/dmaapbc/dbcapp/controller/DmaapAccessController.java b/dcae_dmaapbc_webapp/dbca-common/src/main/java/org/onap/dcae/dmaapbc/dbcapp/controller/DmaapAccessController.java
new file mode 100644
index 0000000..bd5c420
--- /dev/null
+++ b/dcae_dmaapbc_webapp/dbca-common/src/main/java/org/onap/dcae/dmaapbc/dbcapp/controller/DmaapAccessController.java
@@ -0,0 +1,356 @@
+package org.onap.dcae.dmaapbc.dbcapp.controller;
+
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.servlet.http.HttpServletRequest;
+
+import org.onap.dcae.dmaapbc.client.DmaapBcRestClient;
+import org.onap.dcae.dmaapbc.dbcapp.domain.DmaapAccess;
+import org.onap.dcae.dmaapbc.model.Dmaap;
+import org.onap.dcae.dmaapbc.model.DmaapObject;
+import org.onap.dcae.dmaapbc.model.ErrorResponse;
+import org.openecomp.portalsdk.core.domain.User;
+import org.openecomp.portalsdk.core.logging.logic.EELFLoggerDelegate;
+import org.openecomp.portalsdk.core.util.SystemProperties;
+import org.openecomp.portalsdk.core.web.support.UserUtils;
+import org.slf4j.MDC;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.ResponseBody;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+/**
+ * DMaaP Access controller: serves Ajax requests made by Angular on pages where
+ * the user adds, edits and deletes DMaaP access profiles. This controller must
+ * defend the database against rogue requests including SQL injection attacks.
+ */
+@Controller
+@RequestMapping("/")
+public class DmaapAccessController extends DbcappRestrictedBaseController {
+
+ /**
+ * Logger that conforms with ECOMP guidelines
+ */
+ private static EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(DmaapAccessController.class);
+
+ private static final String DMAAP_ACCESS_PATH = "/dmaap_access";
+ private static final String SELECT_DMAAP_ACCESS_PATH = "/select_dmaap_access";
+
+ /**
+ * For general use in these methods
+ */
+ private final ObjectMapper mapper;
+
+ /**
+ * Never forget that Spring autowires fields AFTER the constructor is
+ * called.
+ */
+ public DmaapAccessController() {
+ mapper = new ObjectMapper();
+ }
+
+ /**
+ * Gets a list of DMaaP access profiles for this user from the database and
+ * returns them in a JSON array nested within a response object. Traps errors and constructs an appropriate JSON block if an error
+ * happens.
+ *
+ * See {@link #getOrInitDmaapAccessList(String)}.
+ *
+ * @param request
+ * HttpServletRequest
+ * @return JSON with access profiles, or an error JSON if the request fails.
+ */
+ @RequestMapping(value = { DMAAP_ACCESS_PATH }, method = RequestMethod.GET, produces = "application/json")
+ @ResponseBody
+ public String getDmaapAccessList(HttpServletRequest request) {
+ MDC.put(SystemProperties.AUDITLOG_BEGIN_TIMESTAMP, DataBusHomeController.logDateFormat.format(new Date()));
+ logger.setRequestBasedDefaultsIntoGlobalLoggingContext(request, DataBusHomeController.APP_NAME);
+ String outboundJson = null;
+ try {
+ User appUser = UserUtils.getUserSession(request);
+ if (appUser == null || appUser.getLoginId() == null || appUser.getLoginId().length() == 0)
+ throw new Exception("getDmaapAccessList: Failed to get Login ID");
+ List<DmaapAccess> dbAccessList = getOrInitDmaapAccessList(appUser.getLoginId());
+ // Wrap the list in the status indicator.
+ Map<String, Object> model = new HashMap<String, Object>();
+ model.put(STATUS_RESPONSE_KEY, new Integer(200));
+ model.put(DATA_RESPONSE_KEY, dbAccessList);
+ outboundJson = mapper.writeValueAsString(model);
+ } catch (Exception ex) {
+ outboundJson = buildJsonError(500, "Failed to get DMaaP access profile list", ex);
+ }
+ MDC.put(SystemProperties.AUDITLOG_END_TIMESTAMP, DataBusHomeController.logDateFormat.format(new Date()));
+ logger.info(EELFLoggerDelegate.auditLogger, request.getMethod() + request.getRequestURI());
+ return outboundJson;
+ }
+
+ /**
+ * Adds a DMaaP access profile for the requesting user ID; ignores any
+ * values for row ID and user ID in the body. Traps errors and
+ * constructs an appropriate JSON block if an error happens.
+ *
+ * @param request
+ * HttpServletRequest
+ * @return Trivial JSON object indicating success or failure.
+ */
+ @RequestMapping(value = { DMAAP_ACCESS_PATH }, method = RequestMethod.POST, produces = "application/json")
+ @ResponseBody
+ public String addDmaapAccess(HttpServletRequest request) {
+ MDC.put(SystemProperties.AUDITLOG_BEGIN_TIMESTAMP, DataBusHomeController.logDateFormat.format(new Date()));
+ logger.setRequestBasedDefaultsIntoGlobalLoggingContext(request, DataBusHomeController.APP_NAME);
+ String outboundJson = null;
+ try {
+ User appUser = UserUtils.getUserSession(request);
+ if (appUser == null || appUser.getLoginId() == null || appUser.getLoginId().length() == 0)
+ throw new Exception("addDmaapAccess: Failed to get Login ID");
+
+ DmaapAccess dmaapAccess = mapper.readValue(request.getReader(), DmaapAccess.class);
+ logger.debug("addDmaapAccess: received object: {} ", dmaapAccess);
+
+ // Null out ID to get an auto-generated ID
+ dmaapAccess.setId(null);
+ // Overwrite any submitted user id
+ dmaapAccess.setUserId(appUser.getLoginId());
+ // Encrypt password
+ if (dmaapAccess.getPassword() != null)
+ dmaapAccess.encryptPassword(dmaapAccess.getPassword());
+
+ // Create a new row
+ getDmaapAccessService().saveDmaapAccess(dmaapAccess);
+
+ // Answer success
+ outboundJson = buildJsonSuccess(200, null);
+ } catch (Exception ex) {
+ outboundJson = buildJsonError(500, "Failed to add DMaaP access profile", ex);
+ }
+ MDC.put(SystemProperties.AUDITLOG_END_TIMESTAMP, DataBusHomeController.logDateFormat.format(new Date()));
+ logger.info(EELFLoggerDelegate.auditLogger, request.getMethod() + request.getRequestURI());
+ return outboundJson;
+ }
+
+ /**
+ * Updates a DMaaP access profile if the row user ID matches the requesting
+ * user ID. Traps errors and
+ * constructs an appropriate JSON block if an error happens.
+ *
+ * @param id
+ * Path parameter with ID of the DMaaP access profile
+ * @param request
+ * HttpServletRequest
+ * @return Trivial JSON object indicating success or failure.
+ */
+ @RequestMapping(value = { DMAAP_ACCESS_PATH + "/{id}" }, method = RequestMethod.PUT, produces = "application/json")
+ @ResponseBody
+ public String updateDmaapAccess(@PathVariable("id") long id, HttpServletRequest request) {
+ MDC.put(SystemProperties.AUDITLOG_BEGIN_TIMESTAMP, DataBusHomeController.logDateFormat.format(new Date()));
+ logger.setRequestBasedDefaultsIntoGlobalLoggingContext(request, DataBusHomeController.APP_NAME);
+ String outboundJson = null;
+ try {
+ User appUser = UserUtils.getUserSession(request);
+ if (appUser == null || appUser.getLoginId() == null || appUser.getLoginId().length() == 0)
+ throw new Exception("updateDmaapAccess: Failed to get Login ID");
+
+ DmaapAccess domainObj = getDmaapAccessService().getDmaapAccess(id);
+ if (!appUser.getLoginId().equals(domainObj.getUserId()))
+ throw new Exception("updateDmaapAccess: mismatch of appUser and row user ID");
+
+ DmaapAccess dmaapAccess = mapper.readValue(request.getReader(), DmaapAccess.class);
+ logger.debug("updateDmaapAccess: received object: {} ", dmaapAccess);
+
+ // Use the path-parameter id; don't trust the one in the object
+ dmaapAccess.setId(id);
+ // Encrypt password if present
+ if (dmaapAccess.getPassword() != null)
+ dmaapAccess.encryptPassword(dmaapAccess.getPassword());
+
+ // Update the existing row
+ getDmaapAccessService().saveDmaapAccess(dmaapAccess);
+
+ // Answer "OK"
+ outboundJson = buildJsonSuccess(200, null);
+ } catch (Exception ex) {
+ outboundJson = buildJsonError(500, "Failed to update DMaaP access profile", ex);
+ }
+ MDC.put(SystemProperties.AUDITLOG_END_TIMESTAMP, DataBusHomeController.logDateFormat.format(new Date()));
+ logger.info(EELFLoggerDelegate.auditLogger, request.getMethod() + request.getRequestURI());
+ return outboundJson;
+ }
+
+ /**
+ * Deletes a DMaaP access profile if the row user ID matches the requesting
+ * user ID. Traps errors and
+ * constructs an appropriate JSON block if an error happens.
+ *
+ * @param id
+ * Path parameter with ID of the DMaaP access profile
+ * @param request
+ * HttpServletRequest
+ * @return Trivial JSON object indicating success or failure (altho this is
+ * slightly contrary to conventions for a DELETE method)
+ */
+ @RequestMapping(value = {
+ DMAAP_ACCESS_PATH + "/{id}" }, method = RequestMethod.DELETE, produces = "application/json")
+ @ResponseBody
+ public String deleteDmaapAccess(@PathVariable("id") long id, HttpServletRequest request) {
+ MDC.put(SystemProperties.AUDITLOG_BEGIN_TIMESTAMP, DataBusHomeController.logDateFormat.format(new Date()));
+ logger.setRequestBasedDefaultsIntoGlobalLoggingContext(request, DataBusHomeController.APP_NAME);
+ String outboundJson = null;
+ try {
+ User appUser = UserUtils.getUserSession(request);
+ if (appUser == null || appUser.getLoginId() == null || appUser.getLoginId().length() == 0)
+ throw new Exception("deleteDmaapAccess: Failed to get Login ID");
+ // Validate that this user owns the row with the specified ID
+ DmaapAccess domainObj = getDmaapAccessService().getDmaapAccess(id);
+ if (!appUser.getLoginId().equals(domainObj.getUserId()))
+ throw new Exception("deleteDmaapAccess: mismatch of appUser and row user ID");
+
+ getDmaapAccessService().deleteDmaapAccess(id);
+
+ // Answer "OK"
+ outboundJson = buildJsonSuccess(200, null);
+ } catch (Exception ex) {
+ outboundJson = buildJsonError(500, "Failed to delete DMaaP access profile", ex);
+ }
+ MDC.put(SystemProperties.AUDITLOG_END_TIMESTAMP, DataBusHomeController.logDateFormat.format(new Date()));
+ logger.info(EELFLoggerDelegate.auditLogger, request.getMethod() + request.getRequestURI());
+ return outboundJson;
+ }
+
+ /**
+ * Gets the selected DMaaP access row for the requesting user.
+ *
+ * See {@link #getSelectedDmaapAccess(String)}
+ *
+ * @param request
+ * HttpServletRequest
+ * @return JSON object with one DmaapAccessProfile, or an error
+ */
+ @RequestMapping(value = { SELECT_DMAAP_ACCESS_PATH }, method = RequestMethod.GET, produces = "application/json")
+ @ResponseBody
+ public String getSelectedDmaapAccessProfile(HttpServletRequest request) {
+ MDC.put(SystemProperties.AUDITLOG_BEGIN_TIMESTAMP, DataBusHomeController.logDateFormat.format(new Date()));
+ logger.setRequestBasedDefaultsIntoGlobalLoggingContext(request, DataBusHomeController.APP_NAME);
+ String outboundJson = null;
+ try {
+ User appUser = UserUtils.getUserSession(request);
+ if (appUser == null || appUser.getLoginId() == null || appUser.getLoginId().length() == 0)
+ throw new Exception("getSelectedDmaapAccessProfile: Failed to get Login ID");
+ DmaapAccess selected = super.getSelectedDmaapAccess(appUser.getLoginId());
+ // clone and decrypt
+ DmaapAccess clear = new DmaapAccess(selected);
+ try {
+ clear.setPassword(clear.decryptPassword());
+ } catch (Exception ex) {
+ // Should never happen
+ throw new RuntimeException("getSelectedDmaapAccessProfile: Failed to decrypt password", ex);
+ }
+ outboundJson = buildJsonSuccess(200, clear);
+ } catch (Exception ex) {
+ outboundJson = buildJsonError(500, "Failed to get selected DMaaP access profile", ex);
+ }
+ MDC.put(SystemProperties.AUDITLOG_END_TIMESTAMP, DataBusHomeController.logDateFormat.format(new Date()));
+ logger.info(EELFLoggerDelegate.auditLogger, request.getMethod() + request.getRequestURI());
+ return outboundJson;
+ }
+
+ /**
+ * Marks the DMaaP access row as selected (first choice) for the requesting
+ * user if the row user ID matches the requesting user ID. As a side effect,
+ * removes selected marking from all other user rows. Returns status,
+ * additionally an error message on failure. Traps errors and
+ * constructs an appropriate JSON block if an error happens.
+ *
+ * Choice of PUT is fairly arbitrary - there is no body, but GET is for
+ * actions that do not change data.
+ *
+ * @param id
+ * Path parameter with ID of the DMaaP access profile
+ * @param request
+ * HttpServletRequest
+ * @return Trivial JSON object indicating success or failure.
+ */
+ @RequestMapping(value = {
+ SELECT_DMAAP_ACCESS_PATH + "/{id}" }, method = RequestMethod.PUT, produces = "application/json")
+ @ResponseBody
+ public String selectDmaapAccess(@PathVariable("id") long id, HttpServletRequest request) {
+ MDC.put(SystemProperties.AUDITLOG_BEGIN_TIMESTAMP, DataBusHomeController.logDateFormat.format(new Date()));
+ logger.setRequestBasedDefaultsIntoGlobalLoggingContext(request, DataBusHomeController.APP_NAME);
+ String outboundJson = null;
+ try {
+ User appUser = UserUtils.getUserSession(request);
+ if (appUser == null || appUser.getLoginId() == null || appUser.getLoginId().length() == 0)
+ throw new Exception("selectDmaapAccess: Failed to get Login UID");
+ // A little inefficient in that it requires 3 database accesses;
+ // probably could be done in 1 with some sophisticated SQL.
+ List<DmaapAccess> dmaapAccessList = getDmaapAccessService().getDmaapAccessList(appUser.getLoginId());
+ for (DmaapAccess dmaap : dmaapAccessList) {
+ // Only write out the changed rows.
+ boolean changed = false;
+ if (id == dmaap.getId()) {
+ changed = !dmaap.getSelected();
+ dmaap.setSelected(true);
+ } else {
+ changed = dmaap.getSelected();
+ dmaap.setSelected(false);
+ }
+ if (changed)
+ getDmaapAccessService().saveDmaapAccess(dmaap);
+ }
+
+ // Answer OK
+ outboundJson = buildJsonSuccess(200, null);
+ } catch (Exception ex) {
+ outboundJson = buildJsonError(500, "Failed to select a DMaaP access profile", ex);
+ }
+ MDC.put(SystemProperties.AUDITLOG_END_TIMESTAMP, DataBusHomeController.logDateFormat.format(new Date()));
+ logger.info(EELFLoggerDelegate.auditLogger, request.getMethod() + request.getRequestURI());
+ return outboundJson;
+ }
+
+ /**
+ * Tests the URL in the DMaaP access profile object. Traps errors and
+ * constructs an appropriate JSON block if an error happens.
+ *
+ * @param request
+ * HttpServletRequest
+ * @return JSON with a Dmaap object (which has name etc.) on success, error
+ * on failure.
+ */
+ @RequestMapping(value = { "test_dmaap_access" }, method = RequestMethod.POST, produces = "application/json")
+ @ResponseBody
+ public String testDmaapAccess(HttpServletRequest request) {
+ MDC.put(SystemProperties.AUDITLOG_BEGIN_TIMESTAMP, DataBusHomeController.logDateFormat.format(new Date()));
+ logger.setRequestBasedDefaultsIntoGlobalLoggingContext(request, DataBusHomeController.APP_NAME);
+ String outboundJson = null;
+ try {
+ DmaapAccess dmaapAccess = mapper.readValue(request.getReader(), DmaapAccess.class);
+ logger.debug("testDmaapAccess: received object: {} ", dmaapAccess);
+ if (dmaapAccess.getDmaapUrl() == null || dmaapAccess.getDmaapUrl().trim().length() == 0)
+ throw new Exception("Null or empty URL");
+
+ DmaapBcRestClient restClient = getDmaapBcRestClient(dmaapAccess);
+ // Get the instance so the page can display its name
+ DmaapObject dmaap = restClient.getDmaap();
+ if (dmaap instanceof Dmaap) {
+ outboundJson = buildJsonSuccess(200, dmaap);
+ } else {
+ // Bad credentials lands here.
+ ErrorResponse err = (ErrorResponse) dmaap;
+ outboundJson = buildJsonError(500, "Test failed: " + err.getMessage(), null);
+ }
+ } catch (Exception ex) {
+ // This is entirely likely; e.e., unknown host exception on typo.
+ outboundJson = buildJsonError(500, "Invalid DMaaP URL", ex);
+ }
+ MDC.put(SystemProperties.AUDITLOG_END_TIMESTAMP, DataBusHomeController.logDateFormat.format(new Date()));
+ logger.info(EELFLoggerDelegate.auditLogger, request.getMethod() + request.getRequestURI());
+ return outboundJson;
+ }
+
+}
diff --git a/dcae_dmaapbc_webapp/dbca-common/src/main/java/org/onap/dcae/dmaapbc/dbcapp/controller/HealthCheckController.java b/dcae_dmaapbc_webapp/dbca-common/src/main/java/org/onap/dcae/dmaapbc/dbcapp/controller/HealthCheckController.java
new file mode 100644
index 0000000..820cd5b
--- /dev/null
+++ b/dcae_dmaapbc_webapp/dbca-common/src/main/java/org/onap/dcae/dmaapbc/dbcapp/controller/HealthCheckController.java
@@ -0,0 +1,142 @@
+package org.onap.dcae.dmaapbc.dbcapp.controller;
+
+import java.util.Date;
+
+import javax.servlet.http.HttpServletRequest;
+
+import org.onap.dcae.dmaapbc.dbcapp.service.DmaapAccessService;
+import org.openecomp.portalsdk.core.controller.UnRestrictedBaseController;
+import org.openecomp.portalsdk.core.logging.logic.EELFLoggerDelegate;
+import org.openecomp.portalsdk.core.util.SystemProperties;
+import org.slf4j.MDC;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.EnableAspectJAutoProxy;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * This controller responds to probes for application health, returning a JSON
+ * body to indicate current status.
+ */
+@RestController
+@Configuration
+@EnableAspectJAutoProxy
+@RequestMapping("/")
+public class HealthCheckController extends UnRestrictedBaseController {
+
+ private EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(HealthCheckController.class);
+
+ private static final String HEALTH_CHECK_PATH = "/healthCheck";
+
+ @Autowired
+ private DmaapAccessService dmaapAccessService;
+
+ /**
+ * Model for JSON response with health-check results.
+ */
+ public class HealthStatus {
+ // Either 200 or 500
+ public int statusCode;
+ // Additional detail in case of error, empty in case of success.
+ public String message;
+
+ public HealthStatus(int code, String msg) {
+ this.statusCode = code;
+ this.message = msg;
+ }
+
+ public int getStatusCode() {
+ return statusCode;
+ }
+
+ public void setStatusCode(int code) {
+ this.statusCode = code;
+ }
+
+ public String getMessage() {
+ return message;
+ }
+
+ public void setMessage(String msg) {
+ this.message = msg;
+ }
+ }
+
+ /**
+ * Checks application health by making a trivial query to the database.
+ *
+ * @param request
+ * HttpServletRequest
+ * @return 200 if database access succeeds, 500 if it fails.
+ */
+ @RequestMapping(value = { HEALTH_CHECK_PATH }, method = RequestMethod.GET, produces = "application/json")
+ public HealthStatus healthCheck(HttpServletRequest request) {
+ logger.setRequestBasedDefaultsIntoGlobalLoggingContext(request, DataBusHomeController.APP_NAME);
+ logger.info(EELFLoggerDelegate.auditLogger, request.getMethod() + request.getRequestURI());
+ HealthStatus healthStatus = null;
+ try {
+ logger.debug(EELFLoggerDelegate.debugLogger, "Performing health check");
+ dmaapAccessService.getDmaapAccessCount();
+ healthStatus = new HealthStatus(200, "health check succeeded");
+ } catch (Exception ex) {
+ logger.error(EELFLoggerDelegate.errorLogger, "Failed to perform health check", ex);
+ healthStatus = new HealthStatus(500, "health check failed: " + ex.toString());
+ }
+ return healthStatus;
+ }
+
+ /**
+ * This implementation does not support suspend/resume.
+ *
+ * @param request
+ * HttpServletRequest
+ * @return Trivial success
+ */
+ @RequestMapping(value = {
+ HEALTH_CHECK_PATH + "/suspend" }, method = RequestMethod.GET, produces = "application/json")
+ public HealthStatus healthCheckSuspend(HttpServletRequest request) {
+ MDC.put(SystemProperties.AUDITLOG_BEGIN_TIMESTAMP, DataBusHomeController.logDateFormat.format(new Date()));
+ logger.setRequestBasedDefaultsIntoGlobalLoggingContext(request, DataBusHomeController.APP_NAME);
+ HealthStatus response = new HealthStatus(200, "suspend not implemented");
+ MDC.put(SystemProperties.AUDITLOG_END_TIMESTAMP, DataBusHomeController.logDateFormat.format(new Date()));
+ logger.info(EELFLoggerDelegate.auditLogger, request.getMethod() + request.getRequestURI());
+ return response;
+ }
+
+ /**
+ * This implementation does not support suspend/resume.
+ *
+ * @param request
+ * HttpServletRequest
+ * @return Trivial success
+ */
+ @RequestMapping(value = {
+ HEALTH_CHECK_PATH + "/resume" }, method = RequestMethod.GET, produces = "application/json")
+ public HealthStatus healthCheckResume(HttpServletRequest request) {
+ MDC.put(SystemProperties.AUDITLOG_BEGIN_TIMESTAMP, DataBusHomeController.logDateFormat.format(new Date()));
+ logger.setRequestBasedDefaultsIntoGlobalLoggingContext(request, DataBusHomeController.APP_NAME);
+ HealthStatus response = new HealthStatus(200, "resume not implemented");
+ MDC.put(SystemProperties.AUDITLOG_END_TIMESTAMP, DataBusHomeController.logDateFormat.format(new Date()));
+ logger.info(EELFLoggerDelegate.auditLogger, request.getMethod() + request.getRequestURI());
+ return response;
+ }
+
+ /**
+ * Answers ping request without checking the application health.
+ *
+ * @param request
+ * HttpServletRequest
+ * @return Trivial success
+ */
+ @RequestMapping(value = { HEALTH_CHECK_PATH + "/ping" }, method = RequestMethod.GET, produces = "application/json")
+ public HealthStatus ping(HttpServletRequest request) {
+ MDC.put(SystemProperties.AUDITLOG_BEGIN_TIMESTAMP, DataBusHomeController.logDateFormat.format(new Date()));
+ logger.setRequestBasedDefaultsIntoGlobalLoggingContext(request, DataBusHomeController.APP_NAME);
+ HealthStatus response = new HealthStatus(200, "ping received");
+ MDC.put(SystemProperties.AUDITLOG_END_TIMESTAMP, DataBusHomeController.logDateFormat.format(new Date()));
+ logger.info(EELFLoggerDelegate.auditLogger, request.getMethod() + request.getRequestURI());
+ return response;
+ }
+}
diff --git a/dcae_dmaapbc_webapp/dbca-common/src/main/java/org/onap/dcae/dmaapbc/dbcapp/controller/MessageRouterController.java b/dcae_dmaapbc_webapp/dbca-common/src/main/java/org/onap/dcae/dmaapbc/dbcapp/controller/MessageRouterController.java
new file mode 100644
index 0000000..70bc90a
--- /dev/null
+++ b/dcae_dmaapbc_webapp/dbca-common/src/main/java/org/onap/dcae/dmaapbc/dbcapp/controller/MessageRouterController.java
@@ -0,0 +1,207 @@
+package org.onap.dcae.dmaapbc.dbcapp.controller;
+
+import java.util.Date;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.openecomp.portalsdk.core.logging.logic.EELFLoggerDelegate;
+import org.openecomp.portalsdk.core.util.SystemProperties;
+import org.slf4j.MDC;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.ResponseBody;
+
+/**
+ * Message Router controller: serves Ajax requests made by Angular scripts on
+ * pages that show topics and clients.
+ */
+@Controller
+@RequestMapping("/")
+public class MessageRouterController extends DbcappRestrictedBaseController {
+
+ private static EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(MessageRouterController.class);
+
+ private static final String TOPIC_PATH = "/mr_topic";
+ private static final String CLIENT_PATH = "/mr_client";
+
+ public MessageRouterController() {
+ }
+
+ /**
+ * Answers a request for one page of message router topics. See
+ * {@link #getItemListForPageWrapper(HttpServletRequest, DmaapDataItem)}
+ *
+ * @param request
+ * HttpServletRequest
+ * @return One page of MR topics
+ */
+ @RequestMapping(value = { TOPIC_PATH }, method = RequestMethod.GET, produces = "application/json")
+ @ResponseBody
+ public String getMRTopicsByPage(HttpServletRequest request) {
+ MDC.put(SystemProperties.AUDITLOG_BEGIN_TIMESTAMP, DataBusHomeController.logDateFormat.format(new Date()));
+ logger.setRequestBasedDefaultsIntoGlobalLoggingContext(request, DataBusHomeController.APP_NAME);
+ String response = getItemListForPageWrapper(request, DmaapDataItem.MR_TOPIC);
+ MDC.put(SystemProperties.AUDITLOG_END_TIMESTAMP, DataBusHomeController.logDateFormat.format(new Date()));
+ logger.info(EELFLoggerDelegate.auditLogger, request.getMethod() + request.getRequestURI());
+ return response;
+ }
+
+ /**
+ * Answers a request for one page of message router clients. See
+ * {@link #getItemListForPageWrapper(HttpServletRequest, DmaapDataItem)}
+ *
+ * @param request
+ * HttpServletRequest
+ * @return One page of MR clients
+ */
+ @RequestMapping(value = { CLIENT_PATH }, method = RequestMethod.GET, produces = "application/json")
+ @ResponseBody
+ public String getMRClientsByPage(HttpServletRequest request) {
+ MDC.put(SystemProperties.AUDITLOG_BEGIN_TIMESTAMP, DataBusHomeController.logDateFormat.format(new Date()));
+ logger.setRequestBasedDefaultsIntoGlobalLoggingContext(request, DataBusHomeController.APP_NAME);
+ String response = getItemListForPageWrapper(request, DmaapDataItem.MR_CLIENT);
+ MDC.put(SystemProperties.AUDITLOG_END_TIMESTAMP, DataBusHomeController.logDateFormat.format(new Date()));
+ logger.info(EELFLoggerDelegate.auditLogger, request.getMethod() + request.getRequestURI());
+ return response;
+ }
+
+ /**
+ * Adds a topic with the specified information. Expects a JSON block in the
+ * request body - a Topic object.
+ *
+ * @param request
+ * HttpServletRequest
+ * @return JSON success/failure response
+ */
+ @RequestMapping(value = { TOPIC_PATH }, method = RequestMethod.POST, produces = "application/json")
+ @ResponseBody
+ public String addTopic(HttpServletRequest request) {
+ MDC.put(SystemProperties.AUDITLOG_BEGIN_TIMESTAMP, DataBusHomeController.logDateFormat.format(new Date()));
+ logger.setRequestBasedDefaultsIntoGlobalLoggingContext(request, DataBusHomeController.APP_NAME);
+ String response = addItem(request, DmaapDataItem.MR_TOPIC, HttpServletResponse.SC_CREATED);
+ MDC.put(SystemProperties.AUDITLOG_END_TIMESTAMP, DataBusHomeController.logDateFormat.format(new Date()));
+ logger.info(EELFLoggerDelegate.auditLogger, request.getMethod() + request.getRequestURI());
+ return response;
+ }
+
+ /**
+ * Adds a client with the specified information. Expects a JSON block in the
+ * request body - a MR_Client object.
+ *
+ * @param request
+ * HttpServletRequest
+ * @return JSON success/failure response
+ */
+ @RequestMapping(value = { CLIENT_PATH }, method = RequestMethod.POST, produces = "application/json")
+ @ResponseBody
+ public String addMRClient(HttpServletRequest request) {
+ MDC.put(SystemProperties.AUDITLOG_BEGIN_TIMESTAMP, DataBusHomeController.logDateFormat.format(new Date()));
+ logger.setRequestBasedDefaultsIntoGlobalLoggingContext(request, DataBusHomeController.APP_NAME);
+ String response = addItem(request, DmaapDataItem.MR_CLIENT, HttpServletResponse.SC_CREATED);
+ MDC.put(SystemProperties.AUDITLOG_END_TIMESTAMP, DataBusHomeController.logDateFormat.format(new Date()));
+ logger.info(EELFLoggerDelegate.auditLogger, request.getMethod() + request.getRequestURI());
+ return response;
+ }
+
+ /**
+ * Updates a topic with the specified information. Expects a JSON block in
+ * the request body - a Topic object.
+ *
+ * Writes a JSON object as an HTTP response; on success it has a "status"
+ * and possibly a "data" item; on failure, also has an "error" item.
+ *
+ * @param id
+ * ID of the topic to update
+ * @param request
+ * HttpServletRequest
+ * @return JSON success/failure response
+ */
+ @RequestMapping(value = { TOPIC_PATH + "/{id}" }, method = RequestMethod.PUT, produces = "application/json")
+ @ResponseBody
+ public String updateTopic(@PathVariable("id") long id, HttpServletRequest request) {
+ MDC.put(SystemProperties.AUDITLOG_BEGIN_TIMESTAMP, DataBusHomeController.logDateFormat.format(new Date()));
+ logger.setRequestBasedDefaultsIntoGlobalLoggingContext(request, DataBusHomeController.APP_NAME);
+ String response = updateItem(request, DmaapDataItem.MR_TOPIC, Long.toString(id), null);
+ MDC.put(SystemProperties.AUDITLOG_END_TIMESTAMP, DataBusHomeController.logDateFormat.format(new Date()));
+ logger.info(EELFLoggerDelegate.auditLogger, request.getMethod() + request.getRequestURI());
+ return response;
+ }
+
+ /**
+ * Updates a client with the specified information. Expects a JSON block in
+ * the request body - a MR_Client object.
+ *
+ * Writes a JSON object as an HTTP response; on success it has a "status"
+ * and possibly a "data" item; on failure, also has an "error" item.
+ *
+ * @param id
+ * ID of the client to update
+ * @param request
+ * HttpServletRequest
+ * @return JSON success/failure response
+ */
+ @RequestMapping(value = { CLIENT_PATH + "/{id}" }, method = RequestMethod.PUT, produces = "application/json")
+ @ResponseBody
+ public String updateMRClient(@PathVariable("id") long id, HttpServletRequest request) {
+ MDC.put(SystemProperties.AUDITLOG_BEGIN_TIMESTAMP, DataBusHomeController.logDateFormat.format(new Date()));
+ logger.setRequestBasedDefaultsIntoGlobalLoggingContext(request, DataBusHomeController.APP_NAME);
+ String response = updateItem(request, DmaapDataItem.MR_CLIENT, Long.toString(id), null);
+ MDC.put(SystemProperties.AUDITLOG_END_TIMESTAMP, DataBusHomeController.logDateFormat.format(new Date()));
+ logger.info(EELFLoggerDelegate.auditLogger, request.getMethod() + request.getRequestURI());
+ return response;
+ }
+
+ /**
+ * Deletes a topic with the FQTN ID specified as a path parameter.
+ *
+ * FQTN is a string of dot-separated names. Spring, in its infinite wisdom,
+ * truncates extensions on dotted path parameters; e.g., "foo.json" becomes
+ * "foo". Avoid truncation here with the extra ":.+" incantation at the end.
+ *
+ * Writes a JSON object as an HTTP response; on success it only has "status"
+ * item; on failure, also has an "error" item.
+ *
+ * @param id
+ * Path parameter with object ID
+ * @param request
+ * HttpServletRequest
+ * @return JSON success/failure response
+ */
+ @RequestMapping(value = { "/mr_topic/{id:.+}" }, method = RequestMethod.DELETE, produces = "application/json")
+ @ResponseBody
+ public String deleteTopic(@PathVariable("id") String id, HttpServletRequest request) {
+ MDC.put(SystemProperties.AUDITLOG_BEGIN_TIMESTAMP, DataBusHomeController.logDateFormat.format(new Date()));
+ logger.setRequestBasedDefaultsIntoGlobalLoggingContext(request, DataBusHomeController.APP_NAME);
+ String response = deleteItem(request, DmaapDataItem.MR_TOPIC, id, 204);
+ MDC.put(SystemProperties.AUDITLOG_END_TIMESTAMP, DataBusHomeController.logDateFormat.format(new Date()));
+ logger.info(EELFLoggerDelegate.auditLogger, request.getMethod() + request.getRequestURI());
+ return response;
+ }
+
+ /**
+ * Deletes a client with the mrClientId specified as a path parameter.
+ *
+ * Writes a JSON object as an HTTP response; on success it only has "status"
+ * item; on failure, also has an "error" item.
+ *
+ * @param id
+ * Path parameter with object ID
+ * @param request
+ * HttpServletRequest
+ * @return JSON success/failure response
+ */
+ @RequestMapping(value = { "/mr_client/{id}" }, method = RequestMethod.DELETE, produces = "application/json")
+ @ResponseBody
+ public String deleteMRClient(@PathVariable("id") long id, HttpServletRequest request) {
+ MDC.put(SystemProperties.AUDITLOG_BEGIN_TIMESTAMP, DataBusHomeController.logDateFormat.format(new Date()));
+ logger.setRequestBasedDefaultsIntoGlobalLoggingContext(request, DataBusHomeController.APP_NAME);
+ String response = deleteItem(request, DmaapDataItem.MR_CLIENT, Long.toString(id), null);
+ MDC.put(SystemProperties.AUDITLOG_END_TIMESTAMP, DataBusHomeController.logDateFormat.format(new Date()));
+ logger.info(EELFLoggerDelegate.auditLogger, request.getMethod() + request.getRequestURI());
+ return response;
+ }
+
+}