summaryrefslogtreecommitdiffstats
path: root/integrity-audit/src/main/java/org
diff options
context:
space:
mode:
Diffstat (limited to 'integrity-audit/src/main/java/org')
-rw-r--r--integrity-audit/src/main/java/org/openecomp/policy/common/ia/AuditThread.java769
-rw-r--r--integrity-audit/src/main/java/org/openecomp/policy/common/ia/DbAudit.java464
-rw-r--r--integrity-audit/src/main/java/org/openecomp/policy/common/ia/DbAuditException.java37
-rw-r--r--integrity-audit/src/main/java/org/openecomp/policy/common/ia/DbDAO.java740
-rw-r--r--integrity-audit/src/main/java/org/openecomp/policy/common/ia/DbDaoTransactionException.java37
-rw-r--r--integrity-audit/src/main/java/org/openecomp/policy/common/ia/IntegrityAudit.java241
-rw-r--r--integrity-audit/src/main/java/org/openecomp/policy/common/ia/IntegrityAuditProperties.java54
-rw-r--r--integrity-audit/src/main/java/org/openecomp/policy/common/ia/IntegrityAuditPropertiesException.java37
-rw-r--r--integrity-audit/src/main/java/org/openecomp/policy/common/ia/jpa/IntegrityAuditEntity.java204
9 files changed, 2583 insertions, 0 deletions
diff --git a/integrity-audit/src/main/java/org/openecomp/policy/common/ia/AuditThread.java b/integrity-audit/src/main/java/org/openecomp/policy/common/ia/AuditThread.java
new file mode 100644
index 00000000..2319f211
--- /dev/null
+++ b/integrity-audit/src/main/java/org/openecomp/policy/common/ia/AuditThread.java
@@ -0,0 +1,769 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Integrity Audit
+ * ================================================================================
+ * Copyright (C) 2017 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.openecomp.policy.common.ia;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.Date;
+import java.util.List;
+import java.util.Properties;
+//import org.apache.log4j.Logger;
+
+
+import org.openecomp.policy.common.ia.jpa.IntegrityAuditEntity;
+import org.openecomp.policy.common.logging.eelf.MessageCodes;
+import org.openecomp.policy.common.logging.flexlogger.FlexLogger;
+import org.openecomp.policy.common.logging.flexlogger.Logger;
+
+/**
+ * AuditThread is the main thread for the IntegrityAudit
+ *
+ */
+public class AuditThread extends Thread {
+
+ private static final Logger logger = FlexLogger.getLogger(AuditThread.class);
+
+ /*
+ * Number of milliseconds that must elapse for audit to be considered
+ * complete. It's public for access by JUnit test logic.
+ */
+ public static final long AUDIT_COMPLETION_INTERVAL = 30000;
+
+ /*
+ * Number of iterations for audit simulation.
+ */
+ public static final long AUDIT_SIMULATION_ITERATIONS = 3;
+
+ /*
+ * Number of milliseconds to sleep between audit simulation iterations. It's
+ * public for access by JUnit test logic.
+ */
+ public static final long AUDIT_SIMULATION_SLEEP_INTERVAL = 5000;
+
+ /*
+ * Unless audit has already been run on this entity, number of milliseconds
+ * to sleep between audit thread iterations. If audit has already been run,
+ * we sleep integrityAuditPeriodMillis.
+ */
+ private static final long AUDIT_THREAD_SLEEP_INTERVAL = 5000;
+
+ /*
+ * DB access class.
+ */
+ private DbDAO dbDAO;
+
+ /*
+ * E.g. pdp_xacml
+ */
+ private String nodeType;
+
+ /*
+ * Persistence unit for which this audit is being run.
+ */
+ private String persistenceUnit;
+
+ /*
+ * Name of this resource
+ */
+ private String resourceName;
+
+ /*
+ * E.g. DB_DRIVER, SITE_NAME, NODE_TYPE
+ */
+ private Properties properties;
+
+ /*
+ * See IntegrityAudit class for usage.
+ */
+ private int integrityAuditPeriodMillis;
+
+ /*
+ * The containing IntegrityAudit instance
+ */
+ private IntegrityAudit integrityAudit;
+
+ /**
+ * AuditThread constructor
+ * @param resourceName
+ * @param persistenceUnit
+ * @param properties
+ * @param integrityAuditPeriodSeconds
+ * @param integrityAudit
+ * @throws Exception
+ */
+ public AuditThread(String resourceName, String persistenceUnit,
+ Properties properties, int integrityAuditPeriodSeconds, IntegrityAudit integrityAudit)
+ throws Exception {
+ this.resourceName = resourceName;
+ this.persistenceUnit = persistenceUnit;
+ this.properties = properties;
+ this.integrityAuditPeriodMillis = integrityAuditPeriodSeconds * 1000;
+ this.integrityAudit = integrityAudit;
+
+ /*
+ * The DbDAO Constructor registers this node in the IntegrityAuditEntity
+ * table. Each resource (node) inserts its own name, persistenceUnit, DB
+ * access properties and other pertinent properties in the table. This
+ * allows the audit on each node to compare its own version of the
+ * entities for the persistenceUnit in question with the versions from
+ * all other nodes of similar type.
+ */
+ dbDAO = new DbDAO(this.resourceName, this.persistenceUnit,
+ this.properties);
+ this.nodeType = properties.getProperty(IntegrityAuditProperties.NODE_TYPE);
+
+ }
+
+ public void run() {
+
+ logger.info("AuditThread.run: Entering");
+
+ try {
+
+ /*
+ * Triggers change in designation, unless no other viable candidate.
+ */
+ boolean auditCompleted = false;
+
+ DbAudit dbAudit = new DbAudit(dbDAO);
+
+ IntegrityAuditEntity entityCurrentlyDesignated = null;
+ IntegrityAuditEntity thisEntity = null;
+ integrityAudit.setThreadInitialized(true); // An exception will set
+ // it to false
+
+ while (true) {
+ try{
+
+ /*
+ * It may have been awhile since we last cycled through this
+ * loop, so refresh the list of IntegrityAuditEntities.
+ */
+ List<IntegrityAuditEntity> integrityAuditEntityList = getIntegrityAuditEntityList();
+
+ /*
+ * We could've set entityCurrentlyDesignated as a side effect of
+ * getIntegrityAuditEntityList(), but then we would've had to
+ * make entityCurrentlyDesignated a class level attribute. Using
+ * this approach, we can keep it local to the run() method.
+ */
+ entityCurrentlyDesignated = getEntityCurrentlyDesignated(integrityAuditEntityList);
+
+ /*
+ * Need to refresh thisEntity each time through loop, because we
+ * need a fresh version of lastUpdated.
+ */
+ thisEntity = getThisEntity(integrityAuditEntityList);
+
+ /*
+ * If we haven't done the audit yet, note that we're current and
+ * see if we're designated.
+ */
+ if (!auditCompleted) {
+ dbDAO.setLastUpdated();
+
+ /*
+ * If no current designation or currently designated node is
+ * stale, see if we're the next node to be designated.
+ */
+ if (entityCurrentlyDesignated == null
+ || isStale(entityCurrentlyDesignated)) {
+ IntegrityAuditEntity designationCandidate = getDesignationCandidate(integrityAuditEntityList);
+
+ /*
+ * If we're the next node to be designated, run the
+ * audit.
+ */
+ if (designationCandidate.getResourceName().equals(
+ this.resourceName)) {
+ runAudit(dbAudit);
+ auditCompleted = true;
+ } else {
+ if (logger.isDebugEnabled()) {
+ logger.debug("AuditThread.run: designationCandidate, "
+ + designationCandidate
+ .getResourceName()
+ + ", not this entity, "
+ + thisEntity.getResourceName());
+ }
+ }
+
+ /*
+ * Application may have been stopped and restarted, in
+ * which case we might be designated but auditCompleted
+ * will have been reset to false, so account for this.
+ */
+ } else if (thisEntity.getResourceName().equals(
+ entityCurrentlyDesignated.getResourceName())) {
+
+ if (logger.isDebugEnabled()) {
+ logger.debug("AuditThread.run: Re-running audit for "
+ + thisEntity.getResourceName());
+ }
+ runAudit(dbAudit);
+ auditCompleted = true;
+
+ } else {
+ if (logger.isDebugEnabled()) {
+ logger.debug("AuditThread.run: Currently designated node, "
+ + entityCurrentlyDesignated
+ .getResourceName()
+ + ", not yet stale and not this node");
+ }
+ }
+
+
+ /*
+ * Audit already completed on this node, so allow the node
+ * to go stale until twice the AUDIT_COMPLETION_PERIOD has
+ * elapsed. This should give plenty of time for another node
+ * (if another node is out there) to pick up designation.
+ */
+ } else {
+
+ auditCompleted = resetAuditCompleted(auditCompleted,
+ thisEntity);
+
+ }
+
+ /*
+ * If we've just run audit, sleep per the
+ * integrity_audit_period_seconds property, otherwise just sleep
+ * the normal interval.
+ */
+ if (auditCompleted) {
+
+ if (logger.isDebugEnabled()) {
+ logger.debug("AuditThread.run: Audit completed; resourceName="
+ + this.resourceName
+ + " sleeping "
+ + integrityAuditPeriodMillis + "ms");
+ }
+ Thread.sleep(integrityAuditPeriodMillis);
+ if (logger.isDebugEnabled()) {
+ logger.debug("AuditThread.run: resourceName="
+ + this.resourceName + " awaking from "
+ + integrityAuditPeriodMillis + "ms sleep");
+ }
+
+ } else {
+
+ if (logger.isDebugEnabled()) {
+ logger.debug("AuditThread.run: resourceName="
+ + this.resourceName + ": Sleeping "
+ + AuditThread.AUDIT_THREAD_SLEEP_INTERVAL
+ + "ms");
+ }
+ Thread.sleep(AuditThread.AUDIT_THREAD_SLEEP_INTERVAL);
+ if (logger.isDebugEnabled()) {
+ logger.debug("AuditThread.run: resourceName="
+ + this.resourceName + ": Awaking from "
+ + AuditThread.AUDIT_THREAD_SLEEP_INTERVAL
+ + "ms sleep");
+ }
+
+ }
+ } catch (Exception e){
+ String msg = "AuditThread.run loop - Exception thrown: " + e.getMessage()
+ + "; Will try audit again in " + (integrityAuditPeriodMillis/1000) + " seconds";
+ logger.error(MessageCodes.EXCEPTION_ERROR, e, msg);
+ // Sleep and try again later
+ Thread.sleep(integrityAuditPeriodMillis);
+ continue;
+ }
+
+ }
+
+ } catch (Exception e) {
+ String msg = "AuditThread.run: Could not start audit loop. Exception thrown; message="+ e.getMessage();
+ logger.error(MessageCodes.EXCEPTION_ERROR, e, msg);
+ integrityAudit.setThreadInitialized(false);
+ }
+
+ logger.info("AuditThread.run: Exiting");
+ }
+
+ /*
+ * Used to create a list that is sorted lexicographically by resourceName.
+ */
+ Comparator<IntegrityAuditEntity> comparator = new Comparator<IntegrityAuditEntity>() {
+ @Override
+ public int compare(final IntegrityAuditEntity r1,
+ final IntegrityAuditEntity r2) {
+ return r1.getResourceName().compareTo(r2.getResourceName());
+ }
+ };
+
+ /**
+ * getDesignationCandidate()
+ * Using round robin algorithm, gets next candidate to be designated. Assumes
+ * list is sorted lexicographically by resourceName.
+ */
+ private IntegrityAuditEntity getDesignationCandidate(
+ List<IntegrityAuditEntity> integrityAuditEntityList) {
+
+ //Note: assumes integrityAuditEntityList is already lexicographically sorted by resourceName
+
+ if (logger.isDebugEnabled()) {
+ logger.debug("getDesignationCandidate: Entering, integrityAuditEntityList.size()="
+ + integrityAuditEntityList.size());
+ }
+
+ IntegrityAuditEntity designationCandidate = null;
+ IntegrityAuditEntity thisEntity = null;
+
+ int designatedEntityIndex = -1;
+ int entityIndex = 0;
+ int priorCandidateIndex = -1;
+ int subsequentCandidateIndex = -1;
+
+ for (IntegrityAuditEntity integrityAuditEntity : integrityAuditEntityList) {
+
+ if (logger.isDebugEnabled()) {
+ logIntegrityAuditEntity(integrityAuditEntity);
+ }
+
+ if (integrityAuditEntity.getResourceName()
+ .equals(this.resourceName)) {
+ if (logger.isDebugEnabled()) {
+ logger.debug("getDesignationCandidate: thisEntity="
+ + integrityAuditEntity.getResourceName());
+ }
+ thisEntity = integrityAuditEntity;
+ }
+
+ if (integrityAuditEntity.isDesignated()) {
+ if (logger.isDebugEnabled()) {
+ logger.debug("getDesignationCandidate: Currently designated entity resourceName="
+ + integrityAuditEntity.getResourceName()
+ + ", persistenceUnit="
+ + integrityAuditEntity.getPersistenceUnit()
+ + ", lastUpdated="
+ + integrityAuditEntity.getLastUpdated()
+ + ", entityIndex=" + entityIndex);
+ }
+ designatedEntityIndex = entityIndex;
+
+ /*
+ * Entity not currently designated
+ */
+ } else {
+
+ /*
+ * See if non-designated entity is stale.
+ */
+ if (isStale(integrityAuditEntity)) {
+
+ if (logger.isDebugEnabled()) {
+ logger.debug("getDesignationCandidate: Entity is stale; resourceName="
+ + integrityAuditEntity.getResourceName()
+ + ", persistenceUnit="
+ + integrityAuditEntity.getPersistenceUnit()
+ + ", lastUpdated="
+ + integrityAuditEntity.getLastUpdated()
+ + ", entityIndex=" + entityIndex);
+ }
+
+ /*
+ * Entity is current.
+ */
+ } else {
+
+ if (designatedEntityIndex == -1) {
+
+ if (priorCandidateIndex == -1) {
+ if (logger.isDebugEnabled()) {
+ logger.debug("getDesignationCandidate: Prior candidate found, resourceName="
+ + integrityAuditEntity
+ .getResourceName()
+ + ", persistenceUnit="
+ + integrityAuditEntity
+ .getPersistenceUnit()
+ + ", lastUpdated="
+ + integrityAuditEntity.getLastUpdated()
+ + ", entityIndex=" + entityIndex);
+ }
+ priorCandidateIndex = entityIndex;
+ } else {
+ if (logger.isDebugEnabled()) {
+ logger.debug("getDesignationCandidate: Prior entity current but prior candidate already found; resourceName="
+ + integrityAuditEntity
+ .getResourceName()
+ + ", persistenceUnit="
+ + integrityAuditEntity
+ .getPersistenceUnit()
+ + ", lastUpdated="
+ + integrityAuditEntity.getLastUpdated()
+ + ", entityIndex=" + entityIndex);
+ }
+ }
+ } else {
+ if (subsequentCandidateIndex == -1) {
+ if (logger.isDebugEnabled()) {
+ logger.debug("getDesignationCandidate: Subsequent candidate found, resourceName="
+ + integrityAuditEntity
+ .getResourceName()
+ + ", persistenceUnit="
+ + integrityAuditEntity
+ .getPersistenceUnit()
+ + ", lastUpdated="
+ + integrityAuditEntity.getLastUpdated()
+ + ", entityIndex=" + entityIndex);
+ }
+ subsequentCandidateIndex = entityIndex;
+ } else {
+ if (logger.isDebugEnabled()) {
+ logger.debug("getDesignationCandidate: Subsequent entity current but subsequent candidate already found; resourceName="
+ + integrityAuditEntity
+ .getResourceName()
+ + ", persistenceUnit="
+ + integrityAuditEntity
+ .getPersistenceUnit()
+ + ", lastUpdated="
+ + integrityAuditEntity.getLastUpdated()
+ + ", entityIndex=" + entityIndex);
+ }
+ }
+ }
+
+ } // end entity is current
+
+ } // end entity not currently designated
+
+ entityIndex++;
+
+ } // end for loop
+
+ /*
+ * Per round robin algorithm, if a current entity is found that is
+ * lexicographically after the currently designated entity, this entity
+ * becomes the designation candidate. If no current entity is found that
+ * is lexicographically after currently designated entity, we cycle back
+ * to beginning of list and pick the first current entity as the
+ * designation candidate.
+ */
+ if (subsequentCandidateIndex != -1) {
+ designationCandidate = integrityAuditEntityList
+ .get(subsequentCandidateIndex);
+ if (logger.isDebugEnabled()) {
+ logger.debug("getDesignationCandidate: Exiting and returning subsequent designationCandidate="
+ + designationCandidate.getResourceName());
+ }
+ } else {
+ if (priorCandidateIndex != -1) {
+ designationCandidate = integrityAuditEntityList
+ .get(priorCandidateIndex);
+ if (logger.isDebugEnabled()) {
+ logger.debug("getDesignationCandidate: Exiting and returning prior designationCandidate="
+ + designationCandidate.getResourceName());
+ }
+ } else {
+ logger.debug("getDesignationCandidate: No subsequent or prior candidate found; designating thisEntity, resourceName="
+ + thisEntity.getResourceName());
+ designationCandidate = thisEntity;
+ }
+ }
+
+ return designationCandidate;
+
+ }
+
+ /**
+ * getEntityCurrentlyDesignated()
+ * Returns entity that is currently designated.
+ * @param integrityAuditEntityList
+ * @return
+ */
+ private IntegrityAuditEntity getEntityCurrentlyDesignated(
+ List<IntegrityAuditEntity> integrityAuditEntityList) {
+
+ if (logger.isDebugEnabled()) {
+ logger.debug("getEntityCurrentlyDesignated: Entering, integrityAuditEntityList.size="
+ + integrityAuditEntityList.size());
+ }
+
+ IntegrityAuditEntity entityCurrentlyDesignated = null;
+
+ for (IntegrityAuditEntity integrityAuditEntity : integrityAuditEntityList) {
+
+ if (integrityAuditEntity.isDesignated()) {
+ if (logger.isDebugEnabled()) {
+ logger.debug("getEntityCurrentlyDesignated: Currently designated entity resourceName="
+ + integrityAuditEntity.getResourceName()
+ + ", persistenceUnit="
+ + integrityAuditEntity.getPersistenceUnit()
+ + ", lastUpdated="
+ + integrityAuditEntity.getLastUpdated());
+ }
+ entityCurrentlyDesignated = integrityAuditEntity;
+ }
+
+ } // end for loop
+
+ if (logger.isDebugEnabled()) {
+ if (entityCurrentlyDesignated != null) {
+ logger.debug("getEntityCurrentlyDesignated: Exiting and returning entityCurrentlyDesignated="
+ + entityCurrentlyDesignated.getResourceName());
+ } else {
+ logger.debug("getEntityCurrentlyDesignated: Exiting and returning entityCurrentlyDesignated="
+ + entityCurrentlyDesignated);
+ }
+ }
+ return entityCurrentlyDesignated;
+
+ }
+
+ /**
+ * getIntegrityAuditEnityList gets the list of IntegrityAuditEntity
+ * @return
+ * @throws DbDaoTransactionException
+ */
+ private List<IntegrityAuditEntity> getIntegrityAuditEntityList()
+ throws DbDaoTransactionException {
+
+ if (logger.isDebugEnabled()) {
+ logger.debug("getIntegrityAuditEntityList: Entering");
+ }
+
+ /*
+ * Get all records for this nodeType and persistenceUnit and then sort
+ * them lexicographically by resourceName. Get index of designated
+ * entity, if any.
+ */
+ /*
+ * Sorted list of entities for a particular nodeType and
+ * persistenceUnit.
+ */
+ List<IntegrityAuditEntity> integrityAuditEntityList = new ArrayList<IntegrityAuditEntity>();
+ integrityAuditEntityList = dbDAO.getIntegrityAuditEntities(
+ this.persistenceUnit, this.nodeType);
+ int listSize = integrityAuditEntityList.size();
+ if (logger.isDebugEnabled()) {
+ logger.debug("getIntegrityAuditEntityList: Got " + listSize
+ + " IntegrityAuditEntity records");
+ }
+ Collections.sort((List<IntegrityAuditEntity>) integrityAuditEntityList,
+ comparator);
+
+ if (logger.isDebugEnabled()) {
+ logger.debug("getIntegrityAuditEntityList: Exiting and returning integrityAuditEntityList, size="
+ + listSize);
+ }
+ return integrityAuditEntityList;
+
+ }
+
+
+ /**
+ * Returns the IntegrityAuditEntity for this entity.
+ * @param integrityAuditEntityList
+ * @return
+ */
+ private IntegrityAuditEntity getThisEntity(
+ List<IntegrityAuditEntity> integrityAuditEntityList) {
+
+ if (logger.isDebugEnabled()) {
+ logger.debug("getThisEntity: Entering, integrityAuditEntityList.size="
+ + integrityAuditEntityList.size());
+ }
+
+ IntegrityAuditEntity thisEntity = null;
+
+ for (IntegrityAuditEntity integrityAuditEntity : integrityAuditEntityList) {
+
+ if (integrityAuditEntity.getResourceName().equals(this.resourceName)) {
+ if (logger.isDebugEnabled()) {
+ logger.debug("getThisEntity: For this entity, resourceName="
+ + integrityAuditEntity.getResourceName()
+ + ", persistenceUnit="
+ + integrityAuditEntity.getPersistenceUnit()
+ + ", lastUpdated="
+ + integrityAuditEntity.getLastUpdated());
+ }
+ thisEntity = integrityAuditEntity;
+ }
+
+ } // end for loop
+
+ if (logger.isDebugEnabled()) {
+ if (thisEntity != null) {
+ logger.debug("getThisEntity: Exiting and returning thisEntity="
+ + thisEntity.getResourceName());
+ } else {
+ logger.debug("getThisEntity: Exiting and returning thisEntity="
+ + thisEntity);
+ }
+ }
+ return thisEntity;
+
+ }
+
+
+ /**
+ * Returns false if the lastUpdated time for the record in question is more
+ * than AUDIT_COMPLETION_INTERVAL seconds ago. During an audit, lastUpdated is updated every five
+ * seconds or so, but when an audit finishes, the node doing the audit stops
+ * updating lastUpdated.
+ * @param integrityAuditEntity
+ * @return
+ */
+ private boolean isStale(IntegrityAuditEntity integrityAuditEntity) {
+
+ if (logger.isDebugEnabled()) {
+ logger.debug("isStale: Entering, resourceName="
+ + integrityAuditEntity.getResourceName()
+ + ", persistenceUnit="
+ + integrityAuditEntity.getPersistenceUnit()
+ + ", lastUpdated=" + integrityAuditEntity.getLastUpdated());
+ }
+
+ boolean stale = false;
+
+ Date currentTime = new Date();
+ Date lastUpdated = integrityAuditEntity.getLastUpdated();
+
+ /*
+ * If lastUpdated is null, we assume that the audit never ran for that
+ * node.
+ */
+ long lastUpdatedTime = 0;
+ if (lastUpdated != null) {
+ lastUpdatedTime = lastUpdated.getTime();
+ }
+ long timeDifference = currentTime.getTime() - lastUpdatedTime;
+ if (timeDifference > AUDIT_COMPLETION_INTERVAL) {
+ stale = true;
+ }
+
+ if (logger.isDebugEnabled()) {
+ logger.debug("isStale: Exiting and returning stale=" + stale
+ + ", timeDifference=" + timeDifference);
+ }
+
+ return stale;
+ }
+
+ private void logIntegrityAuditEntity(
+ IntegrityAuditEntity integrityAuditEntity) {
+
+ logger.debug("logIntegrityAuditEntity: id="
+ + integrityAuditEntity.getId() + ", jdbcDriver="
+ + integrityAuditEntity.getJdbcDriver() + ", jdbcPassword="
+ + integrityAuditEntity.getJdbcPassword() + ", jdbcUrl="
+ + integrityAuditEntity.getJdbcUrl() + ", jdbcUser="
+ + integrityAuditEntity.getJdbcUser() + ", nodeType="
+ + integrityAuditEntity.getNodeType() + ", persistenceUnit="
+ + integrityAuditEntity.getPersistenceUnit() + ", resourceName="
+ + integrityAuditEntity.getResourceName() + ", site="
+ + integrityAuditEntity.getSite() + ", createdDate="
+ + integrityAuditEntity.getCreatedDate() + ", lastUpdated="
+ + integrityAuditEntity.getLastUpdated() + ", designated="
+ + integrityAuditEntity.isDesignated());
+ }
+
+ /*
+ * If more than (AUDIT_COMPLETION_INTERVAL * 2) milliseconds have elapsed
+ * since we last ran the audit, reset auditCompleted, so
+ *
+ * 1) we'll eventually re-run the audit, if no other node picks up the
+ * designation.
+ *
+ * or
+ *
+ * 2) We'll run the audit when the round robin comes back to us.
+ */
+ private boolean resetAuditCompleted(boolean auditCompleted,
+ IntegrityAuditEntity thisEntity) {
+
+ if (logger.isDebugEnabled()) {
+ logger.debug("resetAuditCompleted: auditCompleted="
+ + auditCompleted + "; for thisEntity, resourceName="
+ + thisEntity.getResourceName() + ", persistenceUnit="
+ + thisEntity.getPersistenceUnit() + ", lastUpdated="
+ + thisEntity.getLastUpdated());
+ }
+
+ long timeDifference = -1;
+
+ Date currentTime = new Date();
+ Date lastUpdated = thisEntity.getLastUpdated();
+
+ long lastUpdatedTime = lastUpdated.getTime();
+ timeDifference = currentTime.getTime() - lastUpdatedTime;
+
+ if (timeDifference > (AUDIT_COMPLETION_INTERVAL * 2)) {
+ if (logger.isDebugEnabled()) {
+ logger.debug("resetAuditCompleted: Resetting auditCompleted for resourceName="
+ + this.resourceName);
+ }
+ auditCompleted = false;
+ } else {
+ if (logger.isDebugEnabled()) {
+ logger.debug("resetAuditCompleted: For resourceName="
+ + resourceName
+ + ", time since last update is only "
+ + timeDifference + "; retaining current value for auditCompleted");
+ }
+ }
+
+ if (logger.isDebugEnabled()) {
+ logger.debug("resetAuditCompleted: Exiting and returning auditCompleted="
+ + auditCompleted + ", timeDifference=" + timeDifference);
+ }
+ return auditCompleted;
+ }
+
+ private void runAudit(DbAudit dbAudit) throws Exception {
+
+ if (logger.isDebugEnabled()) {
+ logger.debug("runAudit: Entering, dbAudit=" + dbAudit
+ + "; notifying other resources that resourceName="
+ + this.resourceName + " is current");
+ }
+
+ /*
+ * changeDesignated marks all other nodes as non-designated and this
+ * node as designated.
+ */
+ dbDAO.changeDesignated(this.resourceName, this.persistenceUnit,
+ this.nodeType);
+
+ if (logger.isDebugEnabled()) {
+ logger.debug("runAudit: Running audit for persistenceUnit="
+ + this.persistenceUnit + " on resourceName="
+ + this.resourceName);
+ }
+ if (IntegrityAudit.isUnitTesting) {
+ dbAudit.dbAuditSimulate(this.resourceName, this.persistenceUnit,
+ this.nodeType);
+ } else {
+ dbAudit.dbAudit(this.resourceName, this.persistenceUnit,
+ this.nodeType);
+ }
+
+ if (logger.isDebugEnabled()) {
+ logger.debug("runAudit: Exiting");
+ }
+
+ }
+
+}
diff --git a/integrity-audit/src/main/java/org/openecomp/policy/common/ia/DbAudit.java b/integrity-audit/src/main/java/org/openecomp/policy/common/ia/DbAudit.java
new file mode 100644
index 00000000..9af89998
--- /dev/null
+++ b/integrity-audit/src/main/java/org/openecomp/policy/common/ia/DbAudit.java
@@ -0,0 +1,464 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Integrity Audit
+ * ================================================================================
+ * Copyright (C) 2017 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.openecomp.policy.common.ia;
+
+import java.io.Serializable;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Properties;
+
+import javax.persistence.Table;
+
+import org.apache.commons.lang3.SerializationUtils;
+import org.apache.commons.lang3.builder.RecursiveToStringStyle;
+import org.apache.commons.lang3.builder.ReflectionToStringBuilder;
+import org.apache.commons.lang3.builder.ToStringStyle;
+//import org.apache.log4j.Logger;
+
+
+
+
+
+import org.openecomp.policy.common.ia.jpa.IntegrityAuditEntity;
+import org.openecomp.policy.common.logging.eelf.MessageCodes;
+import org.openecomp.policy.common.logging.flexlogger.FlexLogger;
+import org.openecomp.policy.common.logging.flexlogger.Logger;
+
+/**
+ * class DbAudit does actual auditing of DB tables.
+ */
+public class DbAudit {
+
+ private static final Logger logger = FlexLogger.getLogger(DbAudit.class);
+
+ DbDAO dbDAO = null;
+
+ public DbAudit(DbDAO dbDAO) {
+
+ if (logger.isDebugEnabled()) {
+ logger.debug("Constructor: Entering");
+ }
+
+ this.dbDAO = dbDAO;
+
+ if (logger.isDebugEnabled()) {
+ logger.debug("Constructor: Exiting");
+ }
+
+ }
+
+ /**
+ * dbAudit actually does the audit
+ * @param resourceName
+ * @param persistenceUnit
+ * @param nodeType
+ * @throws Exception
+ */
+ public void dbAudit(String resourceName, String persistenceUnit, String nodeType) throws Exception {
+
+ if (logger.isDebugEnabled()) {
+ logger.debug("dbAudit: Entering, resourceName=" + resourceName
+ + ", persistenceUnit=" + persistenceUnit + ", nodeType="
+ + nodeType);
+ }
+
+ // Get all IntegrityAudit entries so we can get the DB access info
+ List<IntegrityAuditEntity> iaeList = dbDAO.getIntegrityAuditEntities(persistenceUnit, nodeType);
+ if(iaeList == null || iaeList.isEmpty()){
+
+ String msg = "DbAudit: for node " + resourceName + " Found no IntegrityAuditEntity entries";
+ logger.error(MessageCodes.ERROR_AUDIT, msg);
+ throw new DbAuditException(msg);
+
+ }else if(iaeList.size() == 1){
+
+ Long iaeId = null;
+ String iaeRN = null;
+ String iaeNT = null;
+ String iaeS = null;
+ for (IntegrityAuditEntity iae : iaeList){
+ iaeId = iae.getId();
+ iaeRN = iae.getResourceName();
+ iaeNT = iae.getNodeType();
+ iaeS = iae.getSite();
+ }
+ String msg = "DbAudit: Found only one IntegrityAuditEntity entry:"
+ + " ID = " + iaeId
+ + " ResourceName = " + iaeRN
+ + " NodeType = " + iaeNT
+ + " Site = " + iaeS;
+ logger.warn(msg);
+ return;
+ }
+
+ // Obtain all persistence class names for the PU we are auditing
+ HashSet<String> classNameSet = dbDAO.getPersistenceClassNames();
+ if(classNameSet == null || classNameSet.isEmpty()){
+
+ String msg = "DbAudit: For node " + resourceName + " Found no persistence class names";
+ logger.error(MessageCodes.ERROR_AUDIT, msg);
+ throw new DbAuditException(msg);
+
+ }
+
+ /*
+ * Retrieve myIae. We are going to compare the local class entries against
+ * all other DB nodes. Since the audit is run in a round-robin, every instance
+ * will be compared against every other instance.
+ */
+ IntegrityAuditEntity myIae = dbDAO.getMyIntegrityAuditEntity();
+
+ if(myIae == null){
+
+ String msg = "DbAudit: Found no IntegrityAuditEntity entry for resourceName: " + resourceName
+ + " persistenceUnit: " + persistenceUnit;
+ logger.error(MessageCodes.ERROR_AUDIT, msg);
+ throw new DbAuditException(msg);
+
+ }
+ /*
+ * This is the map of mismatched entries indexed by className. For
+ * each class name there is a list of mismatched entries
+ */
+ HashMap<String,HashSet<Object>> misMatchedMap = new HashMap<String,HashSet<Object>>();
+
+ // We need to keep track of how long the audit is taking
+ long startTime = System.currentTimeMillis();
+
+ // Retrieve all instances of the class for each node
+ if (logger.isDebugEnabled()) {
+ logger.debug("dbAudit: Traversing classNameSet, size=" + classNameSet.size());
+ }
+ for(String clazzName: classNameSet){
+
+ if (logger.isDebugEnabled()) {
+ logger.debug("dbAudit: clazzName=" + clazzName);
+ }
+
+ // all instances of the class for myIae
+ HashMap<Object,Object> myEntries = dbDAO.getAllMyEntries(clazzName);
+ //get a map of the objects indexed by id. Does not necessarily have any entries
+
+ if (logger.isDebugEnabled()) {
+ logger.debug("dbAudit: Traversing iaeList, size=" + iaeList.size());
+ }
+ for (IntegrityAuditEntity iae : iaeList){
+ if(iae.getId() == myIae.getId()){
+ if (logger.isDebugEnabled()) {
+ logger.debug("dbAudit: My Id=" + iae.getId()
+ + ", resourceName=" + iae.getResourceName());
+ }
+ continue; //no need to compare with self
+ } else {
+ if (logger.isDebugEnabled()) {
+ logger.debug("dbAudit: Id=" + iae.getId()
+ + ", resourceName=" + iae.getResourceName());
+ }
+ }
+ // Create properties for the other db node
+ Properties theirProperties = new Properties();
+ theirProperties.put(IntegrityAuditProperties.DB_DRIVER, iae.getJdbcDriver());
+ theirProperties.put(IntegrityAuditProperties.DB_URL, iae.getJdbcUrl());
+ theirProperties.put(IntegrityAuditProperties.DB_USER, iae.getJdbcUser());
+ theirProperties.put(IntegrityAuditProperties.DB_PWD, iae.getJdbcPassword());
+ theirProperties.put(IntegrityAuditProperties.SITE_NAME, iae.getSite());
+ theirProperties.put(IntegrityAuditProperties.NODE_TYPE, iae.getNodeType());
+
+ //get a map of the instances for their iae indexed by id
+ HashMap<Object,Object> theirEntries = dbDAO.getAllEntries(persistenceUnit, theirProperties, clazzName);
+ if (logger.isDebugEnabled()) {
+ logger.debug("dbAudit: For persistenceUnit="
+ + persistenceUnit + ", clazzName=" + clazzName
+ + ", theirEntries.size()="
+ + theirEntries.size());
+ }
+
+ /*
+ * Compare myEntries with theirEntries and get back a set of mismatched IDs.
+ * Collect the IDs for the class where a mismatch occurred. We will check
+ * them again for all nodes later.
+ */
+ HashSet<Object> misMatchedKeySet = compareEntries(myEntries, theirEntries);
+ if(!misMatchedKeySet.isEmpty()){
+ HashSet<Object> misMatchedEntry = misMatchedMap.get(clazzName);
+ if(misMatchedEntry == null){
+ misMatchedMap.put(clazzName, misMatchedKeySet);
+ }else{
+ misMatchedEntry.addAll(misMatchedKeySet);
+ misMatchedMap.put(clazzName, misMatchedEntry);
+ }
+ }
+ } //end for (IntegrityAuditEntity iae : iaeList)
+ //Time check
+ if((System.currentTimeMillis() - startTime) >= 5000){ //5 seconds
+ //update the timestamp
+ dbDAO.setLastUpdated();
+ //reset the startTime
+ startTime=System.currentTimeMillis();
+ }else{
+ //sleep a couple seconds to break up the activity
+ if (logger.isDebugEnabled()) {
+ logger.debug("dbAudit: Sleeping 2 seconds");
+ }
+ Thread.sleep(2000);
+ if (logger.isDebugEnabled()) {
+ logger.debug("dbAudit: Waking from sleep");
+ }
+ }
+ }//end: for(String clazzName: classNameList)
+
+ //check if misMatchedMap is empty
+ if(misMatchedMap.isEmpty()){
+
+ if (logger.isDebugEnabled()) {
+ logger.debug("dbAudit: Exiting, misMatchedMap is empty");
+ }
+ //we are done
+ return;
+ } else {
+ if (logger.isDebugEnabled()) {
+ logger.debug("dbAudit: Doing another comparison; misMatchedMap.size()=" + misMatchedMap.size());
+ }
+ }
+
+ // If misMatchedMap is not empty, retrieve the entries in each misMatched list and compare again
+
+ //classNameSet = (HashSet<String>) misMatchedMap.keySet();
+ classNameSet = new HashSet<String>(misMatchedMap.keySet());
+ // We need to keep track of how long the audit is taking
+ startTime = System.currentTimeMillis();
+
+ // Retrieve all instances of the class for each node
+ if (logger.isDebugEnabled()) {
+ logger.debug("dbAudit: Second comparison; traversing classNameSet, size=" + classNameSet.size());
+ }
+
+ int errorCount = 0;
+
+ for(String clazzName: classNameSet){
+
+ if (logger.isDebugEnabled()) {
+ logger.debug("dbAudit: Second comparison; clazzName=" + clazzName);
+ }
+
+ // all instances of the class for myIae
+ HashSet<Object> keySet = misMatchedMap.get(clazzName);
+ HashMap<Object,Object> myEntries = dbDAO.getAllMyEntries(clazzName, keySet);
+ //get a map of the objects indexed by id
+
+ if (logger.isDebugEnabled()) {
+ logger.debug("dbAudit: Second comparison; traversing iaeList, size=" + iaeList.size());
+ }
+ for (IntegrityAuditEntity iae : iaeList){
+ if(iae.getId() == myIae.getId()){
+ if (logger.isDebugEnabled()) {
+ logger.debug("dbAudit: Second comparison; My Id=" + iae.getId()
+ + ", resourceName=" + iae.getResourceName());
+ }
+ continue; //no need to compare with self
+ } else {
+ if (logger.isDebugEnabled()) {
+ logger.debug("dbAudit: Second comparison; Id=" + iae.getId()
+ + ", resourceName=" + iae.getResourceName());
+ }
+ }
+ // Create properties for the other db node
+ Properties theirProperties = new Properties();
+ theirProperties.put(IntegrityAuditProperties.DB_DRIVER, iae.getJdbcDriver());
+ theirProperties.put(IntegrityAuditProperties.DB_URL, iae.getJdbcUrl());
+ theirProperties.put(IntegrityAuditProperties.DB_USER, iae.getJdbcUser());
+ theirProperties.put(IntegrityAuditProperties.DB_PWD, iae.getJdbcPassword());
+ theirProperties.put(IntegrityAuditProperties.SITE_NAME, iae.getSite());
+ theirProperties.put(IntegrityAuditProperties.NODE_TYPE, iae.getNodeType());
+
+ //get a map of the instances for their iae indexed by id
+ HashMap<Object,Object> theirEntries = dbDAO.getAllEntries(persistenceUnit, theirProperties, clazzName, keySet);
+
+ /*
+ * Compare myEntries with theirEntries and get back a set of mismatched IDs.
+ * Collect the IDs for the class where a mismatch occurred. We will now
+ * write an error log for each.
+ */
+ HashSet<Object> misMatchedKeySet = compareEntries(myEntries, theirEntries);
+ if(!misMatchedKeySet.isEmpty()){
+ String keysString = "";
+ for(Object key: misMatchedKeySet){
+ keysString = keysString.concat(key.toString() + ", ");
+ errorCount ++;
+ }
+ writeAuditSummaryLog(clazzName, resourceName, iae.getResourceName(), keysString);
+ if(logger.isDebugEnabled()){
+ for(Object key : misMatchedKeySet){
+ writeAuditDebugLog(clazzName, resourceName, iae.getResourceName(), myEntries.get(key), theirEntries.get(key));
+ }
+ }
+ }
+ }
+ //Time check
+ if((System.currentTimeMillis() - startTime) >= 5000){ //5 seconds
+ //update the timestamp
+ dbDAO.setLastUpdated();
+ //reset the startTime
+ startTime=System.currentTimeMillis();
+ }else{
+ //sleep a couple seconds to break up the activity
+ if (logger.isDebugEnabled()) {
+ logger.debug("dbAudit: Second comparison; sleeping 2 seconds");
+ }
+ Thread.sleep(2000);
+ if (logger.isDebugEnabled()) {
+ logger.debug("dbAudit: Second comparison; waking from sleep");
+ }
+ }
+ }//end: for(String clazzName: classNameList)
+
+ if(errorCount != 0){
+ String msg = " DB Audit: " + errorCount + " errors found. A large number of errors may indicate DB replication has stopped";
+ logger.error(MessageCodes.ERROR_AUDIT, msg);
+ }
+
+ if (logger.isDebugEnabled()) {
+ logger.debug("dbAudit: Exiting");
+ }
+
+ return; //all done
+ }
+
+ /**
+ * dbAuditSimulate simulates the DB audit
+ * @param resourceName
+ * @param persistenceUnit
+ * @param nodeType
+ * @throws InterruptedException
+ * @throws DbDaoTransactionException
+ */
+ public void dbAuditSimulate(String resourceName, String persistenceUnit,
+ String nodeType) throws InterruptedException,
+ DbDaoTransactionException {
+
+ logger.info("dbAuditSimulate: Starting audit simulation for resourceName="
+ + resourceName + ", persistenceUnit=" + persistenceUnit);
+
+ for (int i = 0; i < AuditThread.AUDIT_SIMULATION_ITERATIONS; i++) {
+ dbDAO.setLastUpdated();
+ logger.info("dbAuditSimulate: i=" + i + ", sleeping "
+ + AuditThread.AUDIT_SIMULATION_SLEEP_INTERVAL + "ms");
+ Thread.sleep(AuditThread.AUDIT_SIMULATION_SLEEP_INTERVAL);
+ }
+
+ logger.info("dbAuditSimulate: Finished audit simulation for resourceName="
+ + resourceName + ", persistenceUnit=" + persistenceUnit);
+
+ }
+
+ /**
+ * compareEntries() will compare the lists of entries from the DB
+ * @param myEntries
+ * @param theirEntries
+ * @return
+ */
+ public HashSet<Object> compareEntries(HashMap<Object,Object> myEntries, HashMap<Object,Object> theirEntries){
+ /*
+ * Compare the entries for the same key in each of the hashmaps. The comparison will be done by serializing the objects
+ * (create a byte array) and then do a byte array comparison. The audit will walk the local repository hash map comparing
+ * to the remote cluster hashmap and then turn it around and walk the remote hashmap and look for any entries that are not
+ * present in the local cluster hashmap.
+ *
+ * If the objects are not identical, the audit will put the object IDs on a list to try after completing the audit of the table
+ * it is currently working on.
+ *
+ */
+ HashSet<Object> misMatchedKeySet = new HashSet<Object>();
+ for(Object key: myEntries.keySet()){
+ byte[] mySerializedEntry = SerializationUtils.serialize((Serializable) myEntries.get(key));
+ byte[] theirSerializedEntry = SerializationUtils.serialize((Serializable) theirEntries.get(key));
+ if(!Arrays.equals(mySerializedEntry, theirSerializedEntry)){
+ logger.debug("compareEntries: For myEntries.key=" + key + ", entries do not match");
+ misMatchedKeySet.add(key);
+ } else {
+ logger.debug("compareEntries: For myEntries.key=" + key + ", entries match");
+ }
+ }
+ //now compare it in the other direction to catch entries in their set that is not in my set
+ for(Object key: theirEntries.keySet()){
+ byte[] mySerializedEntry = SerializationUtils.serialize((Serializable) myEntries.get(key));
+ byte[] theirSerializedEntry = SerializationUtils.serialize((Serializable) theirEntries.get(key));
+ if(!Arrays.equals(mySerializedEntry, theirSerializedEntry)){
+ logger.debug("compareEntries: For theirEntries.key=" + key + ", entries do not match");
+ misMatchedKeySet.add(key);
+ } else {
+ logger.debug("compareEntries: For theirEntries.key=" + key + ", entries match");
+ }
+ }
+
+ //return a Set of the object IDs
+ logger.debug("compareEntries: misMatchedKeySet.size()=" + misMatchedKeySet.size());
+ return misMatchedKeySet;
+ }
+
+ /**
+ * writeAuditDebugLog() writes the mismatched entry details to the debug log
+ * @param clazzName
+ * @param resourceName1
+ * @param resourceName2
+ * @param entry1
+ * @param entry2
+ * @throws ClassNotFoundException
+ */
+ public void writeAuditDebugLog(String clazzName, String resourceName1,
+ String resourceName2, Object entry1, Object entry2) throws ClassNotFoundException{
+ Class<?> entityClass = Class.forName(clazzName);
+ String tableName = entityClass.getAnnotation(Table.class).name();
+ String msg = "\nDB Audit Error: "
+ + "\n Table Name: " + tableName
+ + "\n Entry 1 (short prefix style): " + resourceName1 + ": " + new ReflectionToStringBuilder(entry1,ToStringStyle.SHORT_PREFIX_STYLE).toString()
+ + "\n Entry 2 (short prefix style): " + resourceName2 + ": " + new ReflectionToStringBuilder(entry2,ToStringStyle.SHORT_PREFIX_STYLE).toString()
+ + "\n Entry 1 (recursive style): " + resourceName1 + ": " + new ReflectionToStringBuilder(entry1, new RecursiveToStringStyle()).toString()
+ + "\n Entry 2 (recursive style): " + resourceName2 + ": " + new ReflectionToStringBuilder(entry2, new RecursiveToStringStyle()).toString();
+ logger.debug(msg);
+
+ }
+
+ /**
+ * writeAuditSummaryLog() writes a summary of the DB mismatches to the error log
+ * @param clazzName
+ * @param resourceName1
+ * @param resourceName2
+ * @param keys
+ * @throws ClassNotFoundException
+ */
+ public void writeAuditSummaryLog(String clazzName, String resourceName1,
+ String resourceName2, String keys) throws ClassNotFoundException{
+ Class<?> entityClass = Class.forName(clazzName);
+ String tableName = entityClass.getAnnotation(Table.class).name();
+ String msg = " DB Audit Error: Table Name: " + tableName
+ + "; Mismatch between nodes: " + resourceName1 +" and " + resourceName2
+ + "; Mismatched entries (keys): " + keys;
+ logger.info(msg);
+ }
+
+
+
+
+
+}
diff --git a/integrity-audit/src/main/java/org/openecomp/policy/common/ia/DbAuditException.java b/integrity-audit/src/main/java/org/openecomp/policy/common/ia/DbAuditException.java
new file mode 100644
index 00000000..956dd431
--- /dev/null
+++ b/integrity-audit/src/main/java/org/openecomp/policy/common/ia/DbAuditException.java
@@ -0,0 +1,37 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Integrity Audit
+ * ================================================================================
+ * Copyright (C) 2017 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.openecomp.policy.common.ia;
+
+public class DbAuditException extends Exception{
+ private static final long serialVersionUID = 1L;
+ public DbAuditException() {
+ }
+ public DbAuditException(String message) {
+ super(message);
+ }
+
+ public DbAuditException(Throwable cause) {
+ super(cause);
+ }
+ public DbAuditException(String message, Throwable cause) {
+ super(message, cause);
+ }
+}
diff --git a/integrity-audit/src/main/java/org/openecomp/policy/common/ia/DbDAO.java b/integrity-audit/src/main/java/org/openecomp/policy/common/ia/DbDAO.java
new file mode 100644
index 00000000..70f39a2b
--- /dev/null
+++ b/integrity-audit/src/main/java/org/openecomp/policy/common/ia/DbDAO.java
@@ -0,0 +1,740 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Integrity Audit
+ * ================================================================================
+ * Copyright (C) 2017 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.openecomp.policy.common.ia;
+
+import java.util.Date;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Properties;
+
+import javax.persistence.EntityManager;
+import javax.persistence.EntityManagerFactory;
+import javax.persistence.EntityTransaction;
+import javax.persistence.LockTimeoutException;
+import javax.persistence.Persistence;
+import javax.persistence.PersistenceUnitUtil;
+import javax.persistence.Query;
+import javax.persistence.TypedQuery;
+import javax.persistence.criteria.CriteriaBuilder;
+import javax.persistence.criteria.CriteriaQuery;
+import javax.persistence.criteria.Root;
+import javax.persistence.metamodel.ManagedType;
+import javax.persistence.metamodel.Metamodel;
+
+//import org.apache.log4j.Logger;
+
+import org.openecomp.policy.common.ia.IntegrityAuditProperties.NodeTypeEnum;
+import org.openecomp.policy.common.ia.jpa.IntegrityAuditEntity;
+import org.openecomp.policy.common.logging.flexlogger.FlexLogger;
+import org.openecomp.policy.common.logging.flexlogger.Logger;
+
+/**
+ * class DbDAO provides the inteface to the DBs for the purpose of audits.
+ *
+ */
+public class DbDAO {
+ private static final Logger logger = FlexLogger.getLogger(DbDAO.class.getName());
+ private String resourceName;
+ private String persistenceUnit;
+ private String dbDriver;
+ private String dbUrl;
+ private String dbUser;
+ private String dbPwd;
+ private String siteName;
+ private String nodeType;
+ private Properties properties=null;
+
+ private EntityManagerFactory emf;
+
+ /*
+ * Supports designation serialization.
+ */
+ private static final Object lock = new Object();
+
+
+ /**
+ * DbDAO Constructor
+ * @param resourceName
+ * @param persistenceUnit
+ * @param properties
+ * @throws Exception
+ */
+ public DbDAO(String resourceName, String persistenceUnit, Properties properties) throws Exception {
+ logger.debug("DbDAO contructor: enter");
+
+ validateProperties(resourceName, persistenceUnit, properties);
+
+ emf = Persistence.createEntityManagerFactory(persistenceUnit, properties);
+
+ register();
+
+ logger.debug("DbDAO contructor: exit");
+ }
+
+ /**
+ * validateProperties will validate the properties
+ * @param resourceName
+ * @param persistenceUnit
+ * @param properties
+ * @throws IntegrityAuditPropertiesException
+ */
+ private void validateProperties(String resourceName, String persistenceUnit, Properties properties) throws IntegrityAuditPropertiesException{
+ String badparams="";
+ if(IntegrityAudit.parmsAreBad(resourceName, persistenceUnit, properties, badparams)){
+ String msg = "DbDAO: Bad parameters: badparams" + badparams;
+ throw new IntegrityAuditPropertiesException(msg);
+ }
+ this.resourceName = resourceName;
+ this.persistenceUnit = persistenceUnit;
+ this.dbDriver = properties.getProperty(IntegrityAuditProperties.DB_DRIVER).trim();
+ this.dbUrl = properties.getProperty(IntegrityAuditProperties.DB_URL).trim();
+ this.dbUser = properties.getProperty(IntegrityAuditProperties.DB_USER).trim();
+ this.dbPwd = properties.getProperty(IntegrityAuditProperties.DB_PWD).trim();
+ this.siteName = properties.getProperty(IntegrityAuditProperties.SITE_NAME).trim();
+ this.nodeType = properties.getProperty(IntegrityAuditProperties.NODE_TYPE).trim();
+ this.properties = properties;
+ logger.debug("DbDAO.assignProperties: exit:"
+ + "\nresourceName: " + this.resourceName
+ + "\npersistenceUnit: " + this.persistenceUnit
+ + "\nproperties: " + this.properties);
+ }
+
+ /**
+ * getAllMyEntries gets all the DB entries for a particular class
+ * @param className
+ * @return
+ */
+ public HashMap<Object, Object> getAllMyEntries(String className) {
+ logger.debug("getAllMyEntries: Entering, className="
+ + className);
+ HashMap<Object, Object> resultMap = new HashMap<Object,Object>();
+ EntityManager em = emf.createEntityManager();
+ try{
+ CriteriaBuilder cb = em.getCriteriaBuilder();
+ CriteriaQuery<Object> cq = cb.createQuery();
+ Root<?> rootEntry = cq.from(Class.forName(className));
+ CriteriaQuery<Object> all = cq.select(rootEntry);
+ TypedQuery<Object> allQuery = em.createQuery(all);
+ List<Object> objectList = allQuery.getResultList();
+ //Now create the map
+
+ PersistenceUnitUtil util = emf.getPersistenceUnitUtil();
+ for (Object o: objectList){
+ Object key = util.getIdentifier(o);
+ resultMap.put(key, o);
+ }
+ }catch(Exception e){
+ String msg = "getAllEntries encountered exception: " + e;
+ logger.error(msg);
+ System.out.println(new Date());
+ e.printStackTrace();
+ }
+ em.close();
+ logger.debug("getAllMyEntries: Exit, resultMap.keySet()=" + resultMap.keySet());
+ return resultMap;
+ }
+
+ /**
+ * getAllMyEntries gets all entries for a class
+ * @param className
+ * @param keySet
+ * @return
+ */
+ public HashMap<Object, Object> getAllMyEntries(String className, HashSet<Object> keySet){
+ logger.debug("getAllMyEntries: Entering, className="
+ + className + ",\n keySet=" + keySet);
+
+ HashMap<Object, Object> resultMap = new HashMap<Object,Object>();
+ EntityManager em = emf.createEntityManager();
+ try{
+ Class<?> clazz = Class.forName(className);
+ for(Object key : keySet){
+ Object entry = em.find(clazz, key);
+ resultMap.put(key, entry);
+ }
+ }catch(Exception e){
+ String msg = "getAllMyEntries encountered exception: " + e;
+ logger.error(msg);
+ System.out.println(new Date());
+ e.printStackTrace();
+ }
+ em.close();
+
+ logger.debug("getAllMyEntries: Returning resultMap, size=" + resultMap.size());
+ return resultMap;
+ }
+
+ /**
+ * getAllEntries gets all entriesfor a particular persistence unit adn className
+ * @param persistenceUnit
+ * @param properties
+ * @param className
+ * @return
+ */
+ public HashMap<Object,Object> getAllEntries(String persistenceUnit, Properties properties, String className){
+
+ logger.debug("getAllEntries: Entering, persistenceUnit="
+ + persistenceUnit + ",\n className=" + className);
+ HashMap<Object, Object> resultMap = new HashMap<Object,Object>();
+
+ EntityManagerFactory theEmf = Persistence.createEntityManagerFactory(persistenceUnit, properties);
+ EntityManager em = theEmf.createEntityManager();
+ try{
+ CriteriaBuilder cb = em.getCriteriaBuilder();
+ CriteriaQuery<Object> cq = cb.createQuery();
+ Root<?> rootEntry = cq.from(Class.forName(className));
+ CriteriaQuery<Object> all = cq.select(rootEntry);
+ TypedQuery<Object> allQuery = em.createQuery(all);
+ List<Object> objectList = allQuery.getResultList();
+
+ PersistenceUnitUtil util = theEmf.getPersistenceUnitUtil();
+ for (Object o: objectList){
+ Object key = util.getIdentifier(o);
+ resultMap.put(key, o);
+ }
+ }catch(Exception e){
+ String msg = "getAllEntries encountered exception:" + e;
+ logger.error(msg);
+ System.out.println(new Date());
+ e.printStackTrace();
+ }
+ em.close();
+
+ logger.debug("getAllEntries: Returning resultMap, size=" + resultMap.size());
+
+ return resultMap;
+ }
+
+
+ /**
+ * getAllEntries gest all entries for a persistence unit
+ * @param persistenceUnit
+ * @param properties
+ * @param className
+ * @param keySet
+ * @return
+ */
+
+ public HashMap<Object,Object> getAllEntries(String persistenceUnit, Properties properties, String className, HashSet<Object> keySet){
+ logger.debug("getAllEntries: Entering, persistenceUnit="
+ + persistenceUnit + ",\n properties= " + properties + ",\n className=" + className + ",\n keySet= " + keySet);
+ EntityManagerFactory theEmf = Persistence.createEntityManagerFactory(persistenceUnit, properties);
+ EntityManager em = theEmf.createEntityManager();
+ HashMap<Object, Object> resultMap = new HashMap<Object,Object>();
+ try{
+ Class<?> clazz = Class.forName(className);
+ for(Object key : keySet){
+ Object entry = em.find(clazz, key);
+ resultMap.put(key, entry);
+ }
+ }catch(Exception e){
+ String msg = "getAllEntries encountered exception: " + e;
+ logger.error(msg);
+ System.out.println(new Date());
+ e.printStackTrace();
+ }
+ em.close();
+ logger.debug("getAllEntries: Exit, resultMap, size=" + resultMap.size());
+ return resultMap;
+ }
+
+ /**
+ * getIntegrityAuditEntities() Get all the IntegrityAuditEntities for a particular persistence unit
+ * and node type
+ * @param persistenceUnit
+ * @param nodeType
+ * @return
+ * @throws DbDaoTransactionException
+ */
+ @SuppressWarnings("unchecked")
+ public List<IntegrityAuditEntity> getIntegrityAuditEntities(String persistenceUnit, String nodeType) throws DbDaoTransactionException {
+ logger.debug("getIntegrityAuditEntities: Entering, persistenceUnit="
+ + persistenceUnit + ",\n nodeType= " + nodeType);
+ try{
+ EntityManager em = emf.createEntityManager();
+ // Start a transaction
+ EntityTransaction et = em.getTransaction();
+
+ et.begin();
+
+ // if IntegrityAuditEntity entry exists for resourceName and PU, update it. If not found, create a new entry
+ Query iaequery = em.createQuery("Select i from IntegrityAuditEntity i where i.persistenceUnit=:pu and i.nodeType=:nt");
+ iaequery.setParameter("pu", persistenceUnit);
+ iaequery.setParameter("nt", nodeType);
+
+ List<IntegrityAuditEntity> iaeList = iaequery.getResultList();
+
+ // commit transaction
+ et.commit();
+ em.close();
+ logger.debug("getIntegrityAuditEntities: Exit, iaeList=" + iaeList);
+ return iaeList;
+ }catch (Exception e){
+ String msg = "DbDAO: " + "getIntegrityAuditEntities() " + "ecountered a problem in execution: ";
+ logger.error(msg + e);
+ System.out.println(new Date());
+ e.printStackTrace();
+ throw new DbDaoTransactionException(e);
+ }
+
+ }
+
+ /**
+ * getMyIntegrityAuditEntity() gets my IntegrityAuditEntity
+ * @return
+ * @throws DbDaoTransactionException
+ */
+ public IntegrityAuditEntity getMyIntegrityAuditEntity() throws DbDaoTransactionException{
+ try{
+ EntityManager em = emf.createEntityManager();
+
+ // Start a transaction
+ EntityTransaction et = em.getTransaction();
+
+ et.begin();
+
+ // if IntegrityAuditEntity entry exists for resourceName and PU, retrieve it
+ Query iaequery = em.createQuery("Select i from IntegrityAuditEntity i where i.resourceName=:rn and i.persistenceUnit=:pu");
+ iaequery.setParameter("rn", this.resourceName);
+ iaequery.setParameter("pu", this.persistenceUnit);
+
+ @SuppressWarnings("rawtypes")
+ List iaeList = iaequery.getResultList();
+ IntegrityAuditEntity iae = null;
+
+ if(!iaeList.isEmpty()){
+ //ignores multiple results
+ iae = (IntegrityAuditEntity) iaeList.get(0);
+ // refresh the object from DB in case cached data was returned
+ em.refresh(iae);
+ logger.info("Resource: " + this.resourceName + " with PersistenceUnit: " + this.persistenceUnit
+ + " exists");
+ }else{
+ // If it does not exist, log an error
+ logger.error("Attempting to setLastUpdated"
+ + " on an entry that does not exist:"
+ +" resource " + this.resourceName + " with PersistenceUnit: " + this.persistenceUnit);
+ }
+
+ // close the transaction
+ et.commit();
+ // close the EntityManager
+ em.close();
+
+ return iae;
+ }catch (Exception e){
+ String msg = "DbDAO: " + "setLastUpdated() " + "ecountered a problem in execution: ";
+ logger.error(msg + e);
+ System.out.println(new Date());
+ e.printStackTrace();
+ throw new DbDaoTransactionException(e);
+ }
+ }
+
+
+ /**
+ * getIntegrityAuditEntity() gets the IntegrityAuditEntity with a particular ID
+ * @param id
+ * @return
+ * @throws DbDaoTransactionException
+ */
+ public IntegrityAuditEntity getIntegrityAuditEntity(long id) throws DbDaoTransactionException{
+ try{
+ EntityManager em = emf.createEntityManager();
+
+ // Start a transaction
+ EntityTransaction et = em.getTransaction();
+
+ et.begin();
+
+ IntegrityAuditEntity iae = em.find(IntegrityAuditEntity.class, id);
+
+ et.commit();
+ em.close();
+
+ return iae;
+ }catch (Exception e){
+ String msg = "DbDAO: " + "getIntegrityAuditEntity() " + "ecountered a problem in execution: ";
+ logger.error(msg + e);
+ System.out.println(new Date());
+ e.printStackTrace();
+ throw new DbDaoTransactionException(e);
+ }
+ }
+
+ /**
+ * getPersistenceClassNames() gets all the persistence class names.
+ * @return
+ */
+ public HashSet<String> getPersistenceClassNames(){
+ logger.debug("DbDAO: getPersistenceClassNames() entry");
+ HashSet<String> returnList = new HashSet<String>();
+ final Metamodel mm = emf.getMetamodel();
+ logger.debug("\n" + persistenceUnit +" persistence unit classes:");
+ for (final ManagedType<?> managedType : mm.getManagedTypes()) {
+ Class<?> c = managedType.getJavaType();
+ logger.debug(" " + c.getSimpleName());
+ returnList.add(c.getName()); //the full class name needed to make a query using jpa
+ }
+ logger.debug("DbDAO: getPersistenceClassNames() exit");
+ return returnList;
+ }
+
+ /**
+ * Register the IntegrityAudit instance
+ */
+ private void register() throws DbDaoTransactionException {
+ try{
+ EntityManager em = emf.createEntityManager();
+
+ // Start a transaction
+ EntityTransaction et = em.getTransaction();
+
+ et.begin();
+
+ // if IntegrityAuditEntity entry exists for resourceName and PU, update it. If not found, create a new entry
+ Query iaequery = em.createQuery("Select i from IntegrityAuditEntity i where i.resourceName=:rn and i.persistenceUnit=:pu");
+ iaequery.setParameter("rn", this.resourceName);
+ iaequery.setParameter("pu", this.persistenceUnit);
+
+ @SuppressWarnings("rawtypes")
+ List iaeList = iaequery.getResultList();
+ IntegrityAuditEntity iae = null;
+
+ //If it already exists, we just want to update the properties and lastUpdated date
+ if(!iaeList.isEmpty()){
+ //ignores multiple results
+ iae = (IntegrityAuditEntity) iaeList.get(0);
+ // refresh the object from DB in case cached data was returned
+ em.refresh(iae);
+ logger.info("Resource: " + this.resourceName + " with PersistenceUnit: " + this.persistenceUnit
+ + " exists and entry be updated");
+ }else{
+ // If it does not exist, we also must add teh resourceName, persistenceUnit and designated values
+ logger.info("Adding resource " + resourceName + " with PersistenceUnit: " + this.persistenceUnit
+ + " to IntegrityAuditEntity table");
+ iae = new IntegrityAuditEntity();
+ iae.setResourceName(this.resourceName);
+ iae.setPersistenceUnit(this.persistenceUnit);
+ iae.setDesignated(false);
+ }
+ //update/set properties in entry
+ iae.setSite(this.siteName);
+ iae.setNodeType(this.nodeType);
+ iae.setLastUpdated(new Date());
+ iae.setJdbcDriver(this.dbDriver);
+ iae.setJdbcPassword(this.dbPwd);
+ iae.setJdbcUrl(dbUrl);
+ iae.setJdbcUser(dbUser);
+
+ em.persist(iae);
+ // flush to the DB
+ em.flush();
+
+ // commit transaction
+ et.commit();
+ em.close();
+ }catch (Exception e){
+ String msg = "DbDAO: " + "register() " + "ecountered a problem in execution: ";
+ logger.error(msg + e);
+ System.out.println(new Date());
+ e.printStackTrace();
+ throw new DbDaoTransactionException(e);
+ }
+
+ }
+
+ public void setDesignated(boolean designated) throws DbDaoTransactionException{
+ setDesignated(this.resourceName, this.persistenceUnit, designated);
+ }
+
+
+ public void setDesignated(String rName, String pUnit, boolean desig) throws DbDaoTransactionException{
+ logger.debug("setDesignated: enter, resourceName: " + rName + ", persistenceUnit: "
+ + pUnit + ", designated: " + desig);
+ try{
+
+ EntityManager em = emf.createEntityManager();
+
+ // Start a transaction
+ EntityTransaction et = em.getTransaction();
+
+ et.begin();
+
+ // if IntegrityAuditEntity entry exists for resourceName and PU, update it. If not found, create a new entry
+ Query iaequery = em.createQuery("Select i from IntegrityAuditEntity i where i.resourceName=:rn and i.persistenceUnit=:pu");
+ iaequery.setParameter("rn", rName);
+ iaequery.setParameter("pu", pUnit);
+
+ @SuppressWarnings("rawtypes")
+ List iaeList = iaequery.getResultList();
+ IntegrityAuditEntity iae = null;
+
+ if(!iaeList.isEmpty()){
+ //ignores multiple results
+ iae = (IntegrityAuditEntity) iaeList.get(0);
+ // refresh the object from DB in case cached data was returned
+ em.refresh(iae);
+ logger.info("Resource: " + rName + " with PersistenceUnit: " + pUnit
+ + " exists and designated be updated");
+ iae.setDesignated(desig);
+
+ em.persist(iae);
+ // flush to the DB
+ em.flush();
+ }else{
+ // If it does not exist, log an error
+ logger.error("Attempting to setDesignated("
+ + desig + ") on an entry that does not exist:"
+ +" resource " + rName + " with PersistenceUnit: " + pUnit);
+ }
+
+ // close the transaction
+ et.commit();
+ // close the EntityManager
+ em.close();
+ }catch (Exception e){
+ String msg = "DbDAO: " + "setDesignated() " + "ecountered a problem in execution: ";
+ logger.error(msg + e);
+ System.out.println(new Date());
+ e.printStackTrace();
+ throw new DbDaoTransactionException(e);
+ }
+
+ }
+
+ public void setLastUpdated() throws DbDaoTransactionException{
+ logger.debug("setLastUpdated: enter, resourceName: " + this.resourceName + ", persistenceUnit: "
+ + this.persistenceUnit);
+ try{
+ EntityManager em = emf.createEntityManager();
+
+ // Start a transaction
+ EntityTransaction et = em.getTransaction();
+
+ et.begin();
+
+ // if IntegrityAuditEntity entry exists for resourceName and PU, update it. If not found, create a new entry
+ Query iaequery = em.createQuery("Select i from IntegrityAuditEntity i where i.resourceName=:rn and i.persistenceUnit=:pu");
+ iaequery.setParameter("rn", this.resourceName);
+ iaequery.setParameter("pu", this.persistenceUnit);
+
+ @SuppressWarnings("rawtypes")
+ List iaeList = iaequery.getResultList();
+ IntegrityAuditEntity iae = null;
+
+ if(!iaeList.isEmpty()){
+ //ignores multiple results
+ iae = (IntegrityAuditEntity) iaeList.get(0);
+ // refresh the object from DB in case cached data was returned
+ em.refresh(iae);
+ logger.info("Resource: " + this.resourceName + " with PersistenceUnit: " + this.persistenceUnit
+ + " exists and lastUpdated be updated");
+ iae.setLastUpdated(new Date());
+
+ em.persist(iae);
+ // flush to the DB
+ em.flush();
+ }else{
+ // If it does not exist, log an error
+ logger.error("Attempting to setLastUpdated"
+ + " on an entry that does not exist:"
+ +" resource " + this.resourceName + " with PersistenceUnit: " + this.persistenceUnit);
+ }
+
+ // close the transaction
+ et.commit();
+ // close the EntityManager
+ em.close();
+ }catch (Exception e){
+ String msg = "DbDAO: " + "setLastUpdated() " + "ecountered a problem in execution: ";
+ logger.error(msg + e);
+ System.out.println(new Date());
+ e.printStackTrace();
+ throw new DbDaoTransactionException(e);
+ }
+
+ }
+
+ /**
+ * Normally this method should only be used in a JUnit test environment.
+ * Manually deletes all PDP records in droolspdpentity table.
+ */
+ public int deleteAllIntegrityAuditEntities() throws DbDaoTransactionException {
+
+ try{
+
+ if (!IntegrityAudit.isUnitTesting) {
+ String msg = "DbDAO: " + "deleteAllIntegrityAuditEntities() " + "should only be invoked during JUnit testing";
+ logger.error(msg);
+ throw new DbDaoTransactionException(msg);
+ }
+
+ EntityManager em = emf.createEntityManager();
+ // Start a transaction
+ EntityTransaction et = em.getTransaction();
+
+ et.begin();
+
+ // if IntegrityAuditEntity entry exists for resourceName and PU, update it. If not found, create a new entry
+ Query iaequery = em.createQuery("Delete from IntegrityAuditEntity");
+
+ int returnCode = iaequery.executeUpdate();
+
+ // commit transaction
+ et.commit();
+ em.close();
+
+ logger.info("deleteAllIntegrityAuditEntities: returnCode=" + returnCode);
+
+ return returnCode;
+
+ }catch (Exception e){
+ String msg = "DbDAO: " + "deleteAllIntegrityAuditEntities() " + "encountered a problem in execution: ";
+ logger.error(msg + e);
+ System.out.println(new Date());
+ e.printStackTrace();
+ throw new DbDaoTransactionException(e);
+ }
+
+ }
+
+ /**
+ * Changes designation to specified resourceName
+ *
+ * static lock object in conjunction with synchronized keyword ensures that
+ * designation changes are done serially within a resource. I.e. static lock
+ * ensures that multiple instantiations of DbDAO don't interleave
+ * changeDesignated() invocations and potentially produce simultaneous
+ * designations.
+ *
+ * Optimistic locking (the default, versus pessimistic) is sufficient to
+ * avoid simultaneous designations from interleaved changeDesignated()
+ * invocations from different resources (entities), because it prevents
+ * "dirty" and "non-repeatable" reads.
+ *
+ * See http://www.objectdb.com/api/java/jpa/LockModeType
+ *
+ * and
+ *
+ * http://stackoverflow.com/questions/2120248/how-to-synchronize-a-static-
+ * variable-among-threads-running-different-instances-o
+ */
+ public void changeDesignated(String resourceName, String persistenceUnit,
+ String nodeType) throws DbDaoTransactionException {
+
+ if (logger.isDebugEnabled()) {
+ logger.debug("changeDesignated: Entering, resourceName="
+ + resourceName + ", persistenceUnit=" + persistenceUnit
+ + ", nodeType=" + nodeType);
+ }
+
+ long startTime = System.currentTimeMillis();
+
+ synchronized (lock) {
+
+ EntityManager em = null;
+ try {
+
+ em = emf.createEntityManager();
+ em.getTransaction().begin();
+
+ /*
+ * Define query
+ */
+ Query query = em
+ .createQuery("Select i from IntegrityAuditEntity i where i.persistenceUnit=:pu and i.nodeType=:nt");
+ query.setParameter("pu", persistenceUnit);
+ query.setParameter("nt", nodeType);
+
+ /*
+ * Execute query using pessimistic write lock. This ensures that if anyone else is currently reading
+ * the records we'll throw a LockTimeoutException.
+ */
+ @SuppressWarnings("unchecked")
+ List<IntegrityAuditEntity> integrityAuditEntityList = (List<IntegrityAuditEntity>) query
+ .getResultList();
+ for (Object o : integrityAuditEntityList) {
+ if (o instanceof IntegrityAuditEntity) {
+ IntegrityAuditEntity integrityAuditEntity = (IntegrityAuditEntity) o;
+ if (integrityAuditEntity.getResourceName().equals(
+ resourceName)) {
+ if (logger.isDebugEnabled()) {
+ logger.debug("changeDesignated: Designating resourceName="
+ + integrityAuditEntity
+ .getResourceName());
+ }
+ integrityAuditEntity.setDesignated(true);
+ } else {
+ if (logger.isDebugEnabled()) {
+ logger.debug("changeDesignated: Removing designation from resourceName="
+ + integrityAuditEntity
+ .getResourceName());
+ }
+ integrityAuditEntity.setDesignated(false);
+ }
+ }
+ }
+
+ if (logger.isDebugEnabled()) {
+ logger.debug("changeDesignated: Committing designation to resourceName="
+ + resourceName);
+ }
+ em.getTransaction().commit();
+
+ /*
+ * If we get a LockTimeoutException, no harm done really. We'll
+ * probably be successful on the next attempt. The odds of
+ * another DbDAO instance on this entity or another entity
+ * attempting a simultaneous IntegrityAuditEntity table
+ * read/update are pretty slim (we're only in this method for
+ * two or three milliseconds)
+ */
+ } catch (LockTimeoutException e) {
+ em.getTransaction().rollback();
+ String msg = "DbDAO: " + "changeDesignated() "
+ + "caught LockTimeoutException, message=" + e.getMessage();
+ logger.error(msg + e);
+ System.out.println(new Date());
+ e.printStackTrace();
+ throw new DbDaoTransactionException(msg, e);
+ } catch (Exception e) {
+ em.getTransaction().rollback();
+ String msg = "DbDAO: " + "changeDesignated() "
+ + "caught Exception, message=" + e.getMessage();
+ logger.error(msg + e);
+ System.out.println(new Date());
+ e.printStackTrace();
+ throw new DbDaoTransactionException(msg, e);
+ }
+
+ } // end synchronized block
+
+ if (logger.isDebugEnabled()) {
+ logger.debug("changeDesignated: Exiting; time expended="
+ + (System.currentTimeMillis() - startTime) + "ms");
+ }
+
+ }
+
+
+}
diff --git a/integrity-audit/src/main/java/org/openecomp/policy/common/ia/DbDaoTransactionException.java b/integrity-audit/src/main/java/org/openecomp/policy/common/ia/DbDaoTransactionException.java
new file mode 100644
index 00000000..fc2fea03
--- /dev/null
+++ b/integrity-audit/src/main/java/org/openecomp/policy/common/ia/DbDaoTransactionException.java
@@ -0,0 +1,37 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Integrity Audit
+ * ================================================================================
+ * Copyright (C) 2017 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.openecomp.policy.common.ia;
+
+public class DbDaoTransactionException extends Exception{
+ private static final long serialVersionUID = 1L;
+ public DbDaoTransactionException() {
+ }
+ public DbDaoTransactionException(String message) {
+ super(message);
+ }
+
+ public DbDaoTransactionException(Throwable cause) {
+ super(cause);
+ }
+ public DbDaoTransactionException(String message, Throwable cause) {
+ super(message, cause);
+ }
+}
diff --git a/integrity-audit/src/main/java/org/openecomp/policy/common/ia/IntegrityAudit.java b/integrity-audit/src/main/java/org/openecomp/policy/common/ia/IntegrityAudit.java
new file mode 100644
index 00000000..1dd260de
--- /dev/null
+++ b/integrity-audit/src/main/java/org/openecomp/policy/common/ia/IntegrityAudit.java
@@ -0,0 +1,241 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Integrity Audit
+ * ================================================================================
+ * Copyright (C) 2017 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.openecomp.policy.common.ia;
+
+import java.util.Properties;
+
+//import org.apache.log4j.Logger;
+
+import org.openecomp.policy.common.ia.IntegrityAuditProperties.NodeTypeEnum;
+import org.openecomp.policy.common.logging.flexlogger.FlexLogger;
+import org.openecomp.policy.common.logging.flexlogger.Logger;
+
+/**
+ * class IntegrityAudit
+ * Audits all persisted entities for all resource clusters for all sites and logs any anomalies.
+ */
+public class IntegrityAudit {
+
+ private static final Logger logger = FlexLogger.getLogger(IntegrityAudit.class);
+
+ public static boolean isUnitTesting;
+ private boolean isThreadInitialized = false;
+
+ AuditThread auditThread = null;
+
+ private String persistenceUnit;
+ private Properties properties;
+ private String resourceName;
+
+
+ /*
+ * This is the audit period in seconds. For example, if it had a value of 3600, the audit
+ * can only run once per hour. If it has a value of 60, it can run once per minute.
+ *
+ * Values:
+ * integrityAuditPeriodSeconds < 0 (negative number) indicates the audit is off
+ * integrityAuditPeriodSecconds == 0 indicates the audit is to run continuously
+ * integrityAuditPeriodSeconds > 0 indicates the audit is to run at most once during the indicated period
+ *
+ */
+ private int integrityAuditPeriodSeconds;
+
+ /**
+ * IntegrityAudit constructor
+ * @param resourceName
+ * @param persistenceUnit
+ * @param properties
+ * @throws Exception
+ */
+ public IntegrityAudit(String resourceName, String persistenceUnit, Properties properties) throws Exception {
+
+ logger.info("Constructor: Entering and checking for nulls");
+ String parmList = "";
+ if (parmsAreBad(resourceName, persistenceUnit, properties, parmList)) {
+ logger.error("Constructor: Parms contain nulls; cannot run audit for resourceName="
+ + resourceName + ", persistenceUnit=" + persistenceUnit
+ + ", bad parameters: " + parmList);
+ throw new Exception(
+ "Constructor: Parms contain nulls; cannot run audit for resourceName="
+ + resourceName + ", persistenceUnit="
+ + persistenceUnit
+ + ", bad parameters: " + parmList);
+ }
+
+ this.persistenceUnit = persistenceUnit;
+ this.properties = properties;
+ this.resourceName = resourceName;
+
+ if(properties.getProperty(IntegrityAuditProperties.AUDIT_PERIOD_SECONDS) != null){ //It is allowed to be null
+ this.integrityAuditPeriodSeconds= Integer.parseInt(properties.getProperty(IntegrityAuditProperties.AUDIT_PERIOD_SECONDS).trim());
+ } else{
+ //If it is null, set it to the default value
+ this.integrityAuditPeriodSeconds = IntegrityAuditProperties.DEFAULT_AUDIT_PERIOD_SECONDS;
+ }
+ logger.info("Constructor: Exiting");
+
+ }
+
+ /**
+ * Used during JUnit testing by AuditPeriodTest.java
+ */
+ public int getIntegrityAuditPeriodSeconds() {
+ return integrityAuditPeriodSeconds;
+ }
+
+ /**
+ * Determine if the nodeType conforms to the required node types
+ */
+ public static boolean isNodeTypeEnum(String nt) {
+ for (NodeTypeEnum n : NodeTypeEnum.values()) {
+ if (n.toString().equals(nt)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+
+ /**
+ * Makes sure we don't try to run the audit with bad parameters.
+ */
+ public static boolean parmsAreBad(String resourceName, String persistenceUnit,
+ Properties properties, String badparams) {
+
+ boolean parmsAreBad = false;
+
+ if(resourceName == null || resourceName.isEmpty()){
+ badparams = badparams.concat("resourceName ");
+ parmsAreBad = true;
+ }
+
+ if(persistenceUnit == null || persistenceUnit.isEmpty()){
+ badparams = badparams.concat("persistenceUnit ");
+ parmsAreBad = true;
+ }
+
+ String dbDriver = properties.getProperty(IntegrityAuditProperties.DB_DRIVER).trim();
+ if(dbDriver == null || dbDriver.isEmpty()){
+ badparams = badparams.concat("dbDriver ");
+ parmsAreBad = true;
+ }
+
+ String dbUrl = properties.getProperty(IntegrityAuditProperties.DB_URL).trim();
+ if(dbUrl == null || dbUrl.isEmpty()){
+ badparams = badparams.concat("dbUrl ");
+ parmsAreBad = true;
+ }
+
+ String dbUser = properties.getProperty(IntegrityAuditProperties.DB_USER).trim();
+ if(dbUser == null || dbUser.isEmpty()){
+ badparams = badparams.concat("dbUser ");
+ parmsAreBad = true;
+ }
+
+ String dbPwd = properties.getProperty(IntegrityAuditProperties.DB_PWD).trim();
+ if(dbPwd == null){ //may be empty
+ badparams = badparams.concat("dbPwd ");
+ parmsAreBad = true;
+ }
+
+ String siteName = properties.getProperty(IntegrityAuditProperties.SITE_NAME).trim();
+ if(siteName == null || siteName.isEmpty()){
+ badparams = badparams.concat("siteName ");
+ parmsAreBad = true;
+ }
+
+ String nodeType = properties.getProperty(IntegrityAuditProperties.NODE_TYPE).trim();
+ if(nodeType == null || nodeType.isEmpty()){
+ badparams = badparams.concat("nodeType ");
+ parmsAreBad = true;
+ } else {
+ if (!isNodeTypeEnum(nodeType)) {
+ String nodetypes = "nodeType must be one of[";
+ for (NodeTypeEnum n : NodeTypeEnum.values()) {
+ nodetypes = nodetypes.concat(n.toString() + " ");
+ }
+ badparams = badparams.concat(nodetypes + "] ");
+ parmsAreBad = true;
+ }
+ }
+ if(properties.getProperty(IntegrityAuditProperties.AUDIT_PERIOD_SECONDS) != null){ //It is allowed to be null
+ try{
+ Integer.parseInt(properties.getProperty(IntegrityAuditProperties.AUDIT_PERIOD_SECONDS).trim());
+ }catch(NumberFormatException nfe){
+ badparams = badparams.concat(", auditPeriodSeconds="
+ + properties.getProperty(IntegrityAuditProperties.AUDIT_PERIOD_SECONDS).trim());
+ parmsAreBad = true;
+ }
+ }
+ logger.debug("parmsAreBad: exit:"
+ + "\nresourceName: " + resourceName
+ + "\npersistenceUnit: " + persistenceUnit
+ + "\nproperties: " + properties);
+
+ return parmsAreBad;
+ }
+ /**
+ * Starts the audit thread
+ * @throws Exception
+ */
+ public void startAuditThread() throws Exception {
+
+ logger.info("startAuditThread: Entering");
+
+ if (integrityAuditPeriodSeconds >= 0) {
+ this.auditThread = new AuditThread(this.resourceName,
+ this.persistenceUnit, this.properties,
+ integrityAuditPeriodSeconds, this);
+ logger.info("startAuditThread: Audit started and will run every "
+ + integrityAuditPeriodSeconds + " seconds");
+ this.auditThread.start();
+ } else {
+ logger.info("startAuditThread: Suppressing integrity audit, integrityAuditPeriodSeconds="
+ + integrityAuditPeriodSeconds);
+ }
+
+ logger.info("startAuditThread: Exiting");
+ }
+ /**
+ * Stops the audit thread
+ */
+ public void stopAuditThread() {
+
+ logger.info("stopAuditThread: Entering");
+
+ if (this.auditThread != null) {
+ this.auditThread.interrupt();
+ } else {
+ logger.info("stopAuditThread: auditThread never instantiated; no need to interrupt");
+ }
+
+ logger.info("stopAuditThread: Exiting");
+ }
+
+ public boolean isThreadInitialized() {
+ return isThreadInitialized;
+ }
+
+ public void setThreadInitialized(boolean isThreadInitialized) {
+ logger.info("setThreadInitialized: Setting isThreadInitialized=" + isThreadInitialized);
+ this.isThreadInitialized = isThreadInitialized;
+ }
+}
diff --git a/integrity-audit/src/main/java/org/openecomp/policy/common/ia/IntegrityAuditProperties.java b/integrity-audit/src/main/java/org/openecomp/policy/common/ia/IntegrityAuditProperties.java
new file mode 100644
index 00000000..5a87c9cc
--- /dev/null
+++ b/integrity-audit/src/main/java/org/openecomp/policy/common/ia/IntegrityAuditProperties.java
@@ -0,0 +1,54 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Integrity Audit
+ * ================================================================================
+ * Copyright (C) 2017 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.openecomp.policy.common.ia;
+
+public class IntegrityAuditProperties {
+
+ public static final String DEFAULT_DB_DRIVER = "org.h2.Driver";
+ public static final String DEFAULT_DB_URL = "jdbc:h2:file:./sql/iaTest";
+ public static final String DEFAULT_DB_USER = "sa";
+ public static final String DEFAULT_DB_PWD = "";
+ public static final int DEFAULT_AUDIT_PERIOD_SECONDS = -1; // Audit does not run
+
+ public static final String DB_DRIVER = "javax.persistence.jdbc.driver";
+ public static final String DB_URL = "javax.persistence.jdbc.url";
+ public static final String DB_USER = "javax.persistence.jdbc.user";
+ public static final String DB_PWD = "javax.persistence.jdbc.password";
+ public static final String AUDIT_PERIOD_SECONDS = "integrity_audit_period_seconds";
+
+
+ public static final String SITE_NAME = "site_name";
+ public static final String NODE_TYPE = "node_type";
+
+ public static enum NodeTypeEnum {
+ pdp_xacml,
+ pdp_drools,
+ pap,
+ pap_admin,
+ logparser,
+ brms_gateway,
+ astra_gateway,
+ elk_server,
+ pypdp
+
+ }
+
+}
diff --git a/integrity-audit/src/main/java/org/openecomp/policy/common/ia/IntegrityAuditPropertiesException.java b/integrity-audit/src/main/java/org/openecomp/policy/common/ia/IntegrityAuditPropertiesException.java
new file mode 100644
index 00000000..77c85585
--- /dev/null
+++ b/integrity-audit/src/main/java/org/openecomp/policy/common/ia/IntegrityAuditPropertiesException.java
@@ -0,0 +1,37 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Integrity Audit
+ * ================================================================================
+ * Copyright (C) 2017 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.openecomp.policy.common.ia;
+
+public class IntegrityAuditPropertiesException extends Exception{
+ private static final long serialVersionUID = 1L;
+ public IntegrityAuditPropertiesException() {
+ }
+ public IntegrityAuditPropertiesException(String message) {
+ super(message);
+ }
+
+ public IntegrityAuditPropertiesException(Throwable cause) {
+ super(cause);
+ }
+ public IntegrityAuditPropertiesException(String message, Throwable cause) {
+ super(message, cause);
+ }
+}
diff --git a/integrity-audit/src/main/java/org/openecomp/policy/common/ia/jpa/IntegrityAuditEntity.java b/integrity-audit/src/main/java/org/openecomp/policy/common/ia/jpa/IntegrityAuditEntity.java
new file mode 100644
index 00000000..3d50d835
--- /dev/null
+++ b/integrity-audit/src/main/java/org/openecomp/policy/common/ia/jpa/IntegrityAuditEntity.java
@@ -0,0 +1,204 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Integrity Audit
+ * ================================================================================
+ * Copyright (C) 2017 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.openecomp.policy.common.ia.jpa;
+
+import java.io.Serializable;
+import java.util.Date;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.NamedQueries;
+import javax.persistence.NamedQuery;
+import javax.persistence.PrePersist;
+import javax.persistence.PreUpdate;
+import javax.persistence.SequenceGenerator;
+import javax.persistence.Table;
+import javax.persistence.Temporal;
+import javax.persistence.TemporalType;
+/*
+ * The Entity class to for management of IntegrityAudits
+ */
+
+@Entity
+@Table(name="IntegrityAuditEntity")
+@NamedQueries({
+ @NamedQuery(name=" IntegrityAuditEntity.findAll", query="SELECT e FROM IntegrityAuditEntity e "),
+ @NamedQuery(name="IntegrityAuditEntity.deleteAll", query="DELETE FROM IntegrityAuditEntity WHERE 1=1")
+})
+
+public class IntegrityAuditEntity implements Serializable {
+ private static final long serialVersionUID = 1L;
+
+ public static boolean isUnitTesting;
+
+ @Id
+ @GeneratedValue(strategy = GenerationType.AUTO)
+ @Column(name="id")
+ private long id;
+
+ @Column(name="persistenceUnit", nullable=false)
+ private String persistenceUnit;
+
+ @Column(name="site", nullable=true)
+ private String site;
+
+ @Column(name="nodeType", nullable=true)
+ private String nodeType;
+
+ @Column(name="resourceName", nullable=false, unique=true)
+ private String resourceName;
+
+ @Column(name="designated", nullable=true)
+ private boolean designated = false;
+
+ @Column(name="jdbcDriver", nullable=false)
+ private String jdbcDriver;
+
+ @Column(name="jdbcUrl", nullable=false)
+ private String jdbcUrl;
+
+ @Column(name="jdbcUser", nullable=false)
+ private String jdbcUser;
+
+ @Column(name="jdbcPassword", nullable=false)
+ private String jdbcPassword;
+
+ @Temporal(TemporalType.TIMESTAMP)
+ @Column(name="createdDate", updatable=true)
+ private Date createdDate;
+
+ @Temporal(TemporalType.TIMESTAMP)
+ @Column(name="lastUpdated")
+ private Date lastUpdated;
+
+
+ public IntegrityAuditEntity() {
+ }
+
+ @PrePersist
+ public void prePersist() {
+ Date date = new Date();
+ this.createdDate = date;
+ this.lastUpdated = date;
+ }
+
+ @PreUpdate
+ public void preUpdate() {
+ if (!isUnitTesting) {
+ this.lastUpdated = new Date();
+ }
+ }
+
+ public long getId() {
+ return id;
+ }
+
+ public String getPersistenceUnit() {
+ return persistenceUnit;
+ }
+
+ public void setPersistenceUnit(String persistenceUnit) {
+ this.persistenceUnit = persistenceUnit;
+ }
+
+ public String getSite() {
+ return site;
+ }
+
+ public void setSite(String site) {
+ this.site = site;
+ }
+
+ public String getNodeType() {
+ return nodeType;
+ }
+
+ public void setNodeType(String nodeType) {
+ this.nodeType = nodeType;
+ }
+
+ public String getResourceName() {
+ return resourceName;
+ }
+
+ public void setResourceName(String resourceName) {
+ this.resourceName = resourceName;
+ }
+
+ public boolean isDesignated() {
+ return designated;
+ }
+
+ public void setDesignated(boolean designated) {
+ this.designated = designated;
+ }
+
+ public String getJdbcDriver() {
+ return jdbcDriver;
+ }
+
+ public void setJdbcDriver(String jdbcDriver) {
+ this.jdbcDriver = jdbcDriver;
+ }
+
+ public String getJdbcUrl() {
+ return jdbcUrl;
+ }
+
+ public void setJdbcUrl(String jdbcUrl) {
+ this.jdbcUrl = jdbcUrl;
+ }
+
+ public String getJdbcUser() {
+ return jdbcUser;
+ }
+
+ public void setJdbcUser(String jdbcUser) {
+ this.jdbcUser = jdbcUser;
+ }
+
+ public String getJdbcPassword() {
+ return jdbcPassword;
+ }
+
+ public void setJdbcPassword(String jdbcPassword) {
+ this.jdbcPassword = jdbcPassword;
+ }
+
+ public Date getLastUpdated() {
+ return lastUpdated;
+ }
+
+ public void setLastUpdated(Date lastUpdated) {
+ this.lastUpdated = lastUpdated;
+ }
+
+ public Date getCreatedDate() {
+ return createdDate;
+ }
+
+ public void setCreatedDate(Date created) {
+ this.createdDate = created;
+ }
+}