From 4b780cfa3125e30acbd055e260bacf58d33c353e Mon Sep 17 00:00:00 2001 From: Jorge Hernandez Date: Thu, 4 May 2017 09:27:34 -0500 Subject: [POLICY-11] New REST APIs to obtain facts info The following REST APIs have been added, shown by example: GET policy/pdp/engine/controllers//drools : drools information for controller named For brevity in URL description, assume: DROOLS-REL-PATH=policy/pdp/engine/controllers//drools GET ${DROOLS-REL-PATH}/[?count=true] fact classes and count for in controller GET ${DROOLS-REL-PATH}// all fact objects of class for session GET ${DROOLS-REL-PATH}/// all fact objects returned by drools query named for the identifier (need corresponding query definition in drl is necessary) Change-Id: I2f62931f54a65eec4ef80472ad1af05f30ed83ba Signed-off-by: Jorge Hernandez --- .../policy/drools/controller/DroolsController.java | 46 ++++- .../controller/internal/MavenDroolsController.java | 189 ++++++++++++++++++++- .../controller/internal/NullDroolsController.java | 58 +++++-- .../drools/protocol/coders/EventProtocolCoder.java | 29 +++- .../policy/drools/server/restful/RestManager.java | 111 ++++++++++-- 5 files changed, 395 insertions(+), 38 deletions(-) (limited to 'policy-management/src') diff --git a/policy-management/src/main/java/org/openecomp/policy/drools/controller/DroolsController.java b/policy-management/src/main/java/org/openecomp/policy/drools/controller/DroolsController.java index 72f8e0b2..0904d438 100644 --- a/policy-management/src/main/java/org/openecomp/policy/drools/controller/DroolsController.java +++ b/policy-management/src/main/java/org/openecomp/policy/drools/controller/DroolsController.java @@ -21,6 +21,7 @@ package org.openecomp.policy.drools.controller; import java.util.List; +import java.util.Map; import org.openecomp.policy.drools.event.comm.TopicSink; import org.openecomp.policy.drools.properties.Lockable; @@ -65,14 +66,20 @@ public interface DroolsController extends Startable, Lockable { * @return version */ public String getVersion(); - /** * return the policy session names * * @return policy session */ - public List getSessionNames(); + public List getSessionNames(); + + /** + * return the policy full session names + * + * @return policy session + */ + public List getCanonicalSessionNames(); /** * offers an event to this controller for processing @@ -152,7 +159,40 @@ public interface DroolsController extends Startable, Lockable { List decoderConfigurations, List encoderConfigurations) throws IllegalArgumentException, LinkageError, Exception; + + /** + * gets the classnames of facts as well as the current count + * @param sessionName the session name + * @return map of class to count + */ + public Map factClassNames(String sessionName) throws IllegalArgumentException; + + /** + * gets the count of facts for a given session + * @param sessionName the session name + * @return the fact count + * @throws IllegalArgumentException + */ + public long factCount(String sessionName) throws IllegalArgumentException; + /** + * gets all the facts of a given class for a given session + * + * @param sessionName the session identifier + * @param className the class type + * @return the list of facts returned by the query + */ + public List facts(String sessionName, String className); + + /** + * gets the facts associated with a query for a give session for a given queried entity + * + * @param sessionName the session + * @param queryName the query identifier + * @param queriedEntity the queried entity + * @return list of facts returned by the query + */ + public List factQuery(String sessionName, String queryName, String queriedEntity); /** * halts and permanently releases all resources @@ -165,6 +205,4 @@ public interface DroolsController extends Startable, Lockable { */ public static final DroolsControllerFactory factory = new IndexedDroolsControllerFactory(); - - } diff --git a/policy-management/src/main/java/org/openecomp/policy/drools/controller/internal/MavenDroolsController.java b/policy-management/src/main/java/org/openecomp/policy/drools/controller/internal/MavenDroolsController.java index 76bc5151..62ad6843 100644 --- a/policy-management/src/main/java/org/openecomp/policy/drools/controller/internal/MavenDroolsController.java +++ b/policy-management/src/main/java/org/openecomp/policy/drools/controller/internal/MavenDroolsController.java @@ -21,10 +21,17 @@ package org.openecomp.policy.drools.controller.internal; import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; import java.util.List; +import java.util.Map; import org.apache.commons.collections4.queue.CircularFifoQueue; - +import org.drools.core.ClassObjectFilter; +import org.kie.api.runtime.KieSession; +import org.kie.api.runtime.rule.FactHandle; +import org.kie.api.runtime.rule.QueryResults; +import org.kie.api.runtime.rule.QueryResultsRow; import org.openecomp.policy.common.logging.eelf.MessageCodes; import org.openecomp.policy.common.logging.flexlogger.FlexLogger; import org.openecomp.policy.common.logging.flexlogger.Logger; @@ -40,6 +47,7 @@ import org.openecomp.policy.drools.protocol.coders.TopicCoderFilterConfiguration import org.openecomp.policy.drools.protocol.coders.TopicCoderFilterConfiguration.CustomJacksonCoder; import org.openecomp.policy.drools.protocol.coders.TopicCoderFilterConfiguration.PotentialCoderFilter; import org.openecomp.policy.drools.utils.ReflectionUtil; + import com.fasterxml.jackson.annotation.JsonIgnore; /** @@ -647,22 +655,193 @@ public class MavenDroolsController implements DroolsController { return this.locked; } + /** + * gets the policy container + * @return the underlying container + */ + @JsonIgnore + protected PolicyContainer getContainer() { + return this.policyContainer; + } + + /** + * {@inheritDoc} + */ @Override public List getSessionNames() { + return getSessionNames(true); + } + + /** + * {@inheritDoc} + */ + @Override + public List getCanonicalSessionNames() { + return getSessionNames(false); + } + + /** + * get session names + * @param abbreviated true for the short form, otherwise the long form + * @return session names + */ + protected List getSessionNames(boolean abbreviated) { List sessionNames = new ArrayList(); try { for (PolicySession session: this.policyContainer.getPolicySessions()) { - sessionNames.add(session.getFullName()); + if (abbreviated) + sessionNames.add(session.getName()); + else + sessionNames.add(session.getFullName()); } } catch (Exception e) { - logger.warn(MessageCodes.EXCEPTION_ERROR, e, - "Can't retrieve POLICY-CORE sessions: " + e.getMessage(), - this.toString()); + logger.warn("Can't retrieve CORE sessions: " + e.getMessage(), e); sessionNames.add(e.getMessage()); } return sessionNames; } + /** + * provides the underlying core layer container sessions + * + * @return the attached Policy Container + */ + protected List getSessions() { + List sessions = new ArrayList(); + sessions.addAll(this.policyContainer.getPolicySessions()); + return sessions; + } + + /** + * provides the underlying core layer container session with name sessionName + * + * @param sessionName session name + * @return the attached Policy Container + * @throws IllegalArgumentException when an invalid session name is provided + * @throws IllegalStateException when the drools controller is in an invalid state + */ + protected PolicySession getSession(String sessionName) { + if (sessionName == null || sessionName.isEmpty()) + throw new IllegalArgumentException("A Session Name must be provided"); + + List sessions = this.getSessions(); + for (PolicySession session : sessions) { + if (sessionName.equals(session.getName()) || sessionName.equals(session.getName())) + return session; + } + + throw new IllegalArgumentException("Invalid Session Name: " + sessionName); + } + + /** + * {@inheritDoc} + */ + @Override + public Map factClassNames(String sessionName) throws IllegalArgumentException { + if (sessionName == null || sessionName.isEmpty()) + throw new IllegalArgumentException("Invalid Session Name: " + sessionName); + + // List classNames = new ArrayList<>(); + Map classNames = new HashMap<>(); + + PolicySession session = getSession(sessionName); + KieSession kieSession = session.getKieSession(); + + Collection facts = session.getKieSession().getFactHandles(); + for (FactHandle fact : facts) { + try { + String className = kieSession.getObject(fact).getClass().getName(); + if (classNames.containsKey(className)) + classNames.put(className, classNames.get(className) + 1); + else + classNames.put(className, 1); + } catch (Exception e) { + if (logger.isInfoEnabled()) + logger.info("Object cannot be retrieved from fact: " + fact); + } + } + + return classNames; + } + + /** + * {@inheritDoc} + */ + @Override + public long factCount(String sessionName) throws IllegalArgumentException { + if (sessionName == null || sessionName.isEmpty()) + throw new IllegalArgumentException("Invalid Session Name: " + sessionName); + + PolicySession session = getSession(sessionName); + return session.getKieSession().getFactCount(); + } + + /** + * {@inheritDoc} + */ + @Override + public List facts(String sessionName, String className) { + if (sessionName == null || sessionName.isEmpty()) + throw new IllegalArgumentException("Invalid Session Name: " + sessionName); + + if (className == null || className.isEmpty()) + throw new IllegalArgumentException("Invalid Class Name: " + className); + + Class factClass = + ReflectionUtil.fetchClass(this.policyContainer.getClassLoader(), className); + if (factClass == null) + throw new IllegalArgumentException("Class cannot be fetched in model's classloader: " + className); + + PolicySession session = getSession(sessionName); + KieSession kieSession = session.getKieSession(); + + List factObjects = new ArrayList<>(); + + Collection factHandles = kieSession.getFactHandles(new ClassObjectFilter(factClass)); + for (FactHandle factHandle : factHandles) { + try { + factObjects.add(kieSession.getObject(factHandle)); + } catch (Exception e) { + if (logger.isInfoEnabled()) + logger.info("Object cannot be retrieved from fact: " + factHandle); + } + } + + return factObjects; + } + + /** + * {@inheritDoc} + */ + @Override + public List factQuery(String sessionName, String queryName, String queriedEntity) { + if (sessionName == null || sessionName.isEmpty()) + throw new IllegalArgumentException("Invalid Session Name: " + sessionName); + + if (queryName == null || queryName.isEmpty()) + throw new IllegalArgumentException("Invalid Query Name: " + queryName); + + if (queriedEntity == null || queriedEntity.isEmpty()) + throw new IllegalArgumentException("Invalid Queried Entity: " + queriedEntity); + + PolicySession session = getSession(sessionName); + KieSession kieSession = session.getKieSession(); + + List factObjects = new ArrayList<>(); + + QueryResults queryResults = kieSession.getQueryResults(queryName); + for (QueryResultsRow row : queryResults) { + try { + factObjects.add(row.get(queriedEntity)); + } catch (Exception e) { + if (logger.isInfoEnabled()) + logger.info("Object cannot be retrieved from fact: " + row); + } + } + + return factObjects; + } + /** * {@inheritDoc} */ diff --git a/policy-management/src/main/java/org/openecomp/policy/drools/controller/internal/NullDroolsController.java b/policy-management/src/main/java/org/openecomp/policy/drools/controller/internal/NullDroolsController.java index f0c0f474..ac07bb7d 100644 --- a/policy-management/src/main/java/org/openecomp/policy/drools/controller/internal/NullDroolsController.java +++ b/policy-management/src/main/java/org/openecomp/policy/drools/controller/internal/NullDroolsController.java @@ -21,7 +21,9 @@ package org.openecomp.policy.drools.controller.internal; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; +import java.util.Map; import org.openecomp.policy.drools.controller.DroolsController; import org.openecomp.policy.drools.event.comm.TopicSink; @@ -31,16 +33,6 @@ import org.openecomp.policy.drools.protocol.coders.TopicCoderFilterConfiguration * no-op Drools Controller */ public class NullDroolsController implements DroolsController { - - /** - * empty cached events - */ - protected static final String[] emptyRecentEvents = new String[0]; - - /** - * empty session names - */ - protected static final List emptySessionNames = new ArrayList(); /** * {@inheritDoc} @@ -128,7 +120,7 @@ public class NullDroolsController implements DroolsController { @Override public String getVersion() { return NO_VERSION; - } + } /** * {@inheritDoc} @@ -138,6 +130,14 @@ public class NullDroolsController implements DroolsController { return new ArrayList(); } + /** + * {@inheritDoc} + */ + @Override + public List getCanonicalSessionNames() { + return new ArrayList(); + } + /** * {@inheritDoc} */ @@ -160,7 +160,7 @@ public class NullDroolsController implements DroolsController { */ @Override public Object[] getRecentSourceEvents() { - return NullDroolsController.emptyRecentEvents; + return new String[0]; } /** @@ -168,7 +168,7 @@ public class NullDroolsController implements DroolsController { */ @Override public String[] getRecentSinkEvents() { - return NullDroolsController.emptyRecentEvents; + return new String[0]; } /** @@ -216,4 +216,36 @@ public class NullDroolsController implements DroolsController { throw new IllegalArgumentException(this.getClass().getCanonicalName() + " invoked"); } + /** + * {@inheritDoc} + */ + @Override + public Map factClassNames(String sessionName) throws IllegalArgumentException { + return new HashMap(); + } + + /** + * {@inheritDoc} + */ + @Override + public long factCount(String sessionName) throws IllegalArgumentException { + return 0; + } + + /** + * {@inheritDoc} + */ + @Override + public List facts(String sessionName, String className) { + return new ArrayList(); + } + + /** + * {@inheritDoc} + */ + @Override + public List factQuery(String sessionName, String queryName, String queriedEntity) { + return new ArrayList(); + } + } diff --git a/policy-management/src/main/java/org/openecomp/policy/drools/protocol/coders/EventProtocolCoder.java b/policy-management/src/main/java/org/openecomp/policy/drools/protocol/coders/EventProtocolCoder.java index 8f8a4ba7..d82b3724 100644 --- a/policy-management/src/main/java/org/openecomp/policy/drools/protocol/coders/EventProtocolCoder.java +++ b/policy-management/src/main/java/org/openecomp/policy/drools/protocol/coders/EventProtocolCoder.java @@ -1075,7 +1075,7 @@ abstract class GenericEventProtocolCoder { * @throws UnsupportedOperationException if the operation cannot be performed */ public String encode(String topic, Object encodedClass) - throws IllegalArgumentException, IllegalArgumentException, UnsupportedOperationException { + throws IllegalArgumentException, IllegalStateException, UnsupportedOperationException { if (encodedClass == null) { throw new IllegalArgumentException("Invalid encoded class"); @@ -1090,11 +1090,20 @@ abstract class GenericEventProtocolCoder { encodedClass); List droolsControllers = droolsCreators(topic, encodedClass); + + if (droolsControllers.isEmpty()) { + if (logger.isWarnEnabled()) + logger.warn("No Drool Controllers for: " + topic + ":" + + encodedClass.getClass().getCanonicalName() + ":" + + droolsControllers + " IN " + this); + throw new IllegalArgumentException("Invalid Topic: " + topic); + } + if (droolsControllers.size() > 1) { - // unexpected - logger.warn("MULTIPLE DROOLS CONTROLLERS FOUND for: " + topic + ":" + - encodedClass.getClass().getCanonicalName() + ":" + - droolsControllers + " IN " + this); + if (logger.isWarnEnabled()) + logger.warn("MULTIPLE DROOLS CONTROLLERS FOUND for: " + topic + ":" + + encodedClass.getClass().getCanonicalName() + ":" + + droolsControllers + " IN " + this); // continue } @@ -1376,8 +1385,16 @@ abstract class GenericEventProtocolCoder { } List droolsControllers = droolsCreators(topic, fact); + + if (droolsControllers.isEmpty()) { + if (logger.isWarnEnabled()) + logger.warn("No Drool Controllers for: " + topic + ":" + + fact.getClass().getCanonicalName() + ":" + + droolsControllers + " IN " + this); + throw new IllegalArgumentException("Invalid Topic: " + topic); + } + if (droolsControllers.size() > 1) { - // unexpected logger.warn("MULTIPLE DROOLS CONTROLLERS FOUND for: " + topic + ":" + fact.getClass().getCanonicalName() + ":" + droolsControllers + " IN " + this); diff --git a/policy-management/src/main/java/org/openecomp/policy/drools/server/restful/RestManager.java b/policy-management/src/main/java/org/openecomp/policy/drools/server/restful/RestManager.java index 48e6313a..cb5d3688 100644 --- a/policy-management/src/main/java/org/openecomp/policy/drools/server/restful/RestManager.java +++ b/policy-management/src/main/java/org/openecomp/policy/drools/server/restful/RestManager.java @@ -405,16 +405,94 @@ public class RestManager { build(); } - public DroolsController getDroolsController(String controllerName) throws IllegalArgumentException { - PolicyController controller = PolicyController.factory.get(controllerName); - if (controller == null) - throw new IllegalArgumentException(controllerName + " does not exist"); - - DroolsController drools = controller.getDrools(); - if (drools == null) - throw new IllegalArgumentException(controllerName + " has no drools configuration"); - - return drools; + @GET + @Path("engine/controllers/{controllerName}/drools") + @Produces(MediaType.APPLICATION_JSON) + public Response drools(@PathParam("controllerName") String controllerName) { + try { + DroolsController drools = getDroolsController(controllerName); + return Response.status(Response.Status.OK). + entity(drools). + build(); + } catch (IllegalArgumentException | IllegalStateException e) { + logger.warn(MessageCodes.EXCEPTION_ERROR, e, + controllerName, this.toString()); + return Response.status(Response.Status.BAD_REQUEST). + entity(new Error(e.getMessage())). + build(); + } + } + + @GET + @Path("engine/controllers/{controllerName}/drools/facts/{sessionName}") + @Produces(MediaType.APPLICATION_JSON) + public Response droolsFacts(@DefaultValue("false") @QueryParam("count") boolean count, + @PathParam("controllerName") String controllerName, + @PathParam("sessionName") String sessionName) { + try { + DroolsController drools = getDroolsController(controllerName); + if (!count) + return Response.status(Response.Status.OK). + entity(drools.factClassNames(sessionName)). + build(); + else + return Response.status(Response.Status.OK). + entity(new Long(drools.factCount(sessionName))). + build(); + } catch (IllegalArgumentException | IllegalStateException e) { + logger.warn(MessageCodes.EXCEPTION_ERROR, e, + controllerName, this.toString()); + return Response.status(Response.Status.BAD_REQUEST). + entity(new Error(e.getMessage())). + build(); + } + } + + @GET + @Path("engine/controllers/{controllerName}/drools/facts/{sessionName}/{className}") + @Produces(MediaType.APPLICATION_JSON) + public Response droolsFacts(@DefaultValue("false") @QueryParam("count") boolean count, + @PathParam("controllerName") String controllerName, + @PathParam("sessionName") String sessionName, + @PathParam("className") String className) { + try { + DroolsController drools = getDroolsController(controllerName); + List facts = drools.facts(sessionName, className); + if (!count) + return Response.status(Response.Status.OK).entity(facts).build(); + else + return Response.status(Response.Status.OK).entity(facts.size()).build(); + } catch (IllegalArgumentException | IllegalStateException e) { + logger.warn(MessageCodes.EXCEPTION_ERROR, e, + controllerName, this.toString()); + return Response.status(Response.Status.BAD_REQUEST). + entity(new Error(e.getMessage())). + build(); + } + } + + @GET + @Path("engine/controllers/{controllerName}/drools/facts/{sessionName}/{queryName}/{queriedEntity}") + @Produces(MediaType.APPLICATION_JSON) + public Response droolsFacts(@DefaultValue("false") @QueryParam("count") boolean count, + @PathParam("controllerName") String controllerName, + @PathParam("sessionName") String sessionName, + @PathParam("queryName") String queryName, + @PathParam("queriedEntity") String queriedEntity) { + try { + DroolsController drools = getDroolsController(controllerName); + List facts = drools.factQuery(sessionName, queryName, queriedEntity); + if (!count) + return Response.status(Response.Status.OK).entity(facts).build(); + else + return Response.status(Response.Status.OK).entity(facts.size()).build(); + } catch (IllegalArgumentException | IllegalStateException e) { + logger.warn(MessageCodes.EXCEPTION_ERROR, e, + controllerName, this.toString()); + return Response.status(Response.Status.BAD_REQUEST). + entity(new Error(e.getMessage())). + build(); + } } @GET @@ -1134,6 +1212,19 @@ public class RestManager { build(); } + + protected DroolsController getDroolsController(String controllerName) throws IllegalArgumentException { + PolicyController controller = PolicyController.factory.get(controllerName); + if (controller == null) + throw new IllegalArgumentException(controllerName + " does not exist"); + + DroolsController drools = controller.getDrools(); + if (drools == null) + throw new IllegalArgumentException(controllerName + " has no drools configuration"); + + return drools; + } + /* * Helper classes for aggregation of results */ -- cgit 1.2.3-korg