Increase JUnit Code Coverage for PolicyDBDao
[policy/engine.git] / ONAP-PAP-REST / src / main / java / org / onap / policy / pap / xacml / rest / components / PolicyDBDao.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * ONAP-PAP-REST
4  * ================================================================================
5  * Copyright (C) 2017-2019 AT&T Intellectual Property. All rights reserved.
6  * Modified Copyright (C) 2018 Samsung Electronics Co., Ltd.
7  * ================================================================================
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  *      http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  * ============LICENSE_END=========================================================
20  */
21
22 package org.onap.policy.pap.xacml.rest.components;
23
24 import java.io.ByteArrayInputStream;
25 import java.io.File;
26 import java.io.FileInputStream;
27 import java.io.FileNotFoundException;
28 import java.io.FileWriter;
29 import java.io.IOException;
30 import java.io.InputStream;
31 import java.io.StringReader;
32 import java.net.HttpURLConnection;
33 import java.net.MalformedURLException;
34 import java.net.ProtocolException;
35 import java.net.URI;
36 import java.net.URL;
37 import java.nio.charset.StandardCharsets;
38 import java.nio.file.Files;
39 import java.nio.file.InvalidPathException;
40 import java.nio.file.Path;
41 import java.nio.file.Paths;
42 import java.util.Base64;
43 import java.util.Date;
44 import java.util.HashMap;
45 import java.util.HashSet;
46 import java.util.Iterator;
47 import java.util.LinkedList;
48 import java.util.List;
49 import java.util.Map;
50 import java.util.Set;
51 import java.util.UUID;
52 import javax.persistence.EntityManager;
53 import javax.persistence.EntityManagerFactory;
54 import javax.persistence.LockModeType;
55 import javax.persistence.PersistenceException;
56 import javax.persistence.Query;
57 import javax.persistence.RollbackException;
58 import javax.xml.parsers.DocumentBuilder;
59 import javax.xml.parsers.DocumentBuilderFactory;
60 import javax.xml.xpath.XPath;
61 import javax.xml.xpath.XPathFactory;
62 import org.apache.commons.io.FilenameUtils;
63 import org.apache.commons.io.IOUtils;
64 import org.onap.policy.common.logging.eelf.MessageCodes;
65 import org.onap.policy.common.logging.eelf.PolicyLogger;
66 import org.onap.policy.common.logging.flexlogger.FlexLogger;
67 import org.onap.policy.common.logging.flexlogger.Logger;
68 import org.onap.policy.pap.xacml.rest.XACMLPapServlet;
69 import org.onap.policy.rest.XACMLRestProperties;
70 import org.onap.policy.rest.adapter.PolicyRestAdapter;
71 import org.onap.policy.rest.dao.PolicyDBException;
72 import org.onap.policy.rest.jpa.ActionBodyEntity;
73 import org.onap.policy.rest.jpa.ConfigurationDataEntity;
74 import org.onap.policy.rest.jpa.DatabaseLockEntity;
75 import org.onap.policy.rest.jpa.GroupEntity;
76 import org.onap.policy.rest.jpa.PdpEntity;
77 import org.onap.policy.rest.jpa.PolicyDBDaoEntity;
78 import org.onap.policy.rest.jpa.PolicyEntity;
79 import org.onap.policy.utils.CryptoUtils;
80 import org.onap.policy.xacml.api.pap.OnapPDP;
81 import org.onap.policy.xacml.api.pap.OnapPDPGroup;
82 import org.onap.policy.xacml.api.pap.PAPPolicyEngine;
83 import org.onap.policy.xacml.std.pap.StdPDPGroup;
84 import org.onap.policy.xacml.std.pap.StdPDPPolicy;
85 import org.onap.policy.xacml.util.XACMLPolicyWriter;
86 import org.w3c.dom.Document;
87 import org.xml.sax.InputSource;
88 import oasis.names.tc.xacml._3_0.core.schema.wd_17.PolicySetType;
89 import oasis.names.tc.xacml._3_0.core.schema.wd_17.PolicyType;
90 import com.att.research.xacml.api.pap.PAPException;
91 import com.att.research.xacml.api.pap.PDP;
92 import com.att.research.xacml.api.pap.PDPPolicy;
93 import com.att.research.xacml.util.XACMLProperties;
94
95 public class PolicyDBDao {
96     private static final Logger logger = FlexLogger.getLogger(PolicyDBDao.class);
97     private List<?> otherServers;
98     private EntityManagerFactory emf;
99     private static PolicyDBDao currentInstance = null;
100     private PAPPolicyEngine papEngine;
101
102     private static final String JSON_CONFIG = "JSON";
103     private static final String XML_CONFIG = "XML";
104     private static final String PROPERTIES_CONFIG = "PROPERTIES";
105     private static final String OTHER_CONFIG = "OTHER";
106
107     // Declared to static variables which were repeating multiple times across the PolicyDBDao
108     public static final String config = "Config";
109     public static final String action = "Action";
110     private static final String groupIdVar = "groupId";
111     private static final String deletedVar = "deleted";
112     private static final String groupEntitySelectQuery =
113             "SELECT g FROM GroupEntity g WHERE g.groupId=:groupId AND g.deleted=:deleted";
114     private static final String pdpEntitySelectQuery =
115             "SELECT p FROM PdpEntity p WHERE p.pdpId=:pdpId AND p.deleted=:deleted";
116     private static final String groupCannotBeFound = "The group could not be found with id ";
117     private static final String foundInDBNotDeleted = " were found in the database that are not deleted";
118     private static final String moreThanOnePDP = "Somehow, more than one pdp with the same id ";
119     private static final String deletedStatusFound = " and deleted status were found in the database";
120     private static final String duplicateGroupId = "Somehow, more than one group with the same id ";
121     private static final String pdpIdVariable = "pdpId";
122     private static final String queryFailedToCheckExisting = "Query failed trying to check for existing group";
123     private static final String queryFailedToGetGroup = "Query failed trying to get group ";
124     public static final String scope = "scope";
125     private static final String policyDBDaoVar = "PolicyDBDao";
126     private static final String duplicatePolicyId = "Somehow, more than one policy with the id ";
127     private static final String foundInDB = " were found in the database";
128     private static final String TIMESTAMP = "\n   TimeStamp = ";
129     private static final String CAUGHTEXCEPTIONONNOTIFY = "Caught Exception on notifyOthers(";
130
131     private static boolean isJunit = false;
132
133     public static void setJunit(boolean isJunit) {
134         PolicyDBDao.isJunit = isJunit;
135     }
136
137     /**
138      * Get an instance of a PolicyDBDao. It creates one if it does not exist. Only one instance is allowed to be created
139      * per server.
140      *
141      * @param emf The EntityFactoryManager to be used for database connections
142      * @return The new instance of PolicyDBDao or throw exception if the given emf is null.
143      * @throws IllegalStateException if a PolicyDBDao has already been constructed. Call getPolicyDBDaoInstance() to get
144      *         this.
145      */
146     public static PolicyDBDao getPolicyDBDaoInstance(EntityManagerFactory emf) {
147         logger.debug("getPolicyDBDaoInstance(EntityManagerFactory emf) as getPolicyDBDaoInstance(" + emf + ") called");
148         if (currentInstance == null) {
149             if (emf != null) {
150                 currentInstance = new PolicyDBDao(emf);
151                 return currentInstance;
152             }
153             throw new IllegalStateException("The EntityManagerFactory is Null");
154         }
155         return currentInstance;
156     }
157
158     /**
159      * Gets the current instance of PolicyDBDao.
160      *
161      * @return The instance of PolicyDBDao or throws exception if the given instance is null.
162      * @throws IllegalStateException if a PolicyDBDao instance is null. Call createPolicyDBDaoInstance
163      *         (EntityManagerFactory emf) to get this.
164      */
165     public static PolicyDBDao getPolicyDBDaoInstance() {
166         logger.debug("getPolicyDBDaoInstance() as getPolicyDBDaoInstance() called");
167         if (currentInstance != null) {
168             return currentInstance;
169         }
170         throw new IllegalStateException(
171                 "The PolicyDBDao.currentInstance is Null.  Use getPolicyDBDao(EntityManagerFactory emf)");
172     }
173
174     public void setPapEngine(PAPPolicyEngine papEngine2) {
175         this.papEngine = papEngine2;
176     }
177
178     private PolicyDBDao(EntityManagerFactory emf) {
179         logger.debug("PolicyDBDao(EntityManagerFactory emf) as PolicyDBDao(" + emf + ") called");
180         this.emf = emf;
181
182         // not needed in this release
183         if (!register()) {
184             PolicyLogger
185                     .error("This server's PolicyDBDao instance could not be registered and may not reveive updates");
186         }
187
188         otherServers = getRemotePolicyDBDaoList();
189         if (logger.isDebugEnabled()) {
190             logger.debug("Number of remote PolicyDBDao instances: " + otherServers.size());
191         }
192         if (otherServers.isEmpty()) {
193             logger.warn("List of PolicyDBDao servers is empty or could not be retrieved");
194         }
195     }
196
197     // not static because we are going to be using the instance's emf
198     // waitTime in ms to wait for lock, or -1 to wait forever (no)
199     private void startTransactionSynced(EntityManager entityMgr, int waitTime) {
200         logger.debug("\n\nstartTransactionSynced(EntityManager entityMgr,int waitTime) as "
201                 + "\n   startTransactionSynced(" + entityMgr + "," + waitTime + ") called\n\n");
202         DatabaseLockEntity lock = null;
203
204         entityMgr.setProperty("javax.persistence.query.timeout", waitTime);
205         entityMgr.getTransaction().begin();
206
207         if (logger.isDebugEnabled()) {
208             Map<String, Object> properties = entityMgr.getProperties();
209             logger.debug(
210                     "\n\nstartTransactionSynced():" + "\n   entityManager.getProperties() = " + properties + "\n\n");
211         }
212         try {
213             if (logger.isDebugEnabled()) {
214                 logger.debug("\n\nstartTransactionSynced():" + "\n   ATTEMPT to get the DB lock" + "\n\n");
215             }
216             lock = entityMgr.find(DatabaseLockEntity.class, 1, LockModeType.PESSIMISTIC_WRITE);
217             if (logger.isDebugEnabled()) {
218                 logger.debug("\n\nstartTransactionSynced():" + "\n   GOT the DB lock" + "\n\n");
219             }
220         } catch (Exception e) {
221             System.out.println("Could not get lock entity");
222             logger.error("Exception Occured" + e);
223         }
224         if (lock == null) {
225             throw new IllegalStateException(
226                     "The lock row does not exist in the table. Please create a primary key with value = 1.");
227         }
228
229     }
230
231     /**
232      * Gets the list of other registered PolicyDBDaos from the database
233      *
234      * @return List (type PolicyDBDaoEntity) of other PolicyDBDaos
235      */
236     private List<?> getRemotePolicyDBDaoList() {
237         logger.debug("getRemotePolicyDBDaoList() as getRemotePolicyDBDaoList() called");
238         List<?> policyDBDaoEntityList = new LinkedList<>();
239         EntityManager em = emf.createEntityManager();
240         startTransactionSynced(em, 1000);
241         try {
242             Query getPolicyDBDaoEntityQuery = em.createNamedQuery("PolicyDBDaoEntity.findAll");
243             policyDBDaoEntityList = getPolicyDBDaoEntityQuery.getResultList();
244
245         } catch (Exception e) {
246             PolicyLogger.error(MessageCodes.EXCEPTION_ERROR, e, policyDBDaoVar,
247                     "Exception querying for other registered PolicyDBDaos");
248             logger.warn("List of remote PolicyDBDaos will be empty", e);
249         }
250         try {
251             em.getTransaction().commit();
252         } catch (Exception e) {
253             logger.warn("List of remote PolicyDBDaos will be empty", e);
254             try {
255                 em.getTransaction().rollback();
256             } catch (Exception e2) {
257                 logger.debug("List of remote PolicyDBDaos will be empty", e2);
258             }
259         }
260         em.close();
261         return policyDBDaoEntityList;
262     }
263
264     public PolicyDBDaoTransaction getNewTransaction() {
265         logger.debug("getNewTransaction() as getNewTransaction() called");
266         return new PolicyDBDaoTransactionInstance();
267     }
268
269     /*
270      * Because the normal transactions are not used in audits, we can use the same transaction mechanism to get a
271      * transaction and obtain the emlock and the DB lock. We just need to provide different transaction timeout values
272      * in ms because the audit will run longer than normal transactions.
273      */
274     public PolicyDBDaoTransaction getNewAuditTransaction() {
275         logger.debug("getNewAuditTransaction() as getNewAuditTransaction() called");
276         // Use the standard transaction wait time in ms
277         int auditWaitMs = Integer.parseInt(XACMLProperties.getProperty(XACMLRestProperties.PROP_PAP_TRANS_WAIT));
278         // Use the (extended) audit timeout time in ms
279         int auditTimeoutMs = Integer.parseInt(XACMLProperties.getProperty(XACMLRestProperties.PROP_PAP_AUDIT_TIMEOUT));
280         return new PolicyDBDaoTransactionInstance(auditTimeoutMs, auditWaitMs);
281     }
282
283
284     /**
285      * Checks if two strings are equal. Null strings ARE allowed.
286      *
287      * @param one A String or null to compare
288      * @param two A String or null to compare
289      */
290     private static boolean stringEquals(String one, String two) {
291         logger.debug("stringEquals(String one, String two) as stringEquals(" + one + ", " + two + ") called");
292         if (one == null && two == null) {
293             return true;
294         }
295         if (one == null || two == null) {
296             return false;
297         }
298         return one.equals(two);
299     }
300
301     /**
302      * Returns the url of this local pap server, removing the username and password, if they are present
303      *
304      * @return The url of this local pap server
305      */
306     private String[] getPapUrlUserPass() {
307         logger.debug("getPapUrl() as getPapUrl() called");
308         String url = XACMLProperties.getProperty(XACMLRestProperties.PROP_PAP_URL);
309         if (url == null) {
310             return null;
311         }
312         return splitPapUrlUserPass(url);
313     }
314
315     private String[] splitPapUrlUserPass(String url) {
316         String[] urlUserPass = new String[3];
317         String[] commaSplit = url.split(",");
318         urlUserPass[0] = commaSplit[0];
319         if (commaSplit.length > 2) {
320             urlUserPass[1] = commaSplit[1];
321             urlUserPass[2] = commaSplit[2];
322         }
323         if (urlUserPass[1] == null || "".equals(urlUserPass[1])) {
324             String usernamePropertyValue = XACMLProperties.getProperty(XACMLRestProperties.PROP_PAP_USERID);
325             if (usernamePropertyValue != null) {
326                 urlUserPass[1] = usernamePropertyValue;
327             }
328         }
329         if (urlUserPass[2] == null || "".equals(urlUserPass[2])) {
330             String passwordPropertyValue = XACMLProperties.getProperty(XACMLRestProperties.PROP_PAP_PASS);
331             if (passwordPropertyValue != null) {
332                 urlUserPass[2] = passwordPropertyValue;
333             }
334         }
335         // if there is no comma, for some reason there is no username and password, so don't try to cut them off
336         return urlUserPass;
337     }
338
339     /**
340      * Register the PolicyDBDao instance in the PolicyDBDaoEntity table
341      *
342      * @return Boolean, were we able to register?
343      */
344     private boolean register() {
345         logger.debug("register() as register() called");
346         String[] url = getPapUrlUserPass();
347         // --- check URL length
348         if (url == null || url.length < 3) {
349             return false;
350         }
351         EntityManager em = emf.createEntityManager();
352         try {
353             startTransactionSynced(em, 1000);
354         } catch (IllegalStateException e) {
355             logger.debug("\nPolicyDBDao.register() caught an IllegalStateException: \n" + e + "\n");
356             DatabaseLockEntity lock;
357             lock = em.find(DatabaseLockEntity.class, 1);
358             if (lock == null) {
359                 lock = new DatabaseLockEntity();
360                 em.persist(lock);
361                 lock.setKey(1);
362                 try {
363                     em.flush();
364                     em.getTransaction().commit();
365                     em.close();
366                 } catch (Exception e2) {
367                     PolicyLogger.error(MessageCodes.EXCEPTION_ERROR, e2, policyDBDaoVar,
368                             "COULD NOT CREATE DATABASELOCK ROW.  WILL TRY ONE MORE TIME");
369                 }
370
371                 em = emf.createEntityManager();
372                 try {
373                     startTransactionSynced(em, 1000);
374                 } catch (Exception e3) {
375                     String msg = "DATABASE LOCKING NOT WORKING. CONCURRENCY CONTROL NOT WORKING";
376                     PolicyLogger.error(MessageCodes.EXCEPTION_ERROR, e3, policyDBDaoVar, msg);
377                     throw new IllegalStateException("msg" + "\n" + e3);
378                 }
379             }
380         }
381         logger.debug("\nPolicyDBDao.register. Database locking and concurrency control is initialized\n");
382         PolicyDBDaoEntity foundPolicyDBDaoEntity = em.find(PolicyDBDaoEntity.class, url[0]);
383         Query getPolicyDBDaoEntityQuery =
384                 em.createQuery("SELECT e FROM PolicyDBDaoEntity e WHERE e.policyDBDaoUrl=:url");
385         getPolicyDBDaoEntityQuery.setParameter("url", url[0]);
386         // encrypt the password
387         String txt = null;
388         try {
389             txt = CryptoUtils.encryptTxt(url[2].getBytes(StandardCharsets.UTF_8));
390         } catch (Exception e) {
391             logger.debug(e);
392             PolicyLogger.error(MessageCodes.EXCEPTION_ERROR, e, policyDBDaoVar, "Could not encrypt PAP password");
393         }
394         if (foundPolicyDBDaoEntity == null) {
395             PolicyDBDaoEntity newPolicyDBDaoEntity = new PolicyDBDaoEntity();
396             em.persist(newPolicyDBDaoEntity);
397             newPolicyDBDaoEntity.setPolicyDBDaoUrl(url[0]);
398             newPolicyDBDaoEntity.setDescription("PAP server at " + url[0]);
399             newPolicyDBDaoEntity.setUsername(url[1]);
400             newPolicyDBDaoEntity.setPassword(txt);
401             try {
402                 em.getTransaction().commit();
403             } catch (Exception e) {
404                 logger.debug(e);
405                 try {
406                     em.getTransaction().rollback();
407                 } catch (Exception e2) {
408                     logger.debug(e2);
409                     PolicyLogger.error(MessageCodes.EXCEPTION_ERROR, e2, policyDBDaoVar,
410                             "Could not add new PolicyDBDao to the database");
411                 }
412             }
413         } else {
414             // just want to update in order to change modified date
415             if (url[1] != null && !stringEquals(url[1], foundPolicyDBDaoEntity.getUsername())) {
416                 foundPolicyDBDaoEntity.setUsername(url[1]);
417             }
418             if (txt != null && !stringEquals(txt, foundPolicyDBDaoEntity.getPassword())) {
419                 foundPolicyDBDaoEntity.setPassword(txt);
420             }
421             foundPolicyDBDaoEntity.preUpdate();
422             try {
423                 em.getTransaction().commit();
424             } catch (Exception e) {
425                 logger.debug(e);
426                 try {
427                     em.getTransaction().rollback();
428                 } catch (Exception e2) {
429                     logger.debug(e2);
430                     PolicyLogger.error(MessageCodes.EXCEPTION_ERROR, e2, policyDBDaoVar,
431                             "Could not update PolicyDBDao in the database");
432                 }
433             }
434         }
435         em.close();
436         logger.debug("\nPolicyDBDao.register(). Success!!\n");
437         return true;
438     }
439
440     private class NotifyOtherThread implements Runnable {
441         public NotifyOtherThread(Object obj, long entityId, String entityType, String newGroupId) {
442             this.obj = obj;
443             this.entityId = entityId;
444             this.entityType = entityType;
445             this.newGroupId = newGroupId;
446         }
447
448         private Object obj;
449         private long entityId;
450         private String entityType;
451         private String newGroupId;
452
453         @Override
454         public void run() {
455             // naming of 'o' is for backwards compatibility with the rest of the function
456             PolicyDBDaoEntity dbdEntity = (PolicyDBDaoEntity) obj;
457             String o = dbdEntity.getPolicyDBDaoUrl();
458             String username = dbdEntity.getUsername();
459             String txt;
460             try {
461                 txt = new String(CryptoUtils.decryptTxt(dbdEntity.getPassword()), StandardCharsets.UTF_8);
462             } catch (Exception e) {
463                 logger.debug(e);
464                 // if we can't decrypt, might as well try it anyway
465                 txt = dbdEntity.getPassword();
466             }
467             Base64.Encoder encoder = Base64.getEncoder();
468             String encoding = encoder.encodeToString((username + ":" + txt).getBytes(StandardCharsets.UTF_8));
469             HttpURLConnection connection = null;
470             UUID requestID = UUID.randomUUID();
471             URL url;
472             String papUrl;
473             try {
474                 String[] papUrlUserPass = getPapUrlUserPass();
475                 if (papUrlUserPass == null) {
476                     papUrl = "undefined";
477                 } else {
478                     papUrl = papUrlUserPass[0];
479                 }
480                 logger.debug("We are going to try to notify " + o);
481                 // is this our own url?
482                 String ourUrl = o;
483                 try {
484                     ourUrl = splitPapUrlUserPass((String) o)[0];
485                 } catch (Exception e) {
486                     logger.debug(e);
487                 }
488                 if (o == null) {
489                     o = "undefined";
490                 }
491                 if (papUrl.equals(ourUrl)) {
492                     logger.debug(o + " is our url, skipping notify");
493                     return;
494                 }
495                 if (newGroupId == null) {
496                     url = new URL(
497                             o + "?policydbdaourl=" + papUrl + "&entityid=" + entityId + "&entitytype=" + entityType);
498                 } else {
499                     url = new URL(o + "?policydbdaourl=" + papUrl + "&entityid=" + entityId + "&entitytype="
500                             + entityType + "&extradata=" + newGroupId);
501                 }
502             } catch (MalformedURLException e) {
503                 logger.warn("Caught MalformedURLException on: new URL()", e);
504                 return;
505             }
506             //
507             // Open up the connection
508             //
509             logger.info("PolicyDBDao: NotifyOtherThread: notifying other PAPs of an update");
510             logger.info("Connecting with url: " + url);
511             try {
512                 connection = (HttpURLConnection) url.openConnection();
513             } catch (Exception e) {
514                 logger.warn("Caught exception on: url.openConnection()", e);
515                 return;
516             }
517             //
518             // Setup our method and headers
519             //
520             try {
521                 connection.setRequestMethod("PUT");
522             } catch (ProtocolException e) {
523                 // why would this error ever occur?
524                 logger.warn("Caught ProtocolException on connection.setRequestMethod(\"PUT\");", e);
525                 return;
526             }
527             connection.setRequestProperty("Authorization", "Basic " + encoding);
528             connection.setRequestProperty("Accept", "text/x-java-properties");
529             connection.setRequestProperty("Content-Type", "text/x-java-properties");
530             connection.setRequestProperty("requestID", requestID.toString());
531             int readTimeout;
532             try {
533                 readTimeout =
534                         Integer.parseInt(XACMLProperties.getProperty(XACMLRestProperties.PROP_PAP_NOTIFY_TIMEOUT));
535             } catch (Exception e) {
536                 logger.error("xacml.rest.pap.notify.timeoutms property not set, using a default.", e);
537                 readTimeout = 10000;
538             }
539             connection.setReadTimeout(readTimeout);
540             connection.setConnectTimeout(readTimeout);
541             connection.setUseCaches(false);
542             //
543             // Adding this in. It seems the HttpUrlConnection class does NOT
544             // properly forward our headers for POST re-direction. It does so
545             // for a GET re-direction.
546             //
547             // So we need to handle this ourselves.
548             //
549             connection.setInstanceFollowRedirects(false);
550             connection.setDoOutput(true);
551             connection.setDoInput(true);
552             try {
553                 connection.connect();
554             } catch (Exception e) {
555                 logger.warn("Caught exception on: connection.connect()", e);
556                 return;
557             }
558             try {
559                 if (connection.getResponseCode() == 200) {
560                     logger.info("PolicyDBDao: NotifyOtherThread received response 200 from pap server on notify");
561                 } else {
562                     logger.warn("PolicyDBDao: NotifyOtherThread connection response code not 200, received: "
563                             + connection.getResponseCode());
564                 }
565             } catch (Exception e) {
566                 logger.warn("Caught Exception on: connection.getResponseCode() ", e);
567             }
568
569             connection.disconnect();
570         }
571     }
572
573     private static String evaluateXPath(String expression, String xml) {
574         InputSource source = new InputSource(new StringReader(xml));
575
576         DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
577         String description = "";
578         try {
579             DocumentBuilder db = dbf.newDocumentBuilder();
580             Document document = db.parse(source);
581
582             XPathFactory xpathFactory = XPathFactory.newInstance();
583             XPath xpath = xpathFactory.newXPath();
584
585             description = xpath.evaluate(expression, document);
586         } catch (Exception e) {
587             logger.error("Exception Occured while evaluating path" + e);
588         }
589         return description;
590     }
591
592     private static final String POLICY_NOTIFICATION = "policy";
593     private static final String PDP_NOTIFICATION = "pdp";
594     private static final String GROUP_NOTIFICATION = "group";
595
596     public void handleIncomingHttpNotification(String url, String entityId, String entityType, String extraData,
597             XACMLPapServlet xacmlPapServlet) {
598         logger.info("DBDao url: " + url + " has reported an update on " + entityType + " entity " + entityId);
599         PolicyDBDaoTransaction transaction = this.getNewTransaction();
600         // although its named retries, this is the total number of tries
601         int retries;
602         try {
603             retries = Integer
604                     .parseInt(XACMLProperties.getProperty(XACMLRestProperties.PROP_PAP_INCOMINGNOTIFICATION_TRIES));
605         } catch (Exception e) {
606             logger.error("xacml.rest.pap.incomingnotification.tries property not set, using a default of 3." + e);
607             retries = 3;
608         }
609         // if someone sets it to some dumb value, we need to make sure it will try at least once
610         if (retries < 1) {
611             retries = 1;
612         }
613         int pauseBetweenRetries = 1000;
614         switch (entityType) {
615
616             case POLICY_NOTIFICATION:
617                 for (int i = 0; i < retries; i++) {
618                     try {
619                         handleIncomingPolicyChange(entityId);
620                         break;
621                     } catch (Exception e) {
622                         logger.debug(e);
623                         PolicyLogger.error(MessageCodes.EXCEPTION_ERROR, e, policyDBDaoVar,
624                                 "Caught exception on handleIncomingPolicyChange(" + url + ", " + entityId + ", "
625                                         + extraData + ")");
626                     }
627                     try {
628                         Thread.sleep(pauseBetweenRetries);
629                     } catch (InterruptedException ie) {
630                         Thread.currentThread().interrupt();
631                         break;
632                     }
633                 }
634                 break;
635             case PDP_NOTIFICATION:
636                 for (int i = 0; i < retries; i++) {
637                     try {
638                         handleIncomingPdpChange(entityId, transaction);
639                         break;
640                     } catch (Exception e) {
641                         logger.debug(e);
642                         PolicyLogger.error(MessageCodes.EXCEPTION_ERROR, e, policyDBDaoVar,
643                                 "Caught exception on handleIncomingPdpChange(" + url + ", " + entityId + ", "
644                                         + transaction + ")");
645                     }
646                     try {
647                         Thread.sleep(pauseBetweenRetries);
648                     } catch (InterruptedException ie) {
649                         Thread.currentThread().interrupt();
650                         break;
651                     }
652                 }
653                 break;
654             case GROUP_NOTIFICATION:
655                 for (int i = 0; i < retries; i++) {
656                     try {
657                         handleIncomingGroupChange(entityId, extraData, transaction);
658                         break;
659                     } catch (Exception e) {
660                         logger.debug(e);
661                         PolicyLogger.error(MessageCodes.EXCEPTION_ERROR, e, policyDBDaoVar,
662                                 "Caught exception on handleIncomingGroupChange(" + url + ", " + entityId + ", "
663                                         + extraData + ", " + transaction + ", " + xacmlPapServlet + ")");
664                     }
665                     try {
666                         Thread.sleep(pauseBetweenRetries);
667                     } catch (InterruptedException ie) {
668                         Thread.currentThread().interrupt();
669                         break;
670                     }
671                 }
672                 break;
673         }
674         // no changes should be being made in this function, we still need to close
675         transaction.rollbackTransaction();
676     }
677
678     private void handleIncomingGroupChange(String groupId, String extraData, PolicyDBDaoTransaction transaction)
679             throws PAPException, PolicyDBException {
680         GroupEntity groupRecord = null;
681         long groupIdLong = -1;
682         try {
683             groupIdLong = Long.parseLong(groupId);
684         } catch (NumberFormatException e) {
685             throw new IllegalArgumentException("groupId " + groupId + " cannot be parsed into a long");
686         }
687         try {
688             groupRecord = transaction.getGroup(groupIdLong);
689         } catch (Exception e) {
690             PolicyLogger.error(MessageCodes.EXCEPTION_ERROR, e, policyDBDaoVar,
691                     "Caught Exception trying to get pdp group record with transaction.getGroup(" + groupIdLong + ");");
692             throw new PAPException("Could not get local group " + groupIdLong);
693         }
694         if (groupRecord == null) {
695             throw new PersistenceException("The group record returned is null");
696         }
697         // compare to local fs
698         // does group folder exist
699         OnapPDPGroup localGroup = null;
700         try {
701             localGroup = papEngine.getGroup(groupRecord.getGroupId());
702         } catch (Exception e) {
703             logger.warn("Caught PAPException trying to get local pdp group with papEngine.getGroup(" + groupId + ");",
704                     e);
705         }
706         if (localGroup == null && extraData != null) {
707             // here we can try to load an old group id from the extraData
708             try {
709                 localGroup = papEngine.getGroup(extraData);
710             } catch (Exception e) {
711                 logger.warn(
712                         "Caught PAPException trying to get local pdp group with papEngine.getGroup(" + extraData + ");",
713                         e);
714             }
715         }
716         if (localGroup != null && groupRecord.isDeleted()) {
717             OnapPDPGroup newLocalGroup = null;
718             if (extraData != null) {
719                 try {
720                     newLocalGroup = papEngine.getGroup(extraData);
721                 } catch (PAPException e) {
722                     PolicyLogger.error(MessageCodes.EXCEPTION_ERROR, e, policyDBDaoVar,
723                             "Caught PAPException trying to get new pdp group with papEngine.getGroup(" + extraData
724                                     + ");");
725                 }
726             }
727             try {
728                 papEngine.removeGroup(localGroup, newLocalGroup);
729             } catch (NullPointerException | PAPException e) {
730                 PolicyLogger.error(MessageCodes.EXCEPTION_ERROR, e, policyDBDaoVar,
731                         "Caught PAPException trying to get remove pdp group with papEngine.removeGroup(" + localGroup
732                                 + ", " + newLocalGroup + ");");
733                 throw new PAPException("Could not remove group " + groupId);
734             }
735         } else if (localGroup == null) {
736             // creating a new group
737             try {
738                 papEngine.newGroup(groupRecord.getgroupName(), groupRecord.getDescription());
739             } catch (NullPointerException | PAPException e) {
740                 PolicyLogger.error(MessageCodes.EXCEPTION_ERROR, e, policyDBDaoVar,
741                         "Caught PAPException trying to create pdp group with papEngine.newGroup(groupRecord"
742                                 + ".getgroupName(), groupRecord.getDescription());");
743                 throw new PAPException("Could not create group " + groupRecord);
744             }
745             try {
746                 localGroup = papEngine.getGroup(groupRecord.getGroupId());
747             } catch (PAPException e1) {
748                 PolicyLogger.error(MessageCodes.EXCEPTION_ERROR, e1, policyDBDaoVar,
749                         "Caught PAPException trying to get pdp group we just created with papEngine.getGroup"
750                                 + "(groupRecord.getGroupId());\nAny PDPs or policies in the new group may not have been added");
751                 return;
752             }
753             // add possible pdps to group
754             List<?> pdpsInGroup = transaction.getPdpsInGroup(Long.parseLong(groupRecord.getGroupId()));
755             for (Object pdpO : pdpsInGroup) {
756                 PdpEntity pdp = (PdpEntity) pdpO;
757                 try {
758                     papEngine.newPDP(pdp.getPdpId(), localGroup, pdp.getPdpName(), pdp.getDescription(),
759                             pdp.getJmxPort());
760                 } catch (NullPointerException | PAPException e) {
761                     PolicyLogger.error(MessageCodes.EXCEPTION_ERROR, e, policyDBDaoVar,
762                             "Caught PAPException trying to get create pdp with papEngine.newPDP(pdp.getPdpId(), "
763                                     + "localGroup, pdp.getPdpName(), pdp.getDescription(), pdp.getJmxPort());");
764                     throw new PAPException("Could not create pdp " + pdp);
765                 }
766             }
767             // add possible policies to group (filesystem only, apparently)
768         } else {
769             if (!(localGroup instanceof StdPDPGroup)) {
770                 throw new PAPException("group is not a StdPDPGroup");
771             }
772             // clone the object
773             // because it will be comparing the new group to its own version
774             StdPDPGroup localGroupClone = new StdPDPGroup(localGroup.getId(), localGroup.isDefaultGroup(),
775                     localGroup.getName(), localGroup.getDescription(), ((StdPDPGroup) localGroup).getDirectory());
776             localGroupClone.setOnapPdps(localGroup.getOnapPdps());
777             localGroupClone.setPipConfigs(localGroup.getPipConfigs());
778             localGroupClone.setStatus(localGroup.getStatus());
779             // we are updating a group or adding a policy or changing default
780             // set default if it should be
781             if (!localGroupClone.isDefaultGroup() && groupRecord.isDefaultGroup()) {
782                 try {
783                     papEngine.setDefaultGroup(localGroup);
784                     return;
785                 } catch (PAPException e) {
786                     PolicyLogger.error(MessageCodes.EXCEPTION_ERROR, e, policyDBDaoVar,
787                             "Caught PAPException trying to set default group with papEngine.SetDefaultGroup("
788                                     + localGroupClone + ");");
789                     throw new PAPException("Could not set default group to " + localGroupClone);
790                 }
791             }
792             boolean needToUpdate = false;
793             if (updateGroupPoliciesInFileSystem(localGroupClone, localGroup, groupRecord)) {
794                 needToUpdate = true;
795             }
796             if (!stringEquals(localGroupClone.getId(), groupRecord.getGroupId())
797                     || !stringEquals(localGroupClone.getName(), groupRecord.getgroupName())) {
798                 // changing ids
799                 // we do not want to change the id, the papEngine will do this for us, it needs to know the old id
800                 localGroupClone.setName(groupRecord.getgroupName());
801                 needToUpdate = true;
802             }
803             if (!stringEquals(localGroupClone.getDescription(), groupRecord.getDescription())) {
804                 localGroupClone.setDescription(groupRecord.getDescription());
805                 needToUpdate = true;
806             }
807             if (needToUpdate) {
808                 try {
809                     papEngine.updateGroup(localGroupClone);
810                 } catch (PAPException e) {
811                     PolicyLogger.error(MessageCodes.EXCEPTION_ERROR, e, policyDBDaoVar,
812                             "Caught PAPException trying to update group with papEngine.updateGroup(" + localGroupClone
813                                     + ");");
814                     throw new PAPException("Could not update group " + localGroupClone);
815                 }
816             }
817         }
818     }
819
820     // this will also handle removes, since incoming pdpGroup has no policies internally, we are just going to add
821     // them all in from the db
822     private boolean updateGroupPoliciesInFileSystem(OnapPDPGroup pdpGroup, OnapPDPGroup oldPdpGroup,
823             GroupEntity groupRecord) throws PAPException, PolicyDBException {
824         if (!(pdpGroup instanceof StdPDPGroup)) {
825             throw new PAPException("group is not a StdPDPGroup");
826         }
827         StdPDPGroup group = (StdPDPGroup) pdpGroup;
828         // this must always be true since we don't explicitly know when a delete is occuring
829         boolean didUpdate = true;
830         HashMap<String, PDPPolicy> currentPolicySet = new HashMap<>(oldPdpGroup.getPolicies().size());
831         HashSet<PDPPolicy> newPolicySet = new HashSet<>();
832         for (PDPPolicy pdpPolicy : oldPdpGroup.getPolicies()) {
833             currentPolicySet.put(pdpPolicy.getId(), pdpPolicy);
834         }
835         for (PolicyEntity policy : groupRecord.getPolicies()) {
836             String pdpPolicyName = getPdpPolicyName(policy.getPolicyName(), policy.getScope());
837             if (group.getPolicy(pdpPolicyName) == null) {
838                 didUpdate = true;
839                 if (currentPolicySet.containsKey(pdpPolicyName)) {
840                     newPolicySet.add(currentPolicySet.get(pdpPolicyName));
841                 } else {
842                     logger.info(
843                             "PolicyDBDao: Adding the new policy to the PDP group after notification: " + pdpPolicyName);
844                     InputStream policyStream = new ByteArrayInputStream(policy.getPolicyData().getBytes());
845                     group.copyPolicyToFile(pdpPolicyName, policyStream);
846                     ((StdPDPPolicy) (group.getPolicy(pdpPolicyName)))
847                             .setName(removeExtensionAndVersionFromPolicyName(pdpPolicyName));
848                     try {
849                         policyStream.close();
850                     } catch (IOException e) {
851                         didUpdate = false;
852                         PolicyLogger.error(e.getMessage() + e);
853                     }
854                 }
855             }
856         }
857         logger.info("PolicyDBDao: Adding updated policies to group after notification.");
858         if (didUpdate) {
859             newPolicySet.addAll(group.getPolicies());
860             group.setPolicies(newPolicySet);
861         }
862         return didUpdate;
863     }
864
865     /*
866      * This method is called during all pushPolicy transactions and makes sure the file system group is in sync with the
867      * database groupentity
868      */
869     private StdPDPGroup synchronizeGroupPoliciesInFileSystem(StdPDPGroup pdpGroup, GroupEntity groupentity)
870             throws PAPException, PolicyDBException {
871
872         HashMap<String, PDPPolicy> currentPolicyMap = new HashMap<>();
873         HashSet<String> newPolicyIdSet = new HashSet<>();
874         HashSet<PDPPolicy> newPolicySet = new HashSet<>();
875
876         for (PDPPolicy pdpPolicy : pdpGroup.getPolicies()) {
877             currentPolicyMap.put(pdpPolicy.getId(), pdpPolicy);
878         }
879
880         for (PolicyEntity policy : groupentity.getPolicies()) {
881             String pdpPolicyId = getPdpPolicyName(policy.getPolicyName(), policy.getScope());
882             newPolicyIdSet.add(pdpPolicyId);
883
884             if (currentPolicyMap.containsKey(pdpPolicyId)) {
885                 newPolicySet.add(currentPolicyMap.get(pdpPolicyId));
886             } else {
887                 // convert PolicyEntity object to PDPPolicy
888                 String name = pdpPolicyId.replace(".xml", "");
889                 name = name.substring(0, name.lastIndexOf('.'));
890                 InputStream policyStream = new ByteArrayInputStream(policy.getPolicyData().getBytes());
891                 pdpGroup.copyPolicyToFile(pdpPolicyId, name, policyStream);
892                 URI location = Paths.get(pdpGroup.getDirectory().toAbsolutePath().toString(), pdpPolicyId).toUri();
893                 StdPDPPolicy newPolicy = null;
894                 try {
895                     newPolicy = new StdPDPPolicy(pdpPolicyId, true,
896                             removeExtensionAndVersionFromPolicyName(pdpPolicyId), location);
897                     newPolicySet.add(newPolicy);
898                 } catch (Exception e) {
899                     logger.debug(e);
900                     PolicyLogger
901                             .error("PolicyDBDao: Exception occurred while creating the StdPDPPolicy newPolicy object "
902                                     + e.getMessage());
903                 }
904             }
905         }
906
907         for (String id : currentPolicyMap.keySet()) {
908             if (!newPolicyIdSet.contains(id)) {
909                 try {
910                     Files.delete(Paths.get(currentPolicyMap.get(id).getLocation()));
911                 } catch (Exception e) {
912                     logger.debug(e);
913                     PolicyLogger
914                             .error("PolicyDBDao: Exception occurred while attempting to delete the old version of the"
915                                     + " policy file from the group. " + e.getMessage());
916                 }
917             }
918         }
919
920         logger.info("PolicyDBDao: Adding new policy set to group to keep filesystem and DB in sync");
921         pdpGroup.setPolicies(newPolicySet);
922
923         return pdpGroup;
924     }
925
926     private String removeExtensionAndVersionFromPolicyName(String originalPolicyName) throws PolicyDBException {
927         return getPolicyNameAndVersionFromPolicyFileName(originalPolicyName)[0];
928     }
929
930     /**
931      * Splits apart the policy name and version from a policy file path
932      *
933      * @param originalPolicyName: a policy file name ex: Config_policy.2.xml
934      * @return An array [0]: The policy name, [1]: the policy version, as a string
935      */
936     private String[] getPolicyNameAndVersionFromPolicyFileName(String originalPolicyName) throws PolicyDBException {
937         String policyName = originalPolicyName;
938         String[] nameAndVersion = new String[2];
939         try {
940             policyName = removeFileExtension(policyName);
941             nameAndVersion[0] = policyName.substring(0, policyName.lastIndexOf('.'));
942             if (isNullOrEmpty(nameAndVersion[0])) {
943                 throw new PolicyDBException();
944             }
945         } catch (Exception e) {
946             nameAndVersion[0] = originalPolicyName;
947             logger.debug(e);
948         }
949         try {
950             nameAndVersion[1] = policyName.substring(policyName.lastIndexOf('.') + 1);
951             if (isNullOrEmpty(nameAndVersion[1])) {
952                 throw new PolicyDBException();
953             }
954         } catch (Exception e) {
955             nameAndVersion[1] = "1";
956             logger.debug(e);
957         }
958         return nameAndVersion;
959     }
960
961     private void handleIncomingPdpChange(String pdpId, PolicyDBDaoTransaction transaction) throws PAPException {
962         // get pdp
963         long pdpIdLong = -1;
964         try {
965             pdpIdLong = Long.parseLong(pdpId);
966         } catch (NumberFormatException e) {
967             throw new IllegalArgumentException("pdpId " + pdpId + " cannot be parsed into a long");
968         }
969         PdpEntity pdpRecord = null;
970         try {
971             pdpRecord = transaction.getPdp(pdpIdLong);
972         } catch (Exception e) {
973             PolicyLogger.error(MessageCodes.EXCEPTION_ERROR, e, policyDBDaoVar,
974                     "Caught Exception trying to get pdp record with transaction.getPdp(" + pdpIdLong + ");");
975             throw new PAPException("Could not get local pdp " + pdpIdLong);
976         }
977         if (pdpRecord == null) {
978             throw new PersistenceException("The pdpRecord returned is null");
979         }
980         PDP localPdp = null;
981         try {
982             localPdp = papEngine.getPDP(pdpRecord.getPdpId());
983         } catch (PAPException e) {
984             logger.warn("Caught PAPException trying to get local pdp  with papEngine.getPDP(" + pdpId + ");", e);
985         }
986         if (localPdp != null && pdpRecord.isDeleted()) {
987             try {
988                 papEngine.removePDP((OnapPDP) localPdp);
989             } catch (PAPException e) {
990                 PolicyLogger.error(MessageCodes.EXCEPTION_ERROR, e, policyDBDaoVar,
991                         "Caught PAPException trying to get remove pdp with papEngine.removePDP(" + localPdp + ");");
992                 throw new PAPException("Could not remove pdp " + pdpId);
993             }
994         } else if (localPdp == null) {
995             // add new pdp
996             // get group
997             OnapPDPGroup localGroup = null;
998             try {
999                 localGroup = papEngine.getGroup(pdpRecord.getGroup().getGroupId());
1000             } catch (PAPException e1) {
1001                 PolicyLogger.error(MessageCodes.EXCEPTION_ERROR, e1, policyDBDaoVar,
1002                         "Caught PAPException trying to get local group to add pdp to with papEngine.getGroup"
1003                                 + "(pdpRecord.getGroup().getGroupId());");
1004                 throw new PAPException("Could not get local group");
1005             }
1006             try {
1007                 papEngine.newPDP(pdpRecord.getPdpId(), localGroup, pdpRecord.getPdpName(), pdpRecord.getDescription(),
1008                         pdpRecord.getJmxPort());
1009             } catch (NullPointerException | PAPException e) {
1010                 PolicyLogger.error(MessageCodes.EXCEPTION_ERROR, e, policyDBDaoVar,
1011                         "Caught PAPException trying to create pdp with papEngine.newPDP(" + pdpRecord.getPdpId() + ", "
1012                                 + localGroup + ", " + pdpRecord.getPdpName() + ", " + pdpRecord.getDescription() + ", "
1013                                 + pdpRecord.getJmxPort() + ");");
1014                 throw new PAPException("Could not create pdp " + pdpRecord);
1015             }
1016         } else {
1017             boolean needToUpdate = false;
1018             if (!stringEquals(localPdp.getId(), pdpRecord.getPdpId())
1019                     || !stringEquals(localPdp.getName(), pdpRecord.getPdpName())) {
1020                 // again, we don't want to change the id, the papEngine will do this
1021                 localPdp.setName(pdpRecord.getPdpName());
1022                 needToUpdate = true;
1023             }
1024             if (!stringEquals(localPdp.getDescription(), pdpRecord.getDescription())) {
1025                 localPdp.setDescription(pdpRecord.getDescription());
1026                 needToUpdate = true;
1027             }
1028             String localPdpGroupId = null;
1029             try {
1030                 localPdpGroupId = papEngine.getPDPGroup((OnapPDP) localPdp).getId();
1031             } catch (PAPException e) {
1032                 // could be null or something, just warn at this point
1033                 logger.warn("Caught PAPException trying to get id of local group that pdp is in with localPdpGroupId = "
1034                         + "papEngine.getPDPGroup(localPdp).getId();", e);
1035             }
1036             if (!stringEquals(localPdpGroupId, pdpRecord.getGroup().getGroupId())) {
1037                 OnapPDPGroup newPdpGroup = null;
1038                 try {
1039                     newPdpGroup = papEngine.getGroup(pdpRecord.getGroup().getGroupId());
1040                 } catch (PAPException e) {
1041                     // ok, now we have an issue. Time to stop things
1042                     PolicyLogger.error(MessageCodes.EXCEPTION_ERROR, e, policyDBDaoVar,
1043                             "Caught PAPException trying to get id of local group to move pdp to with papEngine"
1044                                     + ".getGroup(pdpRecord.getGroup().getGroupId());");
1045                     throw new PAPException("Could not get local group");
1046                 }
1047                 try {
1048                     papEngine.movePDP((OnapPDP) localPdp, newPdpGroup);
1049                 } catch (PAPException e) {
1050                     PolicyLogger.error(MessageCodes.EXCEPTION_ERROR, e, policyDBDaoVar,
1051                             "Caught PAPException trying to move pdp with papEngine.movePDP(localPdp, newPdpGroup);");
1052                     throw new PAPException("Could not move pdp " + localPdp);
1053                 }
1054             }
1055             if (((PdpEntity) localPdp).getJmxPort() != pdpRecord.getJmxPort()) {
1056                 ((PdpEntity) localPdp).setJmxPort(pdpRecord.getJmxPort());
1057                 needToUpdate = true;
1058             }
1059             if (needToUpdate) {
1060                 try {
1061                     papEngine.updatePDP((OnapPDP) localPdp);
1062                 } catch (PAPException e) {
1063                     PolicyLogger.error(MessageCodes.EXCEPTION_ERROR, e, policyDBDaoVar,
1064                             "Caught PAPException trying to update pdp with papEngine.updatePdp(" + localPdp + ");");
1065                     throw new PAPException("Could not update pdp " + localPdp);
1066                 }
1067             }
1068         }
1069         // compare to local situation
1070         // call command to update
1071     }
1072
1073     private void handleIncomingPolicyChange(String policyId) {
1074         String policyName = null;
1075         EntityManager em = emf.createEntityManager();
1076         Query getPolicyEntityQuery = em.createNamedQuery("PolicyEntity.FindById");
1077         getPolicyEntityQuery.setParameter("id", Long.valueOf(policyId));
1078
1079         @SuppressWarnings("unchecked")
1080         List<PolicyEntity> policies = getPolicyEntityQuery.getResultList();
1081         PolicyEntity policy = null;
1082         if (!policies.isEmpty()) {
1083             policy = policies.get(0);
1084         }
1085         String action = "unknown action";
1086         try {
1087             if (policy != null) {
1088                 policyName = policy.getPolicyName();
1089                 logger.info("Deleting old Policy Config File for " + policy.getPolicyName());
1090                 action = "delete";
1091                 Path subFile = null;
1092
1093                 if (policy.getConfigurationData() != null) {
1094                     subFile = getPolicySubFile(policy.getConfigurationData().getConfigurationName(), config);
1095                 } else if (policy.getActionBodyEntity() != null) {
1096                     subFile = getPolicySubFile(policy.getActionBodyEntity().getActionBodyName(), action);
1097                 }
1098
1099                 if (subFile != null) {
1100                     Files.deleteIfExists(subFile);
1101                 }
1102                 if (policy.getConfigurationData() != null) {
1103                     writePolicySubFile(policy, config);
1104                 } else if (policy.getActionBodyEntity() != null) {
1105                     writePolicySubFile(policy, action);
1106                 }
1107             }
1108         } catch (IOException e1) {
1109             PolicyLogger.error(MessageCodes.EXCEPTION_ERROR, e1, policyDBDaoVar,
1110                     "Error occurred while performing [" + action + "] of Policy File: " + policyName);
1111         }
1112     }
1113
1114     private String getPdpPolicyName(String name, String scope) {
1115         String finalName = "";
1116         finalName += scope;
1117         finalName += ".";
1118         finalName += removeFileExtension(name);
1119         finalName += ".xml";
1120         return finalName;
1121     }
1122
1123     private String removeFileExtension(String fileName) {
1124         return fileName.substring(0, fileName.lastIndexOf('.'));
1125     }
1126
1127     private Path getPolicySubFile(String inputFileName, String subFileType) {
1128         String filename = inputFileName;
1129         logger.info("getPolicySubFile(" + filename + ", " + subFileType + ")");
1130         Path filePath = Paths.get(XACMLProperties.getProperty(XACMLRestProperties.PROP_PAP_WEBAPPS), subFileType);
1131         File file = null;
1132
1133         filename = FilenameUtils.removeExtension(filename);
1134
1135         for (File tmpFile : filePath.toFile().listFiles()) {
1136             if (FilenameUtils.removeExtension(tmpFile.getName()).equals(filename)) {
1137                 file = tmpFile;
1138             }
1139         }
1140
1141         Path finalPath = null;
1142         if (file != null) {
1143             finalPath = Paths.get(file.getAbsolutePath());
1144         }
1145
1146         logger.info("end of getPolicySubFile: " + finalPath);
1147         return finalPath;
1148     }
1149
1150     private boolean writePolicySubFile(PolicyEntity policy, String policyType) {
1151         logger.info("writePolicySubFile with policyName[" + policy.getPolicyName() + "] and policyType[" + policyType
1152                 + "]");
1153         String type = null;
1154         String subTypeName = null;
1155         String subTypeBody = null;
1156         if (config.equalsIgnoreCase(policyType)) {
1157             type = config;
1158             subTypeName = FilenameUtils.removeExtension(policy.getConfigurationData().getConfigurationName());
1159             subTypeBody = policy.getConfigurationData().getConfigBody();
1160
1161             String configType = policy.getConfigurationData().getConfigType();
1162
1163             if (configType != null) {
1164                 if (configType.equals(JSON_CONFIG)) {
1165                     subTypeName = subTypeName + ".json";
1166                 }
1167                 if (configType.equals(XML_CONFIG)) {
1168                     subTypeName = subTypeName + ".xml";
1169                 }
1170                 if (configType.equals(PROPERTIES_CONFIG)) {
1171                     subTypeName = subTypeName + ".properties";
1172                 }
1173                 if (configType.equals(OTHER_CONFIG)) {
1174                     subTypeName = subTypeName + ".txt";
1175                 }
1176             }
1177         } else if (action.equalsIgnoreCase(policyType)) {
1178             type = action;
1179             subTypeName = policy.getActionBodyEntity().getActionBodyName();
1180             subTypeBody = policy.getActionBodyEntity().getActionBody();
1181         }
1182         Path filePath = Paths.get(XACMLProperties.getProperty(XACMLRestProperties.PROP_PAP_WEBAPPS).toString(), type);
1183
1184         if (subTypeBody == null) {
1185             subTypeBody = "";
1186         }
1187         boolean success = false;
1188         try {
1189             Files.deleteIfExists(Paths.get(filePath.toString(), subTypeName));
1190             File file = Paths.get(filePath.toString(), subTypeName).toFile();
1191             boolean value = file.createNewFile();
1192             logger.debug("New file created successfully" + value);
1193             try (FileWriter fileWriter = new FileWriter(file, false)) {
1194                 // false to overwrite
1195                 fileWriter.write(subTypeBody);
1196                 fileWriter.close();
1197                 success = true;
1198             }
1199         } catch (Exception e) {
1200             PolicyLogger.error(MessageCodes.EXCEPTION_ERROR, e, policyDBDaoVar,
1201                     "Exception occured while creating Configuration File for Policy : " + policy.getPolicyName());
1202         }
1203         return success;
1204     }
1205
1206     public void auditLocalDatabase(PAPPolicyEngine papEngine2) {
1207         logger.debug("PolicyDBDao.auditLocalDatabase() is called");
1208         try {
1209             deleteAllGroupTables();
1210             auditGroups(papEngine2);
1211         } catch (Exception e) {
1212             PolicyLogger.error(MessageCodes.EXCEPTION_ERROR, e, policyDBDaoVar, "auditLocalDatabase() error");
1213             logger.error("Exception Occured" + e);
1214         }
1215     }
1216
1217
1218     public StdPDPGroup auditLocalFileSystem(StdPDPGroup group) {
1219
1220         logger.info("Starting Local File System group audit");
1221         EntityManager em = emf.createEntityManager();
1222         em.getTransaction().begin();
1223
1224         StdPDPGroup updatedGroup = null;
1225         try {
1226             Query groupQuery = em.createQuery(groupEntitySelectQuery);
1227             groupQuery.setParameter(groupIdVar, group.getId());
1228             groupQuery.setParameter(deletedVar, false);
1229             List<?> groupQueryList = groupQuery.getResultList();
1230             if (groupQueryList != null && !groupQueryList.isEmpty()) {
1231                 GroupEntity dbgroup = (GroupEntity) groupQueryList.get(0);
1232                 updatedGroup = synchronizeGroupPoliciesInFileSystem(group, dbgroup);
1233                 logger.info("Group was updated during file system audit: " + updatedGroup.toString());
1234             }
1235         } catch (PAPException | PolicyDBException e) {
1236             logger.error(e);
1237         } catch (Exception e) {
1238             logger.error(e);
1239             PolicyLogger.error(MessageCodes.EXCEPTION_ERROR, e, policyDBDaoVar,
1240                     "Caught Exception trying to check if group exists groupQuery.getResultList()");
1241             throw new PersistenceException("Query failed trying to check if group " + group.getId() + " exists");
1242         }
1243
1244         em.getTransaction().commit();
1245         em.close();
1246
1247         return updatedGroup;
1248
1249     }
1250
1251     public void deleteAllGroupTables() {
1252         logger.debug("PolicyDBDao.deleteAllGroupTables() called");
1253         EntityManager em = emf.createEntityManager();
1254         em.getTransaction().begin();
1255
1256         Query deletePdpEntityEntityTableUpdate = em.createNamedQuery("PdpEntity.deleteAll");
1257         deletePdpEntityEntityTableUpdate.executeUpdate();
1258
1259         Query deleteGroupEntityTableUpdate = em.createNamedQuery("GroupEntity.deleteAll");
1260         deleteGroupEntityTableUpdate.executeUpdate();
1261
1262         em.getTransaction().commit();
1263         em.close();
1264     }
1265
1266     @SuppressWarnings("unchecked")
1267     public void auditGroups(PAPPolicyEngine papEngine2) {
1268         logger.debug("PolicyDBDao.auditGroups() called");
1269
1270         EntityManager em = emf.createEntityManager();
1271         em.getTransaction().begin();
1272         final String AUDIT_STR = "Audit";
1273         try {
1274
1275             Set<OnapPDPGroup> groups = papEngine2.getOnapPDPGroups();
1276
1277             for (OnapPDPGroup grp : groups) {
1278                 try {
1279                     GroupEntity groupEntity = new GroupEntity();
1280                     em.persist(groupEntity);
1281                     groupEntity.setGroupName(grp.getName());
1282                     groupEntity.setDescription(grp.getDescription());
1283                     groupEntity.setDefaultGroup(grp.isDefaultGroup());
1284                     groupEntity.setCreatedBy(AUDIT_STR);
1285                     groupEntity.setGroupId(createNewPDPGroupId(grp.getId()));
1286                     groupEntity.setModifiedBy(AUDIT_STR);
1287                     Set<OnapPDP> pdps = grp.getOnapPdps();
1288
1289                     for (OnapPDP pdp : pdps) {
1290                         PdpEntity pdpEntity = new PdpEntity();
1291                         em.persist(pdpEntity);
1292                         pdpEntity.setGroup(groupEntity);
1293                         pdpEntity.setJmxPort(pdp.getJmxPort());
1294                         pdpEntity.setPdpId(pdp.getId());
1295                         pdpEntity.setPdpName(pdp.getName());
1296                         pdpEntity.setModifiedBy(AUDIT_STR);
1297                         pdpEntity.setCreatedBy(AUDIT_STR);
1298
1299                     }
1300
1301                     Set<PDPPolicy> policies = grp.getPolicies();
1302
1303                     for (PDPPolicy policy : policies) {
1304                         try {
1305                             String[] stringArray = getNameScopeAndVersionFromPdpPolicy(policy.getId());
1306                             if (stringArray == null) {
1307                                 throw new IllegalArgumentException(
1308                                         "Invalid input - policyID must contain name, scope and version");
1309                             }
1310                             List<PolicyEntity> policyEntityList;
1311                             Query getPolicyEntitiesQuery = em.createNamedQuery("PolicyEntity.findByNameAndScope");
1312                             getPolicyEntitiesQuery.setParameter("name", stringArray[0]);
1313                             getPolicyEntitiesQuery.setParameter(scope, stringArray[1]);
1314
1315                             policyEntityList = getPolicyEntitiesQuery.getResultList();
1316                             PolicyEntity policyEntity = null;
1317                             if (!policyEntityList.isEmpty()) {
1318                                 policyEntity = policyEntityList.get(0);
1319                             }
1320                             if (policyEntity != null) {
1321                                 groupEntity.addPolicyToGroup(policyEntity);
1322                             }
1323                         } catch (Exception e2) {
1324                             PolicyLogger.error(MessageCodes.EXCEPTION_ERROR, e2, policyDBDaoVar,
1325                                     "Exception auditGroups inner catch");
1326                         }
1327                     }
1328                 } catch (Exception e1) {
1329                     PolicyLogger.error(MessageCodes.EXCEPTION_ERROR, e1, policyDBDaoVar,
1330                             "Exception auditGroups middle catch");
1331                 }
1332             }
1333         } catch (Exception e) {
1334             em.getTransaction().rollback();
1335             PolicyLogger.error(MessageCodes.EXCEPTION_ERROR, e, policyDBDaoVar, "Exception auditGroups outer catch");
1336             em.close();
1337             return;
1338         }
1339
1340         em.getTransaction().commit();
1341         em.close();
1342
1343     }
1344
1345     private String getConfigFile(String filename, PolicyRestAdapter policy) {
1346         if (policy == null) {
1347             return getConfigFile(filename, (String) null);
1348         }
1349         return getConfigFile(filename, policy.getConfigType());
1350     }
1351
1352     // copied from ConfigPolicy.java and modified
1353     // Here we are adding the extension for the configurations file based on the
1354     // config type selection for saving.
1355     private String getConfigFile(String inputFilename, String configType) {
1356         String filename = inputFilename;
1357         logger.debug("getConfigFile(String filename, String scope, String configType) as getConfigFile(" + filename
1358                 + ", " + configType + ") called");
1359         filename = FilenameUtils.removeExtension(filename);
1360         String id = configType;
1361
1362         if (id != null) {
1363             if (id.equals(ConfigPolicy.JSON_CONFIG) || id.contains("Firewall")) {
1364                 filename = filename + ".json";
1365             }
1366             if (id.equals(ConfigPolicy.XML_CONFIG)) {
1367                 filename = filename + ".xml";
1368             }
1369             if (id.equals(ConfigPolicy.PROPERTIES_CONFIG)) {
1370                 filename = filename + ".properties";
1371             }
1372             if (id.equals(ConfigPolicy.OTHER_CONFIG)) {
1373                 filename = filename + ".txt";
1374             }
1375         }
1376         return filename;
1377     }
1378
1379     private String[] getNameScopeAndVersionFromPdpPolicy(String fileName) {
1380         String[] splitByDots = fileName.split("\\.");
1381         if (splitByDots.length < 3) {
1382             return null;
1383         }
1384         String policyName = splitByDots[splitByDots.length - 3];
1385         String version = splitByDots[splitByDots.length - 2];
1386         // policy names now include version
1387         String scope = "";
1388         for (int i = 0; i < splitByDots.length - 3; i++) {
1389             scope += ".".concat(splitByDots[i]);
1390         }
1391         // remove the first dot
1392         if (scope.length() > 0) {
1393             scope = scope.substring(1);
1394         }
1395         String[] returnArray = new String[3];
1396         returnArray[0] = policyName + "." + version + ".xml";
1397         returnArray[2] = version;
1398         returnArray[1] = scope;
1399         return returnArray;
1400     }
1401
1402     public static String createNewPDPGroupId(String name) {
1403         String id = name;
1404         // replace "bad" characters with sequences that will be ok for file names and properties keys.
1405         id = id.replace(" ", "_sp_");
1406         id = id.replace("\t", "_tab_");
1407         id = id.replace("\\", "_bksl_");
1408         id = id.replace("/", "_sl_");
1409         id = id.replace(":", "_col_");
1410         id = id.replace("*", "_ast_");
1411         id = id.replace("?", "_q_");
1412         id = id.replace("\"", "_quo_");
1413         id = id.replace("<", "_lt_");
1414         id = id.replace(">", "_gt_");
1415         id = id.replace("|", "_bar_");
1416         id = id.replace("=", "_eq_");
1417         id = id.replace(",", "_com_");
1418         id = id.replace(";", "_scom_");
1419
1420         return id;
1421     }
1422
1423     /**
1424      * Checks if any of the given strings are empty or null
1425      *
1426      * @param strings One or more Strings (or nulls) to check if they are null or empty
1427      * @return true if one or more of the given strings are empty or null
1428      */
1429     public static boolean isNullOrEmpty(String... strings) {
1430         for (String s : strings) {
1431             if (s == null || "".equals(s)) {
1432                 return true;
1433             }
1434         }
1435         return false;
1436     }
1437
1438
1439     private class PolicyDBDaoTransactionInstance implements PolicyDBDaoTransaction {
1440         private EntityManager em;
1441         private final Object emLock = new Object();
1442         long policyId;
1443         long groupId;
1444         long pdpId;
1445         String newGroupId;
1446         private boolean operationRun = false;
1447         private final Thread transactionTimer;
1448
1449         private PolicyDBDaoTransactionInstance() {
1450             // call the constructor with arguments
1451             this(Integer.parseInt(XACMLProperties.getProperty(XACMLRestProperties.PROP_PAP_TRANS_TIMEOUT)),
1452                     Integer.parseInt(XACMLProperties.getProperty(XACMLRestProperties.PROP_PAP_TRANS_WAIT)));
1453         }
1454
1455         // timeout is how long the transaction can sit before rolling back
1456         // wait time is how long to wait for the transaction to start before throwing an exception
1457         private PolicyDBDaoTransactionInstance(int transactionTimeout, int transactionWaitTime) {
1458             if (logger.isDebugEnabled()) {
1459                 logger.debug("\n\nPolicyDBDaoTransactionInstance() as PolicyDBDaoTransactionInstance() called:"
1460                         + "\n   transactionTimeout = " + transactionTimeout + "\n   transactionWaitTime = "
1461                         + transactionWaitTime + "\n\n");
1462             }
1463             this.em = emf.createEntityManager();
1464             policyId = -1;
1465             groupId = -1;
1466             pdpId = -1;
1467             newGroupId = null;
1468             synchronized (emLock) {
1469                 try {
1470                     startTransactionSynced(this.em, transactionWaitTime);
1471                 } catch (Exception e) {
1472                     logger.debug(e);
1473                     throw new PersistenceException(
1474                             "Could not lock transaction within " + transactionWaitTime + " milliseconds");
1475                 }
1476             }
1477             class TransactionTimer implements Runnable {
1478
1479                 private int sleepTime;
1480
1481                 public TransactionTimer(int timeout) {
1482                     this.sleepTime = timeout;
1483                 }
1484
1485                 @Override
1486                 public void run() {
1487                     if (logger.isDebugEnabled()) {
1488                         Date date = new java.util.Date();
1489                         logger.debug("\n\nTransactionTimer.run() - SLEEPING: " + "\n   sleepTime (ms) = " + sleepTime
1490                                 + TIMESTAMP + date.getTime() + "\n\n");
1491                     }
1492                     try {
1493                         Thread.sleep(sleepTime);
1494                     } catch (InterruptedException e) {
1495                         // probably, the transaction was completed, the last thing we want to do is roll back
1496                         if (logger.isDebugEnabled()) {
1497                             Date date = new java.util.Date();
1498                             logger.debug("\n\nTransactionTimer.run() - WAKE Interrupt: " + TIMESTAMP
1499                                     + date.getTime() + "\n\n");
1500                         }
1501                         Thread.currentThread().interrupt();
1502                         return;
1503                     }
1504                     if (logger.isDebugEnabled()) {
1505                         Date date = new java.util.Date();
1506                         logger.debug("\n\nTransactionTimer.run() - WAKE Timeout: " + TIMESTAMP
1507                                 + date.getTime() + "\n\n");
1508                     }
1509                     rollbackTransaction();
1510                 }
1511
1512             }
1513
1514             transactionTimer = new Thread(new TransactionTimer(transactionTimeout), "transactionTimerThread");
1515             transactionTimer.start();
1516
1517
1518         }
1519
1520         private void checkBeforeOperationRun() {
1521             checkBeforeOperationRun(false);
1522         }
1523
1524         private void checkBeforeOperationRun(boolean justCheckOpen) {
1525             if (!isTransactionOpen()) {
1526                 PolicyLogger.error("There is no transaction currently open");
1527                 throw new IllegalStateException("There is no transaction currently open");
1528             }
1529             if (operationRun && !justCheckOpen) {
1530                 PolicyLogger.error(
1531                         "An operation has already been performed and the current transaction should be " + "committed");
1532                 throw new IllegalStateException(
1533                         "An operation has already been performed and the current transaction should be committed");
1534             }
1535             operationRun = true;
1536         }
1537
1538         @Override
1539         public void commitTransaction() {
1540             synchronized (emLock) {
1541                 logger.debug("commitTransaction() as commitTransaction() called");
1542                 if (!isTransactionOpen()) {
1543                     logger.warn("There is no open transaction to commit");
1544                     try {
1545                         em.close();
1546                     } catch (Exception e) {
1547                         logger.error("Exception Occured" + e);
1548                     }
1549                     return;
1550                 }
1551                 try {
1552                     em.getTransaction().commit();
1553                 } catch (RollbackException e) {
1554                     PolicyLogger.error(MessageCodes.EXCEPTION_ERROR, e, policyDBDaoVar,
1555                             "Caught RollbackException on em.getTransaction().commit()");
1556                     throw new PersistenceException("The commit failed. Message:\n" + e.getMessage());
1557                 }
1558                 em.close();
1559                 // need to revisit
1560                 if (policyId >= 0) {
1561                     if (newGroupId != null) {
1562                         try {
1563                             notifyOthers(policyId, POLICY_NOTIFICATION, newGroupId);
1564                         } catch (Exception e) {
1565                             PolicyLogger.error(MessageCodes.EXCEPTION_ERROR, e, policyDBDaoVar,
1566                                     CAUGHTEXCEPTIONONNOTIFY + policyId + "," + POLICY_NOTIFICATION + ","
1567                                             + newGroupId + ")");
1568                         }
1569                     } else {
1570                         try {
1571                             notifyOthers(policyId, POLICY_NOTIFICATION);
1572                         } catch (Exception e) {
1573                             PolicyLogger.error(MessageCodes.EXCEPTION_ERROR, e, policyDBDaoVar,
1574                                     CAUGHTEXCEPTIONONNOTIFY + policyId + "," + POLICY_NOTIFICATION + ")");
1575                         }
1576                     }
1577                 }
1578                 if (groupId >= 0) {
1579                     // we don't want commit to fail just because this does
1580                     if (newGroupId != null) {
1581                         try {
1582                             notifyOthers(groupId, GROUP_NOTIFICATION, newGroupId);
1583                         } catch (Exception e) {
1584                             PolicyLogger.error(MessageCodes.EXCEPTION_ERROR, e, policyDBDaoVar,
1585                                     CAUGHTEXCEPTIONONNOTIFY + groupId + "," + GROUP_NOTIFICATION + ","
1586                                             + newGroupId + ")");
1587                         }
1588                     } else {
1589                         try {
1590                             notifyOthers(groupId, GROUP_NOTIFICATION);
1591                         } catch (Exception e) {
1592                             PolicyLogger.error(MessageCodes.EXCEPTION_ERROR, e, policyDBDaoVar,
1593                                     CAUGHTEXCEPTIONONNOTIFY + groupId + "," + GROUP_NOTIFICATION + ")");
1594                         }
1595                     }
1596                 }
1597                 if (pdpId >= 0) {
1598                     // we don't want commit to fail just because this does
1599                     try {
1600                         notifyOthers(pdpId, PDP_NOTIFICATION);
1601                     } catch (Exception e) {
1602                         PolicyLogger.error(MessageCodes.EXCEPTION_ERROR, e, policyDBDaoVar,
1603                                 CAUGHTEXCEPTIONONNOTIFY + pdpId + "," + PDP_NOTIFICATION + ")");
1604                     }
1605                 }
1606             }
1607             if (transactionTimer != null) {
1608                 transactionTimer.interrupt();
1609             }
1610         }
1611
1612         @Override
1613         public void rollbackTransaction() {
1614             logger.debug("rollbackTransaction() as rollbackTransaction() called");
1615             synchronized (emLock) {
1616                 if (isTransactionOpen()) {
1617
1618                     try {
1619                         em.getTransaction().rollback();
1620                     } catch (Exception e) {
1621                         PolicyLogger.error(MessageCodes.EXCEPTION_ERROR, e, policyDBDaoVar,
1622                                 "Could not rollback transaction");
1623                     }
1624                     try {
1625                         em.close();
1626                     } catch (Exception e) {
1627                         PolicyLogger.error(MessageCodes.EXCEPTION_ERROR, e, policyDBDaoVar,
1628                                 "Could not close EntityManager");
1629                     }
1630
1631                 } else {
1632                     try {
1633                         em.close();
1634                     } catch (Exception e) {
1635                         logger.warn("Could not close already closed transaction", e);
1636                     }
1637                 }
1638
1639             }
1640             if (transactionTimer != null) {
1641                 transactionTimer.interrupt();
1642             }
1643         }
1644
1645         private void createPolicy(PolicyRestAdapter policy, String username, String policyScope, String inputPolicyName,
1646                 String policyDataString) {
1647             String policyName = inputPolicyName;
1648             logger.debug(
1649                     "createPolicy(PolicyRestAdapter policy, String username, String policyScope, String policyName, "
1650                             + "String policyDataString) as createPolicy(" + policy + ", " + username + ", "
1651                             + policyScope + ", " + policyName + ", " + policyDataString + ") called");
1652             synchronized (emLock) {
1653                 checkBeforeOperationRun();
1654                 String configName = policyName;
1655                 if (policyName.contains("Config_")) {
1656                     policyName = policyName.replace(".Config_", ":Config_");
1657                 } else if (policyName.contains("Action_")) {
1658                     policyName = policyName.replace(".Action_", ":Action_");
1659                 } else if (policyName.contains("Decision_")) {
1660                     policyName = policyName.replace(".Decision_", ":Decision_");
1661                 }
1662                 policyName = policyName.split(":")[1];
1663                 Query createPolicyQuery = em
1664                         .createQuery("SELECT p FROM PolicyEntity p WHERE p.scope=:scope AND p.policyName=:policyName");
1665                 createPolicyQuery.setParameter(scope, policyScope);
1666                 createPolicyQuery.setParameter("policyName", policyName);
1667                 List<?> createPolicyQueryList = createPolicyQuery.getResultList();
1668                 PolicyEntity newPolicyEntity;
1669                 boolean update;
1670                 if (createPolicyQueryList.isEmpty()) {
1671                     newPolicyEntity = new PolicyEntity();
1672                     update = false;
1673                 } else if (createPolicyQueryList.size() > 1) {
1674                     PolicyLogger
1675                             .error("Somehow, more than one policy with the same scope, name, and deleted status were "
1676                                     + "found in the database");
1677                     throw new PersistenceException(
1678                             "Somehow, more than one policy with the same scope, name, and deleted status were found "
1679                                     + "in the database");
1680                 } else {
1681                     newPolicyEntity = (PolicyEntity) createPolicyQueryList.get(0);
1682                     update = true;
1683                 }
1684
1685                 ActionBodyEntity newActionBodyEntity = null;
1686                 if (policy.getPolicyType().equals(action)) {
1687                     boolean abupdate = false;
1688                     if (newPolicyEntity.getActionBodyEntity() == null) {
1689                         newActionBodyEntity = new ActionBodyEntity();
1690                     } else {
1691                         newActionBodyEntity = em.find(ActionBodyEntity.class,
1692                                 newPolicyEntity.getActionBodyEntity().getActionBodyId());
1693                         abupdate = true;
1694                     }
1695
1696                     if (newActionBodyEntity != null) {
1697                         if (!abupdate) {
1698                             em.persist(newActionBodyEntity);
1699                         }
1700                         // build the file path
1701                         // trim the .xml off the end
1702                         String policyNameClean = FilenameUtils.removeExtension(configName);
1703                         String actionBodyName = policyNameClean + ".json";
1704
1705                         // get the action body
1706                         String actionBodyString = policy.getActionBody();
1707                         if (actionBodyString == null) {
1708                             actionBodyString = "{}";
1709                         }
1710                         newActionBodyEntity.setActionBody(actionBodyString);
1711                         newActionBodyEntity.setActionBodyName(actionBodyName);
1712                         newActionBodyEntity.setModifiedBy("PolicyDBDao.createPolicy()");
1713                         newActionBodyEntity.setDeleted(false);
1714                         if (!abupdate) {
1715                             newActionBodyEntity.setCreatedBy("PolicyDBDao.createPolicy()");
1716                         }
1717                         if (logger.isDebugEnabled()) {
1718                             logger.debug("\nPolicyDBDao.createPolicy" + "\n   newActionBodyEntity.getActionBody() = "
1719                                     + newActionBodyEntity.getActionBody()
1720                                     + "\n   newActionBodyEntity.getActionBodyName() = "
1721                                     + newActionBodyEntity.getActionBodyName()
1722                                     + "\n   newActionBodyEntity.getModifiedBy() = "
1723                                     + newActionBodyEntity.getModifiedBy() + "\n   newActionBodyEntity.getCreatedBy() = "
1724                                     + newActionBodyEntity.getCreatedBy() + "\n   newActionBodyEntity.isDeleted() = "
1725                                     + newActionBodyEntity.isDeleted() + "\n   FLUSHING to DB");
1726                         }
1727                         // push the actionBodyEntity to the DB
1728                         em.flush();
1729                     } else {
1730                         // newActionBodyEntity == null
1731                         // We have a actionBody in the policy but we found no actionBody in the DB
1732                         String msg = "\n\nPolicyDBDao.createPolicy - Incoming Action policy had an "
1733                                 + "actionBody, but it could not be found in the DB for update." + "\n  policyScope = "
1734                                 + policyScope + "\n  policyName = " + policyName + "\n\n";
1735                         PolicyLogger
1736                                 .error("PolicyDBDao.createPolicy - Incoming Action policy had an actionBody, but it "
1737                                         + "could not be found in the DB for update: policyName = " + policyName);
1738                         throw new IllegalArgumentException(msg);
1739                     }
1740                 }
1741
1742                 ConfigurationDataEntity newConfigurationDataEntity;
1743                 if (policy.getPolicyType().equals(config)) {
1744                     boolean configUpdate;
1745                     if (newPolicyEntity.getConfigurationData() == null) {
1746                         newConfigurationDataEntity = new ConfigurationDataEntity();
1747                         configUpdate = false;
1748                     } else {
1749                         newConfigurationDataEntity = em.find(ConfigurationDataEntity.class,
1750                                 newPolicyEntity.getConfigurationData().getConfigurationDataId());
1751                         configUpdate = true;
1752                     }
1753
1754                     if (newConfigurationDataEntity != null) {
1755                         if (!configUpdate) {
1756                             em.persist(newConfigurationDataEntity);
1757                         }
1758                         if (!stringEquals(newConfigurationDataEntity.getConfigurationName(),
1759                                 getConfigFile(configName, policy))) {
1760                             newConfigurationDataEntity.setConfigurationName(getConfigFile(configName, policy));
1761                         }
1762                         if (newConfigurationDataEntity.getConfigType() == null
1763                                 || !newConfigurationDataEntity.getConfigType().equals(policy.getConfigType())) {
1764                             newConfigurationDataEntity.setConfigType(policy.getConfigType());
1765                         }
1766                         if (!configUpdate) {
1767                             newConfigurationDataEntity.setCreatedBy(username);
1768                         }
1769                         if (newConfigurationDataEntity.getModifiedBy() == null
1770                                 || !newConfigurationDataEntity.getModifiedBy().equals(username)) {
1771                             newConfigurationDataEntity.setModifiedBy(username);
1772                         }
1773                         if (newConfigurationDataEntity.getDescription() == null
1774                                 || !"".equals(newConfigurationDataEntity.getDescription())) {
1775                             newConfigurationDataEntity.setDescription("");
1776                         }
1777                         if (newConfigurationDataEntity.getConfigBody() == null
1778                                 || newConfigurationDataEntity.getConfigBody().isEmpty()
1779                                 || (!newConfigurationDataEntity.getConfigBody().equals(policy.getConfigBodyData()))) {
1780                             // hopefully one of these won't be null
1781                             if (policy.getConfigBodyData() == null || policy.getConfigBodyData().isEmpty()) {
1782                                 newConfigurationDataEntity.setConfigBody(policy.getJsonBody());
1783                             } else {
1784                                 newConfigurationDataEntity.setConfigBody(policy.getConfigBodyData());
1785                             }
1786                         }
1787                         if (newConfigurationDataEntity.isDeleted()) {
1788                             newConfigurationDataEntity.setDeleted(false);
1789                         }
1790
1791                         em.flush();
1792                     } else {
1793                         // We have a configurationData body in the policy but we found no configurationData body in
1794                         // the DB
1795                         String msg = "\n\nPolicyDBDao.createPolicy - Incoming Config policy had a "
1796                                 + "configurationData body, but it could not be found in the DB for update."
1797                                 + "\n  policyScope = " + policyScope + "\n  policyName = " + policyName + "\n\n";
1798                         PolicyLogger.error("PolicyDBDao.createPolicy - Incoming Config policy had a configurationData "
1799                                 + "body, but it could not be found in the DB for update: policyName = " + policyName);
1800                         throw new IllegalArgumentException(msg);
1801                     }
1802
1803                 } else {
1804                     newConfigurationDataEntity = null;
1805                 }
1806                 if (!update) {
1807                     em.persist(newPolicyEntity);
1808                 }
1809
1810                 policyId = newPolicyEntity.getPolicyId();
1811
1812                 if (!stringEquals(newPolicyEntity.getPolicyName(), policyName)) {
1813                     newPolicyEntity.setPolicyName(policyName);
1814                 }
1815                 if (!stringEquals(newPolicyEntity.getCreatedBy(), username)) {
1816                     newPolicyEntity.setCreatedBy(username);
1817                 }
1818                 if (!stringEquals(newPolicyEntity.getDescription(), policy.getPolicyDescription())) {
1819                     newPolicyEntity.setDescription(policy.getPolicyDescription());
1820                 }
1821                 if (!stringEquals(newPolicyEntity.getModifiedBy(), username)) {
1822                     newPolicyEntity.setModifiedBy(username);
1823                 }
1824                 if (!stringEquals(newPolicyEntity.getPolicyData(), policyDataString)) {
1825                     newPolicyEntity.setPolicyData(policyDataString);
1826                 }
1827                 if (!stringEquals(newPolicyEntity.getScope(), policyScope)) {
1828                     newPolicyEntity.setScope(policyScope);
1829                 }
1830                 if (newPolicyEntity.isDeleted() == true) {
1831                     newPolicyEntity.setDeleted(false);
1832                 }
1833                 newPolicyEntity.setConfigurationData(newConfigurationDataEntity);
1834                 newPolicyEntity.setActionBodyEntity(newActionBodyEntity);
1835
1836                 em.flush();
1837                 this.policyId = newPolicyEntity.getPolicyId();
1838             }
1839         }
1840
1841         @SuppressWarnings("unused")
1842         public PolicyEntity getPolicy(int policyID) {
1843             return getPolicy(policyID, null, null);
1844         }
1845
1846         public PolicyEntity getPolicy(String policyName, String scope) {
1847             return getPolicy(-1, policyName, scope);
1848         }
1849
1850         private PolicyEntity getPolicy(int policyID, String policyName, String scope) {
1851             logger.debug("getPolicy(int policyId, String policyName) as getPolicy(" + policyID + "," + policyName
1852                     + ") called");
1853             if (policyID < 0 && isNullOrEmpty(policyName, scope)) {
1854                 throw new IllegalArgumentException(
1855                         "policyID must be at least 0 or policyName must be not null or blank");
1856             }
1857
1858             synchronized (emLock) {
1859                 checkBeforeOperationRun(true);
1860                 // check if group exists
1861                 String policyId;
1862                 Query policyQuery;
1863                 if (!isNullOrEmpty(policyName, scope)) {
1864                     policyId = policyName;
1865                     policyQuery =
1866                             em.createQuery("SELECT p FROM PolicyEntity p WHERE p.policyName=:name AND p.scope=:scope");
1867                     policyQuery.setParameter("name", policyId);
1868                     policyQuery.setParameter("scope", scope);
1869                 } else {
1870                     policyId = String.valueOf(policyID);
1871                     policyQuery = em.createNamedQuery("PolicyEntity.FindById");
1872                     policyQuery.setParameter("id", policyId);
1873                 }
1874                 List<?> policyQueryList;
1875                 try {
1876                     policyQueryList = policyQuery.getResultList();
1877                 } catch (Exception e) {
1878                     PolicyLogger.error(MessageCodes.EXCEPTION_ERROR, e, policyDBDaoVar,
1879                             "Caught Exception trying to get policy with policyQuery.getResultList()");
1880                     throw new PersistenceException("Query failed trying to get policy " + policyId);
1881                 }
1882                 if (policyQueryList.isEmpty()) {
1883                     PolicyLogger.error("Policy does not exist with id " + policyId);
1884                     throw new PersistenceException("Group policy is being added to does not exist with id " + policyId);
1885                 } else if (policyQueryList.size() > 1) {
1886                     PolicyLogger.error(duplicatePolicyId + policyId + foundInDB);
1887                     throw new PersistenceException(duplicatePolicyId + policyId + foundInDB);
1888                 }
1889                 return (PolicyEntity) policyQueryList.get(0);
1890             }
1891         }
1892
1893         @Override
1894         public GroupEntity getGroup(long groupKey) {
1895             logger.debug("getGroup(int groupKey) as getGroup(" + groupKey + ") called");
1896             if (groupKey < 0) {
1897                 throw new IllegalArgumentException("groupKey must be at least 0");
1898             }
1899             synchronized (emLock) {
1900                 checkBeforeOperationRun(true);
1901                 // check if group exists
1902                 Query groupQuery = em.createQuery("SELECT g FROM GroupEntity g WHERE g.groupKey=:groupKey");
1903                 groupQuery.setParameter("groupKey", groupKey);
1904                 List<?> groupQueryList;
1905                 try {
1906                     groupQueryList = groupQuery.getResultList();
1907                 } catch (Exception e) {
1908                     PolicyLogger.error(MessageCodes.EXCEPTION_ERROR, e, policyDBDaoVar,
1909                             "Caught Exception trying to get group with groupQuery.getResultList()");
1910                     throw new PersistenceException(queryFailedToGetGroup + groupKey);
1911                 }
1912                 if (groupQueryList.isEmpty()) {
1913                     PolicyLogger.error("Group does not exist with groupKey " + groupKey);
1914                     throw new PersistenceException("Group does not exist with groupKey " + groupKey);
1915                 } else if (groupQueryList.size() > 1) {
1916                     PolicyLogger.error("Somehow, more than one group with the groupKey " + groupKey + foundInDB);
1917                     throw new PersistenceException(
1918                             "Somehow, more than one group with the groupKey " + groupKey + foundInDB);
1919                 }
1920                 return (GroupEntity) groupQueryList.get(0);
1921             }
1922         }
1923
1924         @Override
1925         public GroupEntity getGroup(String groupId) {
1926             logger.debug("getGroup(String groupId) as getGroup(" + groupId + ") called");
1927             if (isNullOrEmpty(groupId)) {
1928                 throw new IllegalArgumentException("groupId must not be null or empty");
1929             }
1930             synchronized (emLock) {
1931                 checkBeforeOperationRun(true);
1932                 // check if group exists
1933                 Query groupQuery = em.createQuery("SELECT g FROM GroupEntity g WHERE g.groupId=:groupId");
1934                 groupQuery.setParameter(groupIdVar, groupId);
1935                 List<?> groupQueryList;
1936                 try {
1937                     groupQueryList = groupQuery.getResultList();
1938                 } catch (Exception e) {
1939                     PolicyLogger.error(MessageCodes.EXCEPTION_ERROR, e, policyDBDaoVar,
1940                             "Caught Exception trying to get group with groupQuery.getResultList()");
1941                     throw new PersistenceException(queryFailedToGetGroup + groupId);
1942                 }
1943                 if (groupQueryList.isEmpty()) {
1944                     PolicyLogger.error("Group does not exist with id " + groupId);
1945                     throw new PersistenceException("Group does not exist with id " + groupId);
1946                 } else if (groupQueryList.size() > 1) {
1947                     PolicyLogger.error(duplicateGroupId + groupId + foundInDB);
1948                     throw new PersistenceException(duplicateGroupId + groupId + foundInDB);
1949                 }
1950                 return (GroupEntity) groupQueryList.get(0);
1951             }
1952         }
1953
1954         @Override
1955         public List<?> getPdpsInGroup(long groupKey) {
1956             logger.debug("getPdpsInGroup(int groupKey) as getPdpsInGroup(" + groupKey + ") called");
1957             if (groupKey < 0) {
1958                 throw new IllegalArgumentException("groupId must not be < 0");
1959             }
1960             synchronized (emLock) {
1961                 checkBeforeOperationRun(true);
1962                 Query pdpsQuery = em.createQuery("SELECT p FROM PdpEntity p WHERE p.groupEntity=:group");
1963                 pdpsQuery.setParameter("group", getGroup(groupKey));
1964                 return pdpsQuery.getResultList();
1965             }
1966         }
1967
1968         @Override
1969         public PdpEntity getPdp(long pdpKey) {
1970             logger.debug("getPdp(int pdpKey) as getPdp(" + pdpKey + ") called");
1971             if (pdpKey < 0) {
1972                 throw new IllegalArgumentException("pdpKey must be at least 0");
1973             }
1974             synchronized (emLock) {
1975                 checkBeforeOperationRun(true);
1976                 // check if group exists
1977                 Query pdpQuery = em.createQuery("SELECT p FROM PdpEntity p WHERE p.pdpKey=:pdpKey");
1978                 pdpQuery.setParameter("pdpKey", pdpKey);
1979                 List<?> pdpQueryList;
1980                 try {
1981                     pdpQueryList = pdpQuery.getResultList();
1982                 } catch (Exception e) {
1983                     PolicyLogger.error(MessageCodes.EXCEPTION_ERROR, e, policyDBDaoVar,
1984                             "Caught Exception trying to get pdp with pdpQuery.getResultList()");
1985                     throw new PersistenceException("Query failed trying to get pdp " + pdpKey);
1986                 }
1987                 if (pdpQueryList.isEmpty()) {
1988                     PolicyLogger.error("Pdp does not exist with pdpKey " + pdpKey);
1989                     throw new PersistenceException("Pdp does not exist with pdpKey " + pdpKey);
1990                 } else if (pdpQueryList.size() > 1) {
1991                     PolicyLogger.error("Somehow, more than one pdp with the pdpKey " + pdpKey + foundInDB);
1992                     throw new PersistenceException("Somehow, more than one pdp with the pdpKey " + pdpKey + foundInDB);
1993                 }
1994                 return (PdpEntity) pdpQueryList.get(0);
1995             }
1996         }
1997
1998         @Override
1999         public boolean isTransactionOpen() {
2000             logger.debug("isTransactionOpen() as isTransactionOpen() called");
2001             synchronized (emLock) {
2002                 return em.isOpen() && em.getTransaction().isActive();
2003             }
2004         }
2005
2006         private String processConfigPath(String inputConfigPath) {
2007             String configPath = inputConfigPath;
2008             String webappsPath = XACMLProperties.getProperty(XACMLRestProperties.PROP_PAP_WEBAPPS);
2009             if (webappsPath == null) {
2010                 logger.error("Webapps property does not exist");
2011                 throw new IllegalArgumentException("Webapps property does not exist");
2012             }
2013             configPath = configPath.replace("$URL", webappsPath);
2014             // make sure the correct slashes are in
2015             try {
2016                 configPath = Paths.get(configPath).toString();
2017             } catch (InvalidPathException e) {
2018                 logger.error("Invalid config path: " + configPath, e);
2019                 throw new IllegalArgumentException("Invalid config path: " + configPath);
2020             }
2021             return configPath;
2022         }
2023
2024         private String readConfigFile(String configPath) {
2025             String configDataString = null;
2026             try (InputStream configContentStream = new FileInputStream(configPath);) {
2027                 configDataString = IOUtils.toString(configContentStream);
2028             } catch (FileNotFoundException e) {
2029                 logger.error("Caught FileNotFoundException on new FileInputStream(" + configPath + ")", e);
2030                 throw new IllegalArgumentException("The config file path does not exist");
2031             } catch (IOException e2) {
2032                 logger.error("Caught IOException on newIOUtils.toString(configContentStream)", e2);
2033                 throw new IllegalArgumentException("The config file path cannot be read");
2034             }
2035             if (configDataString == null) {
2036                 throw new IllegalArgumentException("The config file path cannot be read");
2037             }
2038             return configDataString;
2039         }
2040
2041         @Override
2042         public void createPolicy(Policy policy, String username) {
2043
2044             try {
2045                 logger.debug("createPolicy(PolicyRestAdapter policy, String username) as createPolicy(" + policy + ","
2046                         + username + ") called");
2047                 String policyScope = policy.policyAdapter.getDomainDir().replace(File.separator, ".");
2048                 // Does not need to be XACMLPolicyWriterWithPapNotify since it is already in the PAP
2049                 // and this transaction is intercepted up stream.
2050
2051                 String policyDataString = getPolicyDataString(policy);
2052                 if (isJunit) {
2053                     // Using parentPath object to set policy data.
2054                     policyDataString = policy.policyAdapter.getParentPath();
2055                 }
2056                 String configPath = "";
2057                 if (policy.policyAdapter.getPolicyType().equalsIgnoreCase(config)) {
2058                     configPath = evaluateXPath(
2059                             "/Policy/Rule/AdviceExpressions/AdviceExpression[contains(@AdviceId,'ID')"
2060                                     + "]/AttributeAssignmentExpression[@AttributeId='URLID']/AttributeValue/text()",
2061                             policyDataString);
2062                 } else if (policy.policyAdapter.getPolicyType().equalsIgnoreCase(action)) {
2063                     configPath = evaluateXPath(
2064                             "/Policy/Rule/ObligationExpressions/ObligationExpression[contains(@ObligationId, "
2065                                     + policy.policyAdapter.getActionAttribute()
2066                                     + ")]/AttributeAssignmentExpression[@AttributeId='body']/AttributeValue/text()",
2067                             policyDataString);
2068                 }
2069
2070                 String prefix = null;
2071                 if (policy.policyAdapter.getPolicyType().equalsIgnoreCase(config)) {
2072
2073                     prefix = configPath.substring(
2074                             configPath.indexOf(policyScope + ".") + policyScope.concat(".").length(),
2075                             configPath.lastIndexOf(policy.policyAdapter.getPolicyName()));
2076                     if (isNullOrEmpty(policy.policyAdapter.getConfigBodyData())) {
2077                         policy.policyAdapter.setConfigBodyData(getConfigData(configPath));
2078                     }
2079                 } else if (action.equalsIgnoreCase(policy.policyAdapter.getPolicyType())) {
2080                     prefix = "Action_";
2081                 } else if ("Decision".equalsIgnoreCase(policy.policyAdapter.getPolicyType())) {
2082                     prefix = "Decision_";
2083                 }
2084
2085                 if (!(policy.policyAdapter.getData() instanceof PolicyType)
2086                         && !(policy.policyAdapter.getData() instanceof PolicySetType)) {
2087                     PolicyLogger.error("The data field is not an instance of PolicyType or PolicySetType");
2088                     throw new IllegalArgumentException(
2089                             "The data field is not an instance of PolicyType or PolicySetType");
2090                 }
2091                 String finalName = policyScope + "." + prefix + policy.policyAdapter.getPolicyName() + "."
2092                         + policy.policyAdapter.getHighestVersion() + ".xml";
2093                 if (policy.policyAdapter.getConfigType() == null || "".equals(policy.policyAdapter.getConfigType())) {
2094                     // get the config file extension
2095                     String ext = "";
2096                     if (configPath != null && !"".equalsIgnoreCase(configPath)) {
2097                         ext = configPath.substring(configPath.lastIndexOf('.'), configPath.length());;
2098                     }
2099
2100                     if (ext.contains("txt")) {
2101                         policy.policyAdapter.setConfigType(OTHER_CONFIG);
2102                     } else if (ext.contains("json")) {
2103                         policy.policyAdapter.setConfigType(JSON_CONFIG);
2104                     } else if (ext.contains("xml")) {
2105                         policy.policyAdapter.setConfigType(XML_CONFIG);
2106                     } else if (ext.contains("properties")) {
2107                         policy.policyAdapter.setConfigType(PROPERTIES_CONFIG);
2108                     } else {
2109                         if (policy.policyAdapter.getPolicyType().equalsIgnoreCase(action)) {
2110                             policy.policyAdapter.setConfigType(JSON_CONFIG);
2111                         }
2112                     }
2113                 }
2114                 createPolicy(policy.policyAdapter, username, policyScope, finalName, policyDataString);
2115             } catch (Exception e) {
2116                 logger.error("Could not create policy for " + policy, e);
2117                 throw e;
2118             }
2119         }
2120
2121         private String getConfigData(String configPath) {
2122             String configData = "";
2123             try {
2124                 configData = getConfigPath(configPath);
2125             } catch (Exception e) {
2126                 logger.error("Could not read config body data for " + configPath, e);
2127             }
2128             return configData;
2129         }
2130
2131         private String getConfigPath(String configPath) {
2132             try {
2133                 String newConfigPath = processConfigPath(configPath);
2134                 return readConfigFile(newConfigPath);
2135             } catch (IllegalArgumentException e2) {
2136                 logger.error("Could not process config path: " + configPath, e2);
2137             }
2138             return "";
2139         }
2140
2141
2142         /**
2143          * @param policy input policy Object.
2144          * @return read the stream and return policy xml data.
2145          */
2146         private String getPolicyDataString(Policy policy) {
2147             try (InputStream policyXmlStream =
2148                     XACMLPolicyWriter.getXmlAsInputStream(policy.getCorrectPolicyDataObject())) {
2149                 return IOUtils.toString(policyXmlStream);
2150             } catch (IOException e) {
2151                 PolicyLogger.error(MessageCodes.EXCEPTION_ERROR, e, policyDBDaoVar,
2152                         "Caught IOException on reading Policy Data.");
2153                 throw new IllegalArgumentException("Cannot parse the policy xml from the PolicyRestAdapter.");
2154             }
2155         }
2156
2157         @Override
2158         public void close() {
2159             synchronized (emLock) {
2160                 if (em.isOpen()) {
2161                     if (em.getTransaction().isActive()) {
2162                         em.getTransaction().rollback();
2163                     }
2164                     em.close();
2165                 }
2166                 if (transactionTimer != null) {
2167                     transactionTimer.interrupt();
2168                 }
2169             }
2170         }
2171
2172         @Override
2173         public void createGroup(String groupId, String groupName, String inputGroupDescription, String username) {
2174             String groupDescription = inputGroupDescription;
2175             logger.debug("deletePolicy(String policyToDeletes) as createGroup(" + groupId + ", " + groupName + ", "
2176                     + groupDescription + ") called");
2177             if (isNullOrEmpty(groupId, groupName, username)) {
2178                 throw new IllegalArgumentException("groupId, groupName, and username must not be null or empty");
2179             }
2180             if (groupDescription == null) {
2181                 groupDescription = "";
2182             }
2183
2184             synchronized (emLock) {
2185                 checkBeforeOperationRun();
2186                 Query checkGroupQuery = em.createQuery(groupEntitySelectQuery);
2187                 checkGroupQuery.setParameter(groupIdVar, groupId);
2188                 checkGroupQuery.setParameter(deletedVar, false);
2189                 List<?> checkGroupQueryList;
2190                 try {
2191                     checkGroupQueryList = checkGroupQuery.getResultList();
2192                 } catch (Exception e) {
2193                     PolicyLogger.error(MessageCodes.EXCEPTION_ERROR, e, policyDBDaoVar,
2194                             "Caught Exception on checkGroupQuery.getResultList()");
2195                     throw new PersistenceException(queryFailedToCheckExisting);
2196                 }
2197                 if (!checkGroupQueryList.isEmpty()) {
2198                     PolicyLogger.error("The group being added already exists with id " + groupId);
2199                     throw new PersistenceException("The group being added already exists with id " + groupId);
2200                 }
2201                 GroupEntity newGroup = new GroupEntity();
2202                 em.persist(newGroup);
2203                 newGroup.setCreatedBy(username);
2204                 newGroup.setModifiedBy(username);
2205                 newGroup.setGroupName(groupName);
2206                 newGroup.setGroupId(groupId);
2207                 newGroup.setDescription(groupDescription);
2208
2209                 em.flush();
2210                 this.groupId = newGroup.getGroupKey();
2211             }
2212         }
2213
2214         @Override
2215         public void updateGroup(OnapPDPGroup group, String username) {
2216             logger.info(
2217                     "PolicyDBDao: updateGroup(PDPGroup group) as updateGroup(" + group + "," + username + ") called");
2218             if (group == null) {
2219                 throw new IllegalArgumentException("PDPGroup group must not be null");
2220             }
2221             if (isNullOrEmpty(group.getId(), username)) {
2222                 throw new IllegalArgumentException("group.getId() and username must not be null or empty");
2223             }
2224
2225             synchronized (emLock) {
2226                 checkBeforeOperationRun();
2227                 Query getGroupQuery = em.createQuery(groupEntitySelectQuery);
2228                 getGroupQuery.setParameter(groupIdVar, group.getId());
2229                 getGroupQuery.setParameter(deletedVar, false);
2230                 List<?> getGroupQueryList;
2231                 try {
2232                     getGroupQueryList = getGroupQuery.getResultList();
2233                 } catch (Exception e) {
2234                     PolicyLogger.error(MessageCodes.EXCEPTION_ERROR, e, policyDBDaoVar,
2235                             "Caught Exception on getGroupQuery.getResultList()");
2236                     throw new PersistenceException(queryFailedToGetGroup + group.getId() + " for editing");
2237                 }
2238                 if (getGroupQueryList.isEmpty()) {
2239                     PolicyLogger.error("The group cannot be found to update with id " + group.getId());
2240                     throw new PersistenceException("The group cannot be found to update with id " + group.getId());
2241                 } else if (getGroupQueryList.size() > 1) {
2242                     PolicyLogger.error(duplicateGroupId + group.getId() + deletedStatusFound);
2243                     throw new PersistenceException(duplicateGroupId + group.getId() + deletedStatusFound);
2244                 }
2245                 GroupEntity groupToUpdateInDB = (GroupEntity) getGroupQueryList.get(0);
2246                 if (!stringEquals(groupToUpdateInDB.getModifiedBy(), username)) {
2247                     groupToUpdateInDB.setModifiedBy(username);
2248                 }
2249                 if (group.getDescription() != null
2250                         && !stringEquals(group.getDescription(), groupToUpdateInDB.getDescription())) {
2251                     groupToUpdateInDB.setDescription(group.getDescription());
2252                 }
2253                 // let's find out what policies have been deleted
2254                 StdPDPGroup oldGroup = null;
2255                 try {
2256                     oldGroup = (StdPDPGroup) papEngine.getGroup(group.getId());
2257                 } catch (PAPException e1) {
2258                     PolicyLogger.error(MessageCodes.EXCEPTION_ERROR, e1, policyDBDaoVar,
2259                             "We cannot get the group from the papEngine to delete policies");
2260                 }
2261                 if (oldGroup == null) {
2262                     PolicyLogger.error("We cannot get the group from the papEngine to delete policies");
2263                 } else {
2264                     Set<String> newPolicySet = new HashSet<>(group.getPolicies().size());
2265                     // a multiple of n runtime is faster than n^2, so I am using a hashset to do the comparison
2266                     for (PDPPolicy pol : group.getPolicies()) {
2267                         newPolicySet.add(pol.getId());
2268                     }
2269                     for (PDPPolicy pol : oldGroup.getPolicies()) {
2270                         // should be fast since getPolicies uses a HashSet in StdPDPGroup
2271                         if (!newPolicySet.contains(pol.getId())) {
2272                             String[] scopeAndName = getNameScopeAndVersionFromPdpPolicy(pol.getId());
2273                             deletePolicyInScope(username, groupToUpdateInDB, pol, scopeAndName);
2274                         }
2275                     }
2276                 }
2277
2278                 if (group.getName() != null && !stringEquals(group.getName(), groupToUpdateInDB.getgroupName())) {
2279                     // we need to check if the new id exists in the database
2280                     String newGroupId = createNewPDPGroupId(group.getName());
2281                     Query checkGroupQuery = em.createQuery(groupEntitySelectQuery);
2282                     checkGroupQuery.setParameter(groupIdVar, newGroupId);
2283                     checkGroupQuery.setParameter(deletedVar, false);
2284                     List<?> checkGroupQueryList;
2285                     try {
2286                         checkGroupQueryList = checkGroupQuery.getResultList();
2287                     } catch (Exception e) {
2288                         PolicyLogger.error(MessageCodes.EXCEPTION_ERROR, e, policyDBDaoVar,
2289                                 "Caught Exception on checkGroupQuery.getResultList()");
2290                         throw new PersistenceException(queryFailedToCheckExisting);
2291                     }
2292                     if (!checkGroupQueryList.isEmpty()) {
2293                         PolicyLogger.error("The new group name already exists, group id " + newGroupId);
2294                         throw new PersistenceException("The new group name already exists, group id " + newGroupId);
2295                     }
2296                     groupToUpdateInDB.setGroupId(newGroupId);
2297                     groupToUpdateInDB.setGroupName(group.getName());
2298                     this.newGroupId = group.getId();
2299                 }
2300                 em.flush();
2301                 this.groupId = groupToUpdateInDB.getGroupKey();
2302             }
2303         }
2304
2305         private void deletePolicyInScope(String username, GroupEntity groupToUpdateInDB, PDPPolicy pol,
2306                 String[] scopeAndName) {
2307             PolicyEntity policyToDelete;
2308             if (scopeAndName == null) {
2309                 return;
2310             }
2311             try {
2312                 policyToDelete = getPolicy(scopeAndName[0], scopeAndName[1]);
2313                 if ("XACMLPapServlet.doDelete".equals(username)) {
2314                     Iterator<PolicyEntity> dbPolicyIt = groupToUpdateInDB.getPolicies().iterator();
2315                     String policyName = getPolicyNameAndVersionFromPolicyFileName(policyToDelete.getPolicyName())[0];
2316
2317                     logger.info("PolicyDBDao: delete policy from GroupEntity");
2318                     deletePolicyFromGroupEntity(groupToUpdateInDB, policyToDelete, dbPolicyIt, policyName);
2319                 }
2320             } catch (Exception e) {
2321                 PolicyLogger.error(MessageCodes.EXCEPTION_ERROR, e, policyDBDaoVar,
2322                         "Could not get policy to remove: " + pol.getId());
2323                 throw new PersistenceException("Could not get policy to remove: " + pol.getId());
2324             }
2325         }
2326
2327         private void deletePolicyFromGroupEntity(GroupEntity groupToUpdateInDB, PolicyEntity policyToDelete,
2328                 Iterator<PolicyEntity> dbPolicyIt, String policyName) {
2329             try {
2330                 while (dbPolicyIt.hasNext()) {
2331                     PolicyEntity dbpolicy = dbPolicyIt.next();
2332                     if (policyToDelete.getScope().equals(dbpolicy.getScope())
2333                             && getPolicyNameAndVersionFromPolicyFileName(dbpolicy.getPolicyName())[0]
2334                                     .equals(policyName)) {
2335                         dbPolicyIt.remove();
2336
2337                         logger.info("PolicyDBDao: deleting policy from the existing group:\n " + "policyName is "
2338                                 + policyToDelete.getScope() + "." + policyToDelete.getPolicyName() + "\n" + "group is "
2339                                 + groupToUpdateInDB.getGroupId());
2340                     }
2341                 }
2342             } catch (Exception e) {
2343                 logger.debug(e);
2344                 PolicyLogger.error("Could not delete policy with name: " + policyToDelete.getScope() + "."
2345                         + policyToDelete.getPolicyName() + "\n ID: " + policyToDelete.getPolicyId());
2346             }
2347         }
2348
2349         @Override
2350         public void addPdpToGroup(String pdpID, String groupID, String pdpName, String pdpDescription, int pdpJmxPort,
2351                 String username) {
2352             logger.debug("addPdpToGroup(String pdpID, String groupID, String pdpName, String pdpDescription, int "
2353                     + "pdpJmxPort, String username) as addPdpToGroup(" + pdpID + ", " + groupID + ", " + pdpName + ", "
2354                     + pdpDescription + ", " + pdpJmxPort + ", " + username + ") called");
2355             if (isNullOrEmpty(pdpID, groupID, pdpName, username)) {
2356                 throw new IllegalArgumentException("pdpID, groupID, pdpName, and username must not be null or empty");
2357             }
2358             synchronized (emLock) {
2359                 checkBeforeOperationRun();
2360                 Query checkGroupQuery = em.createQuery(groupEntitySelectQuery);
2361                 checkGroupQuery.setParameter(groupIdVar, groupID);
2362                 checkGroupQuery.setParameter(deletedVar, false);
2363                 List<?> checkGroupQueryList;
2364                 try {
2365                     checkGroupQueryList = checkGroupQuery.getResultList();
2366                 } catch (Exception e) {
2367                     PolicyLogger.error(MessageCodes.EXCEPTION_ERROR, e, policyDBDaoVar,
2368                             "Caught Exception trying to check for existing group on checkGroupQuery.getResultList()");
2369                     throw new PersistenceException(queryFailedToCheckExisting);
2370                 }
2371                 if (checkGroupQueryList.size() != 1) {
2372                     PolicyLogger.error("The group does not exist");
2373                     throw new PersistenceException("The group does not exist");
2374                 }
2375                 Query checkDuplicateQuery = em.createQuery(pdpEntitySelectQuery);
2376                 checkDuplicateQuery.setParameter(pdpIdVariable, pdpID);
2377                 checkDuplicateQuery.setParameter(deletedVar, false);
2378                 List<?> checkDuplicateList;
2379                 try {
2380                     checkDuplicateList = checkDuplicateQuery.getResultList();
2381                 } catch (Exception e) {
2382                     PolicyLogger.error(MessageCodes.EXCEPTION_ERROR, e, policyDBDaoVar,
2383                             "Caught Exception trying to check for duplicate PDP " + pdpID
2384                                     + " on checkDuplicateQuery.getResultList()");
2385                     throw new PersistenceException("Query failed trying to check for duplicate PDP " + pdpID);
2386                 }
2387                 PdpEntity newPdp;
2388                 if (!checkDuplicateList.isEmpty()) {
2389                     logger.warn("PDP already exists with id " + pdpID);
2390                     newPdp = (PdpEntity) checkDuplicateList.get(0);
2391                 } else {
2392                     newPdp = new PdpEntity();
2393                     em.persist(newPdp);
2394                 }
2395
2396                 newPdp.setCreatedBy(username);
2397                 newPdp.setDeleted(false);
2398                 newPdp.setDescription(pdpDescription);
2399                 newPdp.setGroup((GroupEntity) checkGroupQueryList.get(0));
2400                 newPdp.setJmxPort(pdpJmxPort);
2401                 newPdp.setModifiedBy(username);
2402                 newPdp.setPdpId(pdpID);
2403                 newPdp.setPdpName(pdpName);
2404
2405                 em.flush();
2406                 this.pdpId = newPdp.getPdpKey();
2407             }
2408         }
2409
2410
2411         @Override
2412         public void updatePdp(OnapPDP pdp, String username) {
2413             logger.debug("updatePdp(PDP pdp, String username) as updatePdp(" + pdp + "," + username + ") called");
2414             if (pdp == null) {
2415                 throw new IllegalArgumentException("PDP pdp must not be null");
2416             }
2417             if (isNullOrEmpty(pdp.getId(), username)) {
2418                 throw new IllegalArgumentException("pdp.getId() and username must not be null or empty");
2419             }
2420
2421             synchronized (emLock) {
2422                 checkBeforeOperationRun();
2423                 Query getPdpQuery = em.createQuery(pdpEntitySelectQuery);
2424                 getPdpQuery.setParameter(pdpIdVariable, pdp.getId());
2425                 getPdpQuery.setParameter(deletedVar, false);
2426                 List<?> getPdpQueryList;
2427                 try {
2428                     getPdpQueryList = getPdpQuery.getResultList();
2429                 } catch (Exception e) {
2430                     PolicyLogger.error(MessageCodes.EXCEPTION_ERROR, e, policyDBDaoVar,
2431                             "Caught Exception on getPdpQuery.getResultList()");
2432                     throw new PersistenceException("Query failed trying to get PDP " + pdp.getId());
2433                 }
2434                 if (getPdpQueryList.isEmpty()) {
2435                     PolicyLogger.error("The pdp cannot be found to update with id " + pdp.getId());
2436                     throw new PersistenceException("The pdp cannot be found to update with id " + pdp.getId());
2437                 } else if (getPdpQueryList.size() > 1) {
2438                     PolicyLogger.error(moreThanOnePDP + pdp.getId() + deletedStatusFound);
2439                     throw new PersistenceException(moreThanOnePDP + pdp.getId() + deletedStatusFound);
2440                 }
2441                 PdpEntity pdpToUpdate = (PdpEntity) getPdpQueryList.get(0);
2442                 if (!stringEquals(pdpToUpdate.getModifiedBy(), username)) {
2443                     pdpToUpdate.setModifiedBy(username);
2444                 }
2445                 if (pdp.getDescription() != null && !stringEquals(pdp.getDescription(), pdpToUpdate.getDescription())) {
2446                     pdpToUpdate.setDescription(pdp.getDescription());
2447                 }
2448                 if (pdp.getName() != null && !stringEquals(pdp.getName(), pdpToUpdate.getPdpName())) {
2449                     pdpToUpdate.setPdpName(pdp.getName());
2450                 }
2451                 if (pdp.getJmxPort() != null && !pdp.getJmxPort().equals(pdpToUpdate.getJmxPort())) {
2452                     pdpToUpdate.setJmxPort(pdp.getJmxPort());
2453                 }
2454
2455                 em.flush();
2456                 this.pdpId = pdpToUpdate.getPdpKey();
2457             }
2458         }
2459
2460         @Override
2461         public void movePdp(OnapPDP pdp, OnapPDPGroup group, String username) {
2462             logger.debug("movePdp(PDP pdp, PDPGroup group, String username) as movePdp(" + pdp + "," + group + ","
2463                     + username + ") called");
2464             if (pdp == null || group == null) {
2465                 throw new IllegalArgumentException("PDP pdp and PDPGroup group must not be null");
2466             }
2467             if (isNullOrEmpty(username, pdp.getId(), group.getId())) {
2468                 throw new IllegalArgumentException(
2469                         "pdp.getId(), group.getId(), and username must not be null or empty");
2470             }
2471
2472             synchronized (emLock) {
2473                 checkBeforeOperationRun();
2474                 // check if pdp exists
2475                 Query getPdpQuery = em.createQuery(pdpEntitySelectQuery);
2476                 getPdpQuery.setParameter(pdpIdVariable, pdp.getId());
2477                 getPdpQuery.setParameter(deletedVar, false);
2478                 List<?> getPdpQueryList;
2479                 try {
2480                     getPdpQueryList = getPdpQuery.getResultList();
2481                 } catch (Exception e) {
2482                     PolicyLogger.error(MessageCodes.EXCEPTION_ERROR, e, policyDBDaoVar,
2483                             "Caught Exception on getPdpQuery.getResultList()");
2484                     throw new PersistenceException("Query failed trying to get pdp to move with id " + pdp.getId());
2485                 }
2486                 if (getPdpQueryList.isEmpty()) {
2487                     PolicyLogger.error("The pdp cannot be found to move with id " + pdp.getId());
2488                     throw new PersistenceException("The pdp cannot be found to move with id " + pdp.getId());
2489                 } else if (getPdpQueryList.size() > 1) {
2490                     PolicyLogger.error(moreThanOnePDP + pdp.getId() + deletedStatusFound);
2491                     throw new PersistenceException(moreThanOnePDP + pdp.getId() + deletedStatusFound);
2492                 }
2493
2494                 // check if new group exists
2495                 Query checkGroupQuery = em.createQuery(groupEntitySelectQuery);
2496                 checkGroupQuery.setParameter(groupIdVar, group.getId());
2497                 checkGroupQuery.setParameter(deletedVar, false);
2498                 List<?> checkGroupQueryList;
2499                 try {
2500                     checkGroupQueryList = checkGroupQuery.getResultList();
2501                 } catch (Exception e) {
2502                     PolicyLogger.error(MessageCodes.EXCEPTION_ERROR, e, policyDBDaoVar,
2503                             "Caught Exception trying to get group on checkGroupQuery.getResultList()");
2504                     throw new PersistenceException("Query failed trying to get new group " + group.getId());
2505                 }
2506                 if (checkGroupQueryList.size() != 1) {
2507                     PolicyLogger.error("The group " + group.getId() + " does not exist");
2508                     throw new PersistenceException("The group " + group.getId() + " does not exist");
2509                 }
2510                 GroupEntity groupToMoveInto = (GroupEntity) checkGroupQueryList.get(0);
2511                 PdpEntity pdpToUpdate = (PdpEntity) getPdpQueryList.get(0);
2512                 pdpToUpdate.setGroup(groupToMoveInto);
2513                 if (!stringEquals(pdpToUpdate.getModifiedBy(), username)) {
2514                     pdpToUpdate.setModifiedBy(username);
2515                 }
2516
2517                 em.flush();
2518                 this.pdpId = pdpToUpdate.getPdpKey();
2519             }
2520         }
2521
2522         @Override
2523         public void changeDefaultGroup(OnapPDPGroup group, String username) {
2524             logger.debug("changeDefaultGroup(PDPGroup group, String username) as changeDefaultGroup(" + group + ","
2525                     + username + ") called");
2526             if (group == null) {
2527                 throw new IllegalArgumentException("PDPGroup group must not be null");
2528             }
2529             if (isNullOrEmpty(group.getId(), username)) {
2530                 throw new IllegalArgumentException("group.getId() and username must not be null or empty");
2531             }
2532
2533             synchronized (emLock) {
2534                 checkBeforeOperationRun();
2535                 Query getGroupQuery = em.createQuery(groupEntitySelectQuery);
2536                 getGroupQuery.setParameter(groupIdVar, group.getId());
2537                 getGroupQuery.setParameter(deletedVar, false);
2538                 List<?> getGroupQueryList;
2539                 try {
2540                     getGroupQueryList = getGroupQuery.getResultList();
2541                 } catch (Exception e) {
2542                     PolicyLogger.error(MessageCodes.EXCEPTION_ERROR, e, policyDBDaoVar,
2543                             "Caught Exception on getGroupQuery.getResultList()");
2544                     throw new PersistenceException(queryFailedToGetGroup + group.getId());
2545                 }
2546                 if (getGroupQueryList.isEmpty()) {
2547                     PolicyLogger.error("The group cannot be found to set default with id " + group.getId());
2548                     throw new PersistenceException("The group cannot be found to set default with id " + group.getId());
2549                 } else if (getGroupQueryList.size() > 1) {
2550                     PolicyLogger.error(duplicateGroupId + group.getId() + deletedStatusFound);
2551                     throw new PersistenceException(duplicateGroupId + group.getId() + deletedStatusFound);
2552                 }
2553                 GroupEntity newDefaultGroup = (GroupEntity) getGroupQueryList.get(0);
2554                 newDefaultGroup.setDefaultGroup(true);
2555                 if (!stringEquals(newDefaultGroup.getModifiedBy(), username)) {
2556                     newDefaultGroup.setModifiedBy(username);
2557                 }
2558
2559                 em.flush();
2560                 this.groupId = newDefaultGroup.getGroupKey();
2561                 Query setAllGroupsNotDefault = em.createQuery(
2562                         "UPDATE GroupEntity g SET g.defaultGroup=:defaultGroup WHERE g.deleted=:deleted AND g"
2563                                 + ".groupKey<>:groupKey");
2564                 // not going to set modified by for all groups
2565                 setAllGroupsNotDefault.setParameter("defaultGroup", false);
2566                 setAllGroupsNotDefault.setParameter(deletedVar, false);
2567                 setAllGroupsNotDefault.setParameter("groupKey", newDefaultGroup.getGroupKey());
2568                 try {
2569                     logger.info("set " + setAllGroupsNotDefault.executeUpdate() + " groups as not default");
2570                 } catch (Exception e) {
2571                     PolicyLogger.error(MessageCodes.EXCEPTION_ERROR, e, policyDBDaoVar,
2572                             "Caught Exception on setAllGroupsNotDefault.executeUpdate()");
2573                     throw new PersistenceException("Could not set all other groups default to false");
2574                 }
2575                 em.flush();
2576             }
2577         }
2578
2579
2580         @Override
2581         public void deleteGroup(OnapPDPGroup group, OnapPDPGroup moveToGroup, String username)
2582                 throws PolicyDBException {
2583             logger.debug("deleteGroup(PDPGroup group, PDPGroup moveToGroup, String username) as deleteGroup(" + group
2584                     + ", " + moveToGroup + "," + username + ") called");
2585             if (group == null) {
2586                 throw new IllegalArgumentException("PDPGroup group cannot be null");
2587             }
2588             if (isNullOrEmpty(username, group.getId())) {
2589                 throw new IllegalArgumentException("group.getId() and and username must not be null or empty");
2590             }
2591
2592             if (group.isDefaultGroup()) {
2593                 PolicyLogger
2594                         .error("The default group " + group.getId() + " was attempted to be deleted. It cannot be.");
2595                 throw new PolicyDBException("You cannot delete the default group.");
2596             }
2597             synchronized (emLock) {
2598                 checkBeforeOperationRun();
2599                 Query deleteGroupQuery = em.createQuery(groupEntitySelectQuery);
2600                 deleteGroupQuery.setParameter(groupIdVar, group.getId());
2601                 deleteGroupQuery.setParameter(deletedVar, false);
2602                 List<?> deleteGroupQueryList;
2603                 try {
2604                     deleteGroupQueryList = deleteGroupQuery.getResultList();
2605                 } catch (Exception e) {
2606                     PolicyLogger.error(MessageCodes.EXCEPTION_ERROR, e, policyDBDaoVar,
2607                             "Caught Exception trying to check if group exists deleteGroupQuery.getResultList()");
2608                     throw new PersistenceException("Query failed trying to check if group exists");
2609                 }
2610                 if (deleteGroupQueryList.isEmpty()) {
2611                     logger.warn(groupCannotBeFound + group.getId());
2612                     return;
2613                 } else if (deleteGroupQueryList.size() > 1) {
2614                     PolicyLogger.error(duplicateGroupId + group.getId() + foundInDBNotDeleted);
2615                     throw new PersistenceException(duplicateGroupId + group.getId() + foundInDBNotDeleted);
2616                 }
2617
2618                 Query pdpsInGroupQuery =
2619                         em.createQuery("SELECT p FROM PdpEntity p WHERE p.groupEntity=:group and p.deleted=:deleted");
2620                 pdpsInGroupQuery.setParameter("group", ((GroupEntity) deleteGroupQueryList.get(0)));
2621                 pdpsInGroupQuery.setParameter(deletedVar, false);
2622                 List<?> pdpsInGroupList;
2623                 try {
2624                     pdpsInGroupList = pdpsInGroupQuery.getResultList();
2625                 } catch (Exception e) {
2626                     PolicyLogger.error(MessageCodes.EXCEPTION_ERROR, e, policyDBDaoVar,
2627                             "Caught Exception trying to get PDPs in group on pdpsInGroupQuery.getResultList()");
2628                     throw new PersistenceException("Query failed trying to get PDPs in group");
2629                 }
2630                 if (!pdpsInGroupList.isEmpty()) {
2631                     if (moveToGroup != null) {
2632                         Query checkMoveToGroupQuery = em.createQuery(
2633                                 "SELECT o FROM GroupEntity o WHERE o.groupId=:groupId AND o.deleted=:deleted");
2634                         checkMoveToGroupQuery.setParameter(groupIdVar, moveToGroup.getId());
2635                         checkMoveToGroupQuery.setParameter(deletedVar, false);
2636                         List<?> checkMoveToGroupList;
2637                         try {
2638                             checkMoveToGroupList = checkMoveToGroupQuery.getResultList();
2639                         } catch (Exception e) {
2640                             PolicyLogger.error(MessageCodes.EXCEPTION_ERROR, e, policyDBDaoVar,
2641                                     "Caught Exception trying to check if group exists checkMoveToGroupQuery"
2642                                             + ".getResultList()");
2643                             throw new PersistenceException("Query failed trying to check if group exists");
2644                         }
2645                         if (checkMoveToGroupList.isEmpty()) {
2646                             PolicyLogger.error(groupCannotBeFound + moveToGroup.getId());
2647                             throw new PersistenceException(groupCannotBeFound + moveToGroup.getId());
2648                         } else if (checkMoveToGroupList.size() > 1) {
2649                             PolicyLogger.error(duplicateGroupId + moveToGroup.getId() + foundInDBNotDeleted);
2650                             throw new PersistenceException(
2651                                     duplicateGroupId + moveToGroup.getId() + foundInDBNotDeleted);
2652                         } else {
2653                             GroupEntity newGroup = (GroupEntity) checkMoveToGroupList.get(0);
2654                             for (Object pdpObject : pdpsInGroupList) {
2655                                 PdpEntity pdp = (PdpEntity) pdpObject;
2656                                 pdp.setGroup(newGroup);
2657                                 if (!stringEquals(pdp.getModifiedBy(), username)) {
2658                                     pdp.setModifiedBy(username);
2659                                 }
2660                                 try {
2661                                     em.flush();
2662                                     this.newGroupId = newGroup.getGroupId();
2663                                 } catch (PersistenceException e) {
2664                                     PolicyLogger.error(MessageCodes.EXCEPTION_ERROR, e, policyDBDaoVar,
2665                                             "Caught PersistenceException trying to set pdp group to null on em.flush"
2666                                                     + "()");
2667                                     throw new PersistenceException("Query failed trying to set pdp group to ");
2668                                 }
2669                             }
2670                         }
2671                     } else {
2672                         PolicyLogger.error("Group " + group.getId()
2673                                 + " is trying to be delted with PDPs. No group was provided to move them to");
2674                         throw new PolicyDBException("Group has PDPs. Must provide a group for them to move to");
2675                     }
2676                 }
2677
2678                 // delete group here
2679                 GroupEntity groupToDelete = (GroupEntity) deleteGroupQueryList.get(0);
2680                 groupToDelete.setDeleted(true);
2681                 if (!stringEquals(groupToDelete.getModifiedBy(), username)) {
2682                     groupToDelete.setModifiedBy(username);
2683                 }
2684                 em.flush();
2685                 this.groupId = groupToDelete.getGroupKey();
2686             }
2687         }
2688
2689         @Override
2690         public StdPDPGroup addPolicyToGroup(String groupID, String policyID, String username) throws PolicyDBException {
2691             logger.info("PolicyDBDao: addPolicyToGroup(String groupID, String policyID, String username) as "
2692                     + "addPolicyToGroup(" + groupID + ", " + policyID + "," + username + ") called");
2693             if (isNullOrEmpty(groupID, policyID, username)) {
2694                 throw new IllegalArgumentException("groupID, policyID, and username must not be null or empty");
2695             }
2696             synchronized (emLock) {
2697                 checkBeforeOperationRun();
2698                 // check if group exists
2699                 Query groupQuery = em.createQuery(groupEntitySelectQuery);
2700                 groupQuery.setParameter(groupIdVar, groupID);
2701                 groupQuery.setParameter(deletedVar, false);
2702                 List<?> groupQueryList;
2703                 try {
2704                     groupQueryList = groupQuery.getResultList();
2705                 } catch (Exception e) {
2706                     PolicyLogger.error(MessageCodes.EXCEPTION_ERROR, e, policyDBDaoVar,
2707                             "Caught Exception trying to check if group exists groupQuery.getResultList()");
2708                     throw new PersistenceException("Query failed trying to check if group " + groupID + " exists");
2709                 }
2710                 if (groupQueryList.isEmpty()) {
2711                     PolicyLogger.error("Group policy is being added to does not exist with id " + groupID);
2712                     throw new PersistenceException("Group policy is being added to does not exist with id " + groupID);
2713                 } else if (groupQueryList.size() > 1) {
2714                     PolicyLogger.error(duplicateGroupId + groupID + foundInDBNotDeleted);
2715                     throw new PersistenceException(duplicateGroupId + groupID + foundInDBNotDeleted);
2716                 }
2717
2718                 // we need to convert the form of the policy id that is used groups into the form that is used
2719                 // for the database. (com.Config_mypol.1.xml) to (Config_mypol.xml)
2720                 String[] policyNameScopeAndVersion = getNameScopeAndVersionFromPdpPolicy(policyID);
2721                 if (policyNameScopeAndVersion == null) {
2722                     throw new IllegalArgumentException("Invalid input - policyID must contain name, scope and version");
2723                 }
2724                 Query policyQuery = em.createQuery(
2725                         "SELECT p FROM PolicyEntity p WHERE p.policyName=:policyName AND p.scope=:scope AND p"
2726                                 + ".deleted=:deleted");
2727                 policyQuery.setParameter("policyName", policyNameScopeAndVersion[0]);
2728                 policyQuery.setParameter(scope, policyNameScopeAndVersion[1]);
2729                 policyQuery.setParameter(deletedVar, false);
2730                 List<?> policyQueryList;
2731                 try {
2732                     policyQueryList = policyQuery.getResultList();
2733                 } catch (Exception e) {
2734                     logger.debug(e);
2735                     PolicyLogger.error(MessageCodes.EXCEPTION_ERROR, e, policyDBDaoVar,
2736                             "Caught Exception trying to check if policy exists policyQuery.getResultList()");
2737                     throw new PersistenceException(
2738                             "Query failed trying to check if policy " + policyNameScopeAndVersion[0] + " exists");
2739                 }
2740                 if (policyQueryList.isEmpty()) {
2741                     PolicyLogger.error("Policy being added to the group does not exist with policy id "
2742                             + policyNameScopeAndVersion[0]);
2743                     throw new PersistenceException("Policy being added to the group does not exist with policy id "
2744                             + policyNameScopeAndVersion[0]);
2745                 } else if (policyQueryList.size() > 1) {
2746                     PolicyLogger.error(duplicatePolicyId + policyNameScopeAndVersion[0] + foundInDBNotDeleted);
2747                     throw new PersistenceException(
2748                             duplicateGroupId + policyNameScopeAndVersion[0] + foundInDBNotDeleted);
2749                 }
2750                 logger.info("PolicyDBDao: Getting group and policy from database");
2751                 GroupEntity group = (GroupEntity) groupQueryList.get(0);
2752                 PolicyEntity policy = (PolicyEntity) policyQueryList.get(0);
2753                 Iterator<PolicyEntity> policyIt = group.getPolicies().iterator();
2754                 String policyName = getPolicyNameAndVersionFromPolicyFileName(policy.getPolicyName())[0];
2755
2756                 logger.info("PolicyDBDao: policyName retrieved is " + policyName);
2757                 try {
2758                     while (policyIt.hasNext()) {
2759                         PolicyEntity pol = policyIt.next();
2760                         if (policy.getScope().equals(pol.getScope())
2761                                 && getPolicyNameAndVersionFromPolicyFileName(pol.getPolicyName())[0]
2762                                         .equals(policyName)) {
2763                             policyIt.remove();
2764                         }
2765                     }
2766                 } catch (Exception e) {
2767                     logger.debug(e);
2768                     PolicyLogger.error("Could not delete old versions for policy " + policy.getPolicyName() + ", ID: "
2769                             + policy.getPolicyId());
2770                 }
2771                 group.addPolicyToGroup(policy);
2772                 em.flush();
2773
2774                 // After adding policy to the db group we need to make sure the filesytem group is in sync with the db
2775                 // group
2776                 try {
2777                     StdPDPGroup pdpGroup = (StdPDPGroup) papEngine.getGroup(group.getGroupId());
2778                     return synchronizeGroupPoliciesInFileSystem(pdpGroup, group);
2779                 } catch (PAPException e) {
2780                     logger.debug(e);
2781                     PolicyLogger
2782                             .error("PolicyDBDao: Could not synchronize the filesystem group with the database group. "
2783                                     + e.getMessage());
2784                 }
2785                 return null;
2786             }
2787         }
2788
2789         // this means delete pdp not just remove from group
2790         @Override
2791         public void removePdpFromGroup(String pdpID, String username) {
2792             logger.debug("removePdpFromGroup(String pdpID, String username) as removePdpFromGroup(" + pdpID + ","
2793                     + username + ") called");
2794             if (isNullOrEmpty(pdpID, username)) {
2795                 throw new IllegalArgumentException("pdpID and username must not be null or empty");
2796             }
2797             synchronized (emLock) {
2798                 checkBeforeOperationRun();
2799                 Query pdpQuery = em.createQuery(pdpEntitySelectQuery);
2800                 pdpQuery.setParameter(pdpIdVariable, pdpID);
2801                 pdpQuery.setParameter(deletedVar, false);
2802                 List<?> pdpList;
2803                 try {
2804                     pdpList = pdpQuery.getResultList();
2805                 } catch (Exception e) {
2806                     PolicyLogger.error(MessageCodes.EXCEPTION_ERROR, e, policyDBDaoVar,
2807                             "Caught Exception trying to check if pdp exists  pdpQuery.getResultList()");
2808                     throw new PersistenceException("Query failed trying to check if pdp " + pdpID + " exists");
2809                 }
2810                 if (pdpList.size() > 1) {
2811                     PolicyLogger.error("Somehow, more than one pdp with the id " + pdpID + foundInDBNotDeleted);
2812                     throw new PersistenceException(
2813                             "Somehow, more than one pdp with the id " + pdpID + foundInDBNotDeleted);
2814                 } else if (pdpList.isEmpty()) {
2815                     PolicyLogger.error("Pdp being removed does not exist with id " + pdpID);
2816                     return;
2817                 }
2818                 PdpEntity pdp = (PdpEntity) pdpList.get(0);
2819                 pdp.setGroup(null);
2820                 if (!stringEquals(pdp.getModifiedBy(), username)) {
2821                     pdp.setModifiedBy(username);
2822                 }
2823                 pdp.setDeleted(true);
2824
2825                 em.flush();
2826                 this.pdpId = pdp.getPdpKey();
2827             }
2828         }
2829
2830         private void notifyOthers(long entityId, String entityType) {
2831             notifyOthers(entityId, entityType, null);
2832         }
2833
2834         private void notifyOthers(long entityId, String entityType, String newGroupId) {
2835             logger.debug("notifyOthers(long entityId, String entityType, long newGroupId) as notifyOthers(" + entityId
2836                     + "," + entityType + "," + newGroupId + ") called");
2837             LinkedList<Thread> notifyThreads = new LinkedList<>();
2838
2839             // we're going to run notifications in parallel threads to speed things up
2840             for (Object obj : otherServers) {
2841                 Thread newNotifyThread = new Thread(new NotifyOtherThread(obj, entityId, entityType, newGroupId));
2842                 newNotifyThread.start();
2843                 notifyThreads.add(newNotifyThread);
2844             }
2845             // we want to wait for all notifications to complete or timeout before we unlock the interface and allow
2846             // more changes
2847             for (Thread t : notifyThreads) {
2848                 try {
2849                     t.join();
2850                 } catch (Exception e) {
2851                     logger.warn("Could not join a notifcation thread" + e);
2852                 }
2853             }
2854         }
2855     }
2856
2857     private PolicyDBDao() {
2858         // empty constructor
2859     }
2860
2861     public static PolicyDBDaoTestClass getPolicyDBDaoTestClass() {
2862         return new PolicyDBDao().new PolicyDBDaoTestClass();
2863     }
2864
2865     final class PolicyDBDaoTestClass {
2866         String getConfigFile(String filename, String scope, PolicyRestAdapter policy) {
2867             return scope + "." + PolicyDBDao.this.getConfigFile(filename, policy);
2868         }
2869
2870         String[] getPolicyNameAndVersionFromPolicyFileName(String originalPolicyName) throws PolicyDBException {
2871             return PolicyDBDao.this.getPolicyNameAndVersionFromPolicyFileName(originalPolicyName);
2872         }
2873         
2874         String[] getNameScopeAndVersionFromPdpPolicy(String fileName) {
2875             return PolicyDBDao.this.getNameScopeAndVersionFromPdpPolicy(fileName);
2876         }
2877         
2878         String getPdpPolicyName(String name, String scope) {
2879             return PolicyDBDao.this.getPdpPolicyName(name, scope);
2880         }
2881         
2882         Path getPolicySubFile(String inputFileName, String subFileType) {
2883             return PolicyDBDao.this.getPolicySubFile(inputFileName, subFileType);
2884         }
2885     }
2886
2887 }