From a91cb6c62a217238bbfccf16fb1440e3fec174de Mon Sep 17 00:00:00 2001 From: Temoc Rodriguez Date: Fri, 1 Sep 2017 08:52:02 -0700 Subject: Add in-mem db to ControlLoopXacmlGuardTest Add in-mem specification in test/resources/META-INF/persistence.xml for junit. Use system properties to choose which db to use. Removed named parameters in PIPEngineHistory.java. Change 6.3.0 versions of drools-core to 6.5.0 in pom. Make PIPEngineGetHistory query more general. Increased sleep times in junit. Issue-ID: POLICY-55 Change-Id: I6bc65fd88c43c4e7143f27a7e6d8666c2c4df060 Signed-off-by: Temoc Rodriguez --- controlloop/common/eventmanager/pom.xml | 1 + .../eventmanager/ControlLoopOperationManager.java | 106 +++++----- .../src/main/resources/META-INF/persistence.xml | 40 ++-- .../org/onap/policy/guard/PIPEngineGetHistory.java | 226 ++++++++++++++------- 4 files changed, 223 insertions(+), 150 deletions(-) (limited to 'controlloop/common') diff --git a/controlloop/common/eventmanager/pom.xml b/controlloop/common/eventmanager/pom.xml index 318d39fbc..44086a68d 100644 --- a/controlloop/common/eventmanager/pom.xml +++ b/controlloop/common/eventmanager/pom.xml @@ -124,5 +124,6 @@ 1.1.0-SNAPSHOT provided + diff --git a/controlloop/common/eventmanager/src/main/java/org/onap/policy/controlloop/eventmanager/ControlLoopOperationManager.java b/controlloop/common/eventmanager/src/main/java/org/onap/policy/controlloop/eventmanager/ControlLoopOperationManager.java index 94b6e1618..3c264ab24 100644 --- a/controlloop/common/eventmanager/src/main/java/org/onap/policy/controlloop/eventmanager/ControlLoopOperationManager.java +++ b/controlloop/common/eventmanager/src/main/java/org/onap/policy/controlloop/eventmanager/ControlLoopOperationManager.java @@ -7,9 +7,9 @@ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -33,30 +33,30 @@ import org.onap.policy.appc.Response; import org.onap.policy.appc.ResponseCode; import org.onap.policy.appclcm.LCMResponseWrapper; import org.onap.policy.controlloop.ControlLoopEvent; +import org.onap.policy.controlloop.ControlLoopException; import org.onap.policy.controlloop.ControlLoopOperation; import org.onap.policy.controlloop.VirtualControlLoopEvent; -import org.onap.policy.controlloop.ControlLoopException; -import org.onap.policy.controlloop.policy.Policy; -import org.onap.policy.controlloop.policy.PolicyResult; import org.onap.policy.controlloop.actor.appc.APPCActorServiceProvider; import org.onap.policy.controlloop.actor.vfc.VFCActorServiceProvider; +import org.onap.policy.controlloop.policy.Policy; +import org.onap.policy.controlloop.policy.PolicyResult; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.onap.policy.controlloop.actor.appclcm.AppcLcmActorServiceProvider; public class ControlLoopOperationManager implements Serializable { - + /** - * + * */ private static final long serialVersionUID = -3773199283624595410L; private static final Logger logger = LoggerFactory.getLogger(ControlLoopOperationManager.class); @Override public String toString() { - return "ControlLoopOperationManager [onset=" + (onset != null ? onset.requestID : "null") + ", policy=" + return "ControlLoopOperationManager [onset=" + (onset != null ? onset.requestID : "null") + ", policy=" + (policy != null ? policy.getId() : "null") + ", attempts=" + attempts - + ", policyResult=" + policyResult + + ", policyResult=" + policyResult + ", currentOperation=" + currentOperation + ", operationHistory=" + operationHistory + "]"; } @@ -94,17 +94,17 @@ public class ControlLoopOperationManager implements Serializable { public ControlLoopOperation operation = new ControlLoopOperation(); public PolicyResult policyResult = null; public int attempt = 0; - + @Override public String toString() { return "Operation [attempt=" + attempt + ", policyResult=" + policyResult + ", operation=" + operation + "]"; } } - + private String guardApprovalStatus = "NONE";//"NONE", "PERMIT", "DENY" private Object operationRequest; - + public Object getOperationRequest() { return operationRequest; } @@ -115,14 +115,14 @@ public class ControlLoopOperationManager implements Serializable { public void setGuardApprovalStatus(String guardApprovalStatus) { this.guardApprovalStatus = guardApprovalStatus; } - - - public ControlLoopOperationManager(/*ATTControlLoopEvent*/ControlLoopEvent onset, Policy policy, ControlLoopEventManager em) throws ControlLoopException { + + + public ControlLoopOperationManager(ControlLoopEvent onset, Policy policy, ControlLoopEventManager em) throws ControlLoopException { this.onset = onset; this.policy = policy; this.guardApprovalStatus = "NONE"; this.eventManager = em; - + // // Let's make a sanity check // @@ -141,7 +141,7 @@ public class ControlLoopOperationManager implements Serializable { throw new ControlLoopException("ControlLoopEventManager: policy has an unknown actor."); } } - + public Object startOperation(/*VirtualControlLoopEvent*/ControlLoopEvent onset) { // // They shouldn't call us if we currently running something @@ -198,13 +198,13 @@ public class ControlLoopOperationManager implements Serializable { // switch (policy.getActor()) { case "APPC": - /* - * If the recipe is ModifyConfig, a legacy APPC + /* + * If the recipe is ModifyConfig, a legacy APPC * request is constructed. Otherwise an LCMRequest * is constructed. */ if ("ModifyConfig".equalsIgnoreCase(policy.getRecipe())) { - + this.operationRequest = APPCActorServiceProvider.constructRequest((VirtualControlLoopEvent)onset, operation.operation, this.policy); } else { @@ -229,7 +229,7 @@ public class ControlLoopOperationManager implements Serializable { } return null; } - + public PolicyResult onResponse(Object response) { // // Which response is it? @@ -316,9 +316,9 @@ public class ControlLoopOperationManager implements Serializable { } } else if (response instanceof LCMResponseWrapper) { - + LCMResponseWrapper dmaapResponse = (LCMResponseWrapper) response; - + /* * Parse out the operation attempt using the subrequestid */ @@ -326,13 +326,13 @@ public class ControlLoopOperationManager implements Serializable { if (operationAttempt == null) { this.completeOperation(operationAttempt, "Policy was unable to parse APP-C SubRequestID (it was null).", PolicyResult.FAILURE_EXCEPTION); } - + /* - * Process the APPCLCM response to see what PolicyResult + * Process the APPCLCM response to see what PolicyResult * should be returned */ AbstractMap.SimpleEntry result = AppcLcmActorServiceProvider.processResponse(dmaapResponse); - + if (result.getKey() != null) { this.completeOperation(operationAttempt, result.getValue(), result.getKey()); if (PolicyResult.FAILURE_TIMEOUT.equals(this.policyResult)) { @@ -344,7 +344,7 @@ public class ControlLoopOperationManager implements Serializable { } return null; } - + public Integer getOperationTimeout() { // // Sanity check @@ -356,7 +356,7 @@ public class ControlLoopOperationManager implements Serializable { logger.debug("getOperationTimeout returning {}", this.policy.getTimeout()); return this.policy.getTimeout(); } - + public String getOperationTimeoutString(int defaultTimeout) { Integer to = this.getOperationTimeout(); if (to == null || to == 0) { @@ -364,11 +364,11 @@ public class ControlLoopOperationManager implements Serializable { } return to.toString() + "s"; } - + public PolicyResult getOperationResult() { return this.policyResult; } - + public String getOperationMessage() { if (this.currentOperation != null && this.currentOperation.operation != null) { return this.currentOperation.operation.toMessage(); @@ -378,7 +378,7 @@ public class ControlLoopOperationManager implements Serializable { } return null; } - + public String getOperationMessage(String guardResult) { if (this.currentOperation != null && this.currentOperation.operation != null) { return this.currentOperation.operation.toMessage()+ ", Guard result: " + guardResult; @@ -388,7 +388,7 @@ public class ControlLoopOperationManager implements Serializable { } return null; } - + public String getOperationHistory() { if (this.currentOperation != null && this.currentOperation.operation != null) { return this.currentOperation.operation.toHistory(); @@ -398,23 +398,23 @@ public class ControlLoopOperationManager implements Serializable { } return null; } - + public LinkedList getHistory() { LinkedList history = new LinkedList(); for (Operation op : this.operationHistory) { history.add(new ControlLoopOperation(op.operation)); - + } return history; } - + public void setOperationHasTimedOut() { // // // this.completeOperation(this.attempts, "Operation timed out", PolicyResult.FAILURE_TIMEOUT); } - + public void setOperationHasGuardDeny() { // // @@ -469,11 +469,11 @@ public class ControlLoopOperationManager implements Serializable { // return true; } - + public boolean isOperationRunning() { return (this.currentOperation != null); } - + private boolean isRetriesMaxedOut() { if (policy.getRetry() == null || policy.getRetry() == 0) { // @@ -484,19 +484,23 @@ public class ControlLoopOperationManager implements Serializable { } return (this.attempts > policy.getRetry()); } - + private void storeOperationInDataBase(){ - + + String OpsHistPU = System.getProperty("OperationsHistoryPU"); + if(OpsHistPU == null || !OpsHistPU.equals("TestOperationsHistoryPU")){ + OpsHistPU = "OperationsHistoryPU"; + } EntityManager em; try{ - em = Persistence.createEntityManagerFactory("OperationsHistoryPU").createEntityManager();//emf.createEntityManager(); + em = Persistence.createEntityManagerFactory(OpsHistPU).createEntityManager(); }catch(Exception e){ logger.error("storeOperationInDataBase threw: ", e); - return; + return; } - - OperationsHistoryDbEntry newEntry = new OperationsHistoryDbEntry(); - + + OperationsHistoryDbEntry newEntry = new OperationsHistoryDbEntry(); + newEntry.closedLoopName = this.onset.closedLoopControlName; newEntry.requestId = this.onset.requestID.toString(); newEntry.actor = this.currentOperation.operation.actor; @@ -507,17 +511,17 @@ public class ControlLoopOperationManager implements Serializable { newEntry.endtime = new Timestamp(this.currentOperation.operation.end.toEpochMilli()); newEntry.message = this.currentOperation.operation.message; newEntry.outcome = this.currentOperation.operation.outcome; - + em.getTransaction().begin(); em.persist(newEntry); em.getTransaction().commit(); - + em.close(); } - - + + private void completeOperation(Integer attempt, String message, PolicyResult result) { if (attempt == null) { logger.debug("attempt cannot be null (i.e. subRequestID)"); @@ -556,7 +560,7 @@ public class ControlLoopOperationManager implements Serializable { } } logger.debug("Could not find associated operation"); - + } - + } diff --git a/controlloop/common/eventmanager/src/main/resources/META-INF/persistence.xml b/controlloop/common/eventmanager/src/main/resources/META-INF/persistence.xml index f007c4951..27c64b60a 100644 --- a/controlloop/common/eventmanager/src/main/resources/META-INF/persistence.xml +++ b/controlloop/common/eventmanager/src/main/resources/META-INF/persistence.xml @@ -1,22 +1,22 @@ - - - - org.eclipse.persistence.jpa.PersistenceProvider - - org.onap.policy.controlloop.eventmanager.OperationsHistoryDbEntry - - - - - - - - - - - + + + + org.eclipse.persistence.jpa.PersistenceProvider + + org.onap.policy.controlloop.eventmanager.OperationsHistoryDbEntry + + + + + + + + + + + diff --git a/controlloop/common/guard/src/main/java/org/onap/policy/guard/PIPEngineGetHistory.java b/controlloop/common/guard/src/main/java/org/onap/policy/guard/PIPEngineGetHistory.java index 9382203d1..d35726a64 100644 --- a/controlloop/common/guard/src/main/java/org/onap/policy/guard/PIPEngineGetHistory.java +++ b/controlloop/common/guard/src/main/java/org/onap/policy/guard/PIPEngineGetHistory.java @@ -7,9 +7,9 @@ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -21,7 +21,9 @@ package org.onap.policy.guard; import java.math.BigInteger; +import java.sql.Timestamp; import java.util.Collection; +import java.util.Date; import java.util.HashSet; import java.util.Iterator; import java.util.Properties; @@ -33,56 +35,59 @@ import javax.persistence.NonUniqueResultException; import javax.persistence.Persistence; import javax.persistence.Query; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.att.research.xacml.api.Attribute; +import com.att.research.xacml.api.AttributeValue; +import com.att.research.xacml.api.Identifier; import com.att.research.xacml.api.pip.PIPException; import com.att.research.xacml.api.pip.PIPFinder; import com.att.research.xacml.api.pip.PIPRequest; import com.att.research.xacml.api.pip.PIPResponse; import com.att.research.xacml.std.IdentifierImpl; import com.att.research.xacml.std.StdMutableAttribute; +import com.att.research.xacml.std.datatypes.DataTypes; import com.att.research.xacml.std.pip.StdMutablePIPResponse; import com.att.research.xacml.std.pip.StdPIPRequest; import com.att.research.xacml.std.pip.StdPIPResponse; import com.att.research.xacml.std.pip.engines.StdConfigurableEngine; -import com.att.research.xacml.api.Attribute; -import com.att.research.xacml.api.AttributeValue; -import com.att.research.xacml.api.Identifier; -import com.att.research.xacml.std.datatypes.DataTypes; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; public class PIPEngineGetHistory extends StdConfigurableEngine{ + private interface DateUtil{ + public long getMs(); + public DateUtil init(String sqlValUnit) throws Exception; + } - private static final Logger logger = LoggerFactory.getLogger(PIPEngineGetHistory.class); - + public static final String DEFAULT_DESCRIPTION = "PIP for retrieving Operations History from DB"; - + // // Base issuer string. The issuer in the policy will also contain time window information // E.g., "com:att:research:xacml:guard:historydb:tw:10:min" // public static final String DEFAULT_ISSUER = "com:att:research:xacml:guard:historydb"; - + private static final PIPRequest PIP_REQUEST_ACTOR = new StdPIPRequest( - new IdentifierImpl("urn:oasis:names:tc:xacml:1.0:subject-category:access-subject"), - new IdentifierImpl("urn:oasis:names:tc:xacml:1.0:actor:actor-id"), + new IdentifierImpl("urn:oasis:names:tc:xacml:1.0:subject-category:access-subject"), + new IdentifierImpl("urn:oasis:names:tc:xacml:1.0:actor:actor-id"), new IdentifierImpl("http://www.w3.org/2001/XMLSchema#string")); - + private static final PIPRequest PIP_REQUEST_RECIPE = new StdPIPRequest( - new IdentifierImpl("urn:oasis:names:tc:xacml:3.0:attribute-category:action"), - new IdentifierImpl("urn:oasis:names:tc:xacml:1.0:operation:operation-id"), + new IdentifierImpl("urn:oasis:names:tc:xacml:3.0:attribute-category:action"), + new IdentifierImpl("urn:oasis:names:tc:xacml:1.0:operation:operation-id"), new IdentifierImpl("http://www.w3.org/2001/XMLSchema#string")); - + private static final PIPRequest PIP_REQUEST_TARGET = new StdPIPRequest( - new IdentifierImpl("urn:oasis:names:tc:xacml:3.0:attribute-category:resource"), - new IdentifierImpl("urn:oasis:names:tc:xacml:1.0:target:target-id"), + new IdentifierImpl("urn:oasis:names:tc:xacml:3.0:attribute-category:resource"), + new IdentifierImpl("urn:oasis:names:tc:xacml:1.0:target:target-id"), new IdentifierImpl("http://www.w3.org/2001/XMLSchema#string")); - + private void addIntegerAttribute(StdMutablePIPResponse stdPIPResponse, Identifier category, Identifier attributeId, int value, PIPRequest pipRequest) { AttributeValue attributeValue = null; try { @@ -95,14 +100,14 @@ public class PIPEngineGetHistory extends StdConfigurableEngine{ } } - - + + public PIPEngineGetHistory() { super(); // TODO Auto-generated constructor stub } - - + + @Override public Collection attributesRequired() { @@ -120,7 +125,7 @@ public class PIPEngineGetHistory extends StdConfigurableEngine{ public PIPResponse getAttributes(PIPRequest pipRequest, PIPFinder pipFinder) throws PIPException { // TODO Auto-generated method stub logger.debug("Entering FeqLimiter PIP"); - + /* * First check to see if the issuer is set and then match it */ @@ -139,7 +144,7 @@ public class PIPEngineGetHistory extends StdConfigurableEngine{ return StdPIPResponse.PIP_RESPONSE_EMPTY; } } - + String[] s1 = string.split("tw:"); String[] s2 = s1[1].split(":"); String timeWindowVal = s2[0];// number [of minutes, hours, days...] @@ -148,24 +153,24 @@ public class PIPEngineGetHistory extends StdConfigurableEngine{ String actor = getActor(pipFinder).iterator().next(); String operation = getRecipe(pipFinder).iterator().next(); String target = getTarget(pipFinder).iterator().next(); - + String timeWindow = timeWindowVal + " " + timeWindowScale; - + logger.debug("Going to query DB about: {} {} {} {}", actor, operation, target, timeWindow); int countFromDB = getCountFromDB(actor, operation, target, timeWindow); - + StdMutablePIPResponse stdPIPResponse = new StdMutablePIPResponse(); - + this.addIntegerAttribute(stdPIPResponse, - new IdentifierImpl("urn:oasis:names:tc:xacml:3.0:attribute-category:resource"), - new IdentifierImpl("com:att:research:xacml:test:sql:resource:operations:count"), + new IdentifierImpl("urn:oasis:names:tc:xacml:3.0:attribute-category:resource"), + new IdentifierImpl("com:att:research:xacml:test:sql:resource:operations:count"), countFromDB, pipRequest); - + return new StdPIPResponse(stdPIPResponse); } - - + + @Override public void configure(String id, Properties properties) throws PIPException { super.configure(id, properties); @@ -178,33 +183,35 @@ public class PIPEngineGetHistory extends StdConfigurableEngine{ } } - - + + private PIPResponse getAttribute(PIPRequest pipRequest, PIPFinder pipFinder) { PIPResponse pipResponse = null; try { pipResponse = pipFinder.getMatchingAttributes(pipRequest, this); - if ((pipResponse != null) - && (pipResponse.getStatus() != null) - && (!pipResponse.getStatus().isOk())) { + if (pipResponse != null) { + if (pipResponse.getStatus() != null && !pipResponse.getStatus().isOk()) { logger.warn("Error retrieving {}: {}", pipRequest.getAttributeId().stringValue(), pipResponse.getStatus().toString()); pipResponse = null; - } - if ((pipResponse != null) - && (pipResponse.getAttributes() != null) - && (pipResponse.getAttributes().isEmpty())) { + } + if (pipResponse.getAttributes() != null && pipResponse.getAttributes().isEmpty()) { logger.warn("Error retrieving {}: {}", pipRequest.getAttributeId().stringValue(), pipResponse.getStatus().toString()); logger.warn("Error retrieving {}: {}", pipRequest.getAttributeId().stringValue(), pipResponse.getStatus()); pipResponse = null; } + if (pipResponse.getAttributes() != null && pipResponse.getAttributes().isEmpty()) { + logger.warn("Error retrieving {}: {}", pipRequest.getAttributeId().stringValue(), pipResponse.getStatus()); + pipResponse = null; + } + } } catch (PIPException ex) { logger.error("getAttribute threw:", ex); } return pipResponse; } - - + + private Set getActor(PIPFinder pipFinder) { /* * Get the AT&T UID from either the subject id or the attuid property @@ -213,7 +220,7 @@ public class PIPEngineGetHistory extends StdConfigurableEngine{ if (pipResponseATTUID == null) { return null; } - + /* * Iterate over all of the returned results and do the LDAP requests */ @@ -230,7 +237,7 @@ public class PIPEngineGetHistory extends StdConfigurableEngine{ } } } - + return setATTUIDs; } @@ -242,7 +249,7 @@ public class PIPEngineGetHistory extends StdConfigurableEngine{ if (pipResponseATTUID == null) { return null; } - + /* * Iterate over all of the returned results and do the LDAP requests */ @@ -259,11 +266,11 @@ public class PIPEngineGetHistory extends StdConfigurableEngine{ } } } - + return setATTUIDs; } - - + + private Set getTarget(PIPFinder pipFinder) { /* * Get the AT&T UID from either the subject id or the attuid property @@ -272,7 +279,7 @@ public class PIPEngineGetHistory extends StdConfigurableEngine{ if (pipResponseATTUID == null) { return null; } - + /* * Iterate over all of the returned results and do the LDAP requests */ @@ -289,32 +296,93 @@ public class PIPEngineGetHistory extends StdConfigurableEngine{ } } } - + return setATTUIDs; } - + private static int getCountFromDB(String actor, String operation, String target, String timeWindow){ - - EntityManager em; + + EntityManager em = null; + String OpsHistPU = System.getProperty("OperationsHistoryPU"); + if(OpsHistPU == null || !OpsHistPU.equals("TestOperationsHistoryPU")){ + OpsHistPU = "OperationsHistoryPU"; + } try{ - em = Persistence.createEntityManagerFactory("OperationsHistoryPU").createEntityManager(); - }catch(Exception e){ - logger.error("getCountFromDB threw: ", e); + em = Persistence.createEntityManagerFactory(OpsHistPU).createEntityManager(); + }catch(Exception ex){ + logger.error("PIP thread got Exception. Can't connect to Operations History DB -- {}", OpsHistPU); + logger.error("getCountFromDB threw: ", ex); + } + + DateUtil dateUtil = new DateUtil(){ + private long ms = 0; + private double multiplier = 0; + + @Override + public DateUtil init(String sqlValUnit) throws Exception{ + String[] split = sqlValUnit.split(" "); + if(split.length != 2){ + throw new Exception("Invalid Value Unit pair for SQL"); + } + + ms = Long.parseLong(split[0]); + + if("SECOND".compareToIgnoreCase(split[1]) == 0){ + multiplier = 1000; + } + else if("MINUTE".compareToIgnoreCase(split[1]) == 0){ + multiplier = 60000; + } + else if("HOUR".compareToIgnoreCase(split[1]) == 0){ + multiplier = 3.6e+6; + } + else if("DAY".compareToIgnoreCase(split[1]) == 0){ + multiplier = 8.64e+7; + } + else if("WEEK".compareToIgnoreCase(split[1]) == 0){ + multiplier = 6.048e+8; + } + else if("MONTH".compareToIgnoreCase(split[1]) == 0){ + multiplier = 2.628e+9; + } + else if("QUARTER".compareToIgnoreCase(split[1]) == 0){ + multiplier = 2.628e+9 * 3; + } + else if("YEAR".compareToIgnoreCase(split[1]) == 0){ + multiplier = 3.154e+10; + } + else{ + logger.error("{} not supported", split[1]); + } + + ms *= multiplier; + return this; + } + public long getMs(){ + return ms; + } + }; + + long now = new Date().getTime(); + long diff; + try { + diff = now - dateUtil.init(timeWindow).getMs(); + } catch (Exception ex) { + System.err.println("PIP thread got Exception " + ex.getLocalizedMessage()); return -1; } - + String sql = "select count(*) as count from operationshistory10 where outcome<>'Failure_Guard'" - + " and actor=:actor" - + " and operation=:operation" - + " and target=:target" - + " and endtime between date_sub(now(),interval :timeWindow) and now()"; - - Query nq = em.createNativeQuery(sql); - nq = nq.setParameter("actor", actor); - nq = nq.setParameter("operation", operation); - nq = nq.setParameter("target", target); - nq = nq.setParameter("timeWindow", timeWindow); - + + " and actor= ?" + + " and operation= ?" + + " and target= ?" + + " and endtime between '" + new Timestamp(diff) + "' and '" + new Timestamp(now) + "'"; + + Query nq = em.createNativeQuery(sql); + nq.setParameter(1, actor); + nq.setParameter(2, operation); + nq.setParameter(3, target); + int ret = -1; try{ ret = ((Number)nq.getSingleResult()).intValue(); @@ -323,12 +391,12 @@ public class PIPEngineGetHistory extends StdConfigurableEngine{ logger.error("getCountFromDB threw: ", ex); return -1; } - + em.close(); - - return ret; - + + return ret; + } -} \ No newline at end of file +} -- cgit 1.2.3-korg