diff options
author | Pamela Dragosh <pdragosh@research.att.com> | 2017-02-14 19:45:48 -0500 |
---|---|---|
committer | Pamela Dragosh <pdragosh@research.att.com> | 2017-02-14 19:46:03 -0500 |
commit | 0e16acf4d8579fd82349d6cd24e236275735a818 (patch) | |
tree | 2c397f9d025dacfb3318d75e8fef9a750f71f76b /policy-core | |
parent | ec6b0922de2f7e9e68ba9586efc9ed2ad75768f8 (diff) |
Initial OpenECOMP policy/drools-pdp commit
Change-Id: I0072ccab6f40ed32da39667f9f8523b6d6dad2e2
Signed-off-by: Pamela Dragosh <pdragosh@research.att.com>
Diffstat (limited to 'policy-core')
13 files changed, 2085 insertions, 0 deletions
diff --git a/policy-core/pom.xml b/policy-core/pom.xml new file mode 100644 index 00000000..3e4bc681 --- /dev/null +++ b/policy-core/pom.xml @@ -0,0 +1,235 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + ============LICENSE_START======================================================= + ECOMP Policy Engine - Drools PDP + ================================================================================ + Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + ================================================================================ + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + ============LICENSE_END========================================================= + --> + +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> + <modelVersion>4.0.0</modelVersion> + + <groupId>org.openecomp.policy.drools-pdp</groupId> + <artifactId>policy-core</artifactId> + <parent> + <groupId>org.openecomp.policy.drools-pdp</groupId> + <artifactId>drools-pdp</artifactId> + <version>1.0.0-SNAPSHOT</version> + </parent> + + <build> + <plugins> + <plugin> + <artifactId>maven-assembly-plugin</artifactId> + <version>2.6</version> + <executions> + <execution> + <id>zipfile</id> + <goals> + <goal>single</goal> + </goals> + <phase>package</phase> + <configuration> + <attach>true</attach> + <finalName>${project.artifactId}-${project.version}</finalName> + <descriptors> + <descriptor>src/assembly/assemble_zip.xml</descriptor> + </descriptors> + <appendAssemblyId>false</appendAssemblyId> + </configuration> + </execution> + </executions> + </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-dependency-plugin</artifactId> + <version>2.8</version> + <executions> + <execution> + <id>copy-dependencies</id> + <goals> + <goal>copy-dependencies</goal> + </goals> + <phase>prepare-package</phase> + <configuration> + <transitive>false</transitive> + <outputDirectory>${project.build.directory}/assembly/lib</outputDirectory> + <overWriteReleases>false</overWriteReleases> + <overWriteSnapshots>true</overWriteSnapshots> + <overWriteIfNewer>true</overWriteIfNewer> + <useRepositoryLayout>false</useRepositoryLayout> + <addParentPoms>false</addParentPoms> + <copyPom>false</copyPom> + <excludeGroupIds>org.opendaylight,com.brocade.odl</excludeGroupIds> + <scope>provided</scope> + </configuration> + </execution> + </executions> + </plugin> + <plugin> + <artifactId>maven-resources-plugin</artifactId> + <version>2.6</version> + <executions> + <execution> + <id>copy-version</id> + <goals> + <goal>copy-resources</goal> + </goals> + <phase>validate</phase> + <configuration> + <outputDirectory>${basedir}/target/versions</outputDirectory> + <resources> + <resource> + <directory>src/main/resources/versions</directory> + <includes> + <include>version.properties</include> + </includes> + <filtering>true</filtering> + </resource> + </resources> + </configuration> + </execution> + <execution> + <id>copy-resources</id> + <goals> + <goal>copy-resources</goal> + </goals> + <phase>validate</phase> + <configuration> + <outputDirectory>${basedir}/target/etc/bvc-extensions</outputDirectory> + <resources> + <resource> + <directory>src/main/resources/etc/bvc-extensions</directory> + <includes> + <include>feature_config_template.cfg</include> + <include>feature_custom.install</include> + </includes> + <filtering>true</filtering> + </resource> + </resources> + </configuration> + </execution> + </executions> + </plugin> + </plugins> + </build> + + <dependencies> + <dependency> + <groupId>log4j</groupId> + <artifactId>log4j</artifactId> + <version>1.2.17</version> + </dependency> + <dependency> + <groupId>org.kie</groupId> + <artifactId>kie-api</artifactId> + <version>6.3.0.Final</version> + </dependency> + <dependency> + <groupId>org.kie</groupId> + <artifactId>kie-ci</artifactId> + <version>6.3.0.Final</version> + <scope>runtime</scope> + </dependency> + <dependency> + <groupId>org.drools</groupId> + <artifactId>drools-core</artifactId> + <version>6.3.0.Final</version> + <scope>runtime</scope> + </dependency> + <dependency> + <groupId>org.drools</groupId> + <artifactId>drools-persistence-jpa</artifactId> + <version>6.3.0.Final</version> + </dependency> + <dependency> + <!-- leave this for now, but will remove policy-utils at the end of conversion --> + <groupId>org.openecomp.policy.drools-pdp</groupId> + <artifactId>policy-utils</artifactId> + <version>1.0.0-SNAPSHOT</version> + </dependency> + <dependency> + <groupId>org.openecomp.policy.common</groupId> + <artifactId>ECOMP-Logging</artifactId> + <version>${common-modules.version}</version> + </dependency> + <dependency> + <groupId>org.openecomp.policy.common</groupId> + <artifactId>integrity-monitor</artifactId> + <version>${common-modules.version}</version> + </dependency> + <dependency> + <groupId>org.openecomp.policy.common</groupId> + <artifactId>integrity-audit</artifactId> + <version>${common-modules.version}</version> + </dependency> + <dependency> + <groupId>org.mariadb.jdbc</groupId> + <artifactId>mariadb-java-client</artifactId> + <version>1.2.3</version> + <scope>runtime</scope> + </dependency> + <dependency> + <groupId>com.h2database</groupId> + <artifactId>h2</artifactId> + <version>[1.4.186,)</version> + <scope>runtime</scope> + </dependency> + <dependency> + <groupId>org.apache.httpcomponents</groupId> + <artifactId>httpcore</artifactId> + <version>4.4.1</version> + </dependency> + <dependency> + <groupId>junit</groupId> + <artifactId>junit</artifactId> + <version>4.11</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.codehaus.btm</groupId> + <artifactId>btm</artifactId> + <version>2.1.4</version> + </dependency> + <dependency> + <groupId>org.eclipse.persistence</groupId> + <artifactId>eclipselink</artifactId> + <version>2.6.2</version> + </dependency> + <dependency> + <groupId>org.hibernate</groupId> + <artifactId>hibernate-entitymanager</artifactId> + <version>5.0.7.Final</version> + </dependency> + + <dependency> + <groupId>org.json</groupId> + <artifactId>json</artifactId> + <version>20160810</version> + </dependency> + </dependencies> + + <dependencyManagement> + <dependencies> + <dependency> + <groupId>org.apache.httpcomponents</groupId> + <artifactId>httpclient</artifactId> + <version>4.5</version> + </dependency> + </dependencies> + </dependencyManagement> +</project> diff --git a/policy-core/src/assembly/assemble_zip.xml b/policy-core/src/assembly/assemble_zip.xml new file mode 100644 index 00000000..447a5271 --- /dev/null +++ b/policy-core/src/assembly/assemble_zip.xml @@ -0,0 +1,85 @@ +<!-- + ============LICENSE_START======================================================= + policy-core + ================================================================================ + Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + ================================================================================ + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + ============LICENSE_END========================================================= + --> + +<!-- Defines how we build the .zip file which is our distribution. --> + +<assembly + xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0 http://maven.apache.org/xsd/assembly-1.1.0.xsd"> + <id>runtime</id> + <formats> + <format>zip</format> + </formats> + + <!-- we want "system" and related files right at the root level as this + file is suppose to be unzip on top of a karaf distro. --> + <includeBaseDirectory>false</includeBaseDirectory> + + <fileSets> + <fileSet> + <directory>target</directory> + <outputDirectory>lib</outputDirectory> + <includes> + <include>policy-core-${project.version}.jar</include> + </includes> + </fileSet> + <fileSet> + <directory>target/assembly/</directory> + <outputDirectory>.</outputDirectory> + <excludes> + </excludes> + </fileSet> + <fileSet> + <directory>.</directory> + <outputDirectory>lib</outputDirectory> + <includes> + <include>*.jar</include> + </includes> + </fileSet> + <fileSet> + <directory>src/main/server-gen/bin</directory> + <outputDirectory>bin</outputDirectory> + <fileMode>0744</fileMode> + <excludes> + </excludes> + </fileSet> + <fileSet> + <directory>src/main/server/bin</directory> + <outputDirectory>bin</outputDirectory> + <fileMode>0744</fileMode> + <excludes> + </excludes> + </fileSet> + <fileSet> + <directory>src/main/server-gen/scripts</directory> + <outputDirectory>scripts</outputDirectory> + </fileSet> + <fileSet> + <directory>src/main/server/scripts</directory> + <outputDirectory>scripts</outputDirectory> + </fileSet> + <fileSet> + <directory>src/main/server/config</directory> + <outputDirectory>config</outputDirectory> + </fileSet> + </fileSets> + +</assembly> diff --git a/policy-core/src/main/java/org/openecomp/policy/drools/core/FeatureAPI.java b/policy-core/src/main/java/org/openecomp/policy/drools/core/FeatureAPI.java new file mode 100644 index 00000000..a14c6547 --- /dev/null +++ b/policy-core/src/main/java/org/openecomp/policy/drools/core/FeatureAPI.java @@ -0,0 +1,153 @@ +/*- + * ============LICENSE_START======================================================= + * policy-core + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.policy.drools.core; + +import java.util.Properties; + +import org.kie.api.runtime.KieSession; + +import org.openecomp.policy.drools.utils.OrderedService; +import org.openecomp.policy.drools.utils.OrderedServiceImpl; + +/** + * This interface provides a way to invoke optional features at various + * points in the code. At appropriate points in the + * application, the code iterates through this list, invoking these optional + * methods. Most of the methods here are notification only -- these tend to + * return a 'void' value. In other cases, such as 'activatePolicySession', + * may + */ +public interface FeatureAPI extends OrderedService +{ + /** + * 'FeatureAPI.impl.getList()' returns an ordered list of objects + * implementing the 'FeatureAPI' interface. + */ + static public OrderedServiceImpl<FeatureAPI> impl = + new OrderedServiceImpl<FeatureAPI>(FeatureAPI.class); + + /** + * This method is called during initialization at a point right after + * 'PolicyContainer' initialization has completed. + * + * @param args standard 'main' arguments, which are currently ignored + * @param configDir the relative directory containing configuration files + */ + public void globalInit(String args[], String configDir); + + /** + * This method is used to create a 'KieSession' as part of a + * 'PolicyContainer'. The caller of this method will iterate over the + * implementers of this interface until one returns a non-null value. + * + * @param policyContainer the 'PolicyContainer' instance containing this + * session + * @param name the name of the KieSession (which is also the name of + * the associated PolicySession) + * @param kieBaseName the name of the 'KieBase' instance containing + * this session + * @return a new KieSession, if one was created, or 'null' if not + * (this depends on the capabilities and state of the object implementing + * this interface) + */ + public KieSession activatePolicySession + (PolicyContainer policyContainer, String name, String kieBaseName); + + /** + * This method is called after 'KieSession.dispose()' is called + * + * @param policySession the 'PolicySession' object that wrapped the + * 'KieSession' + */ + public void disposeKieSession(PolicySession policySession); + + /** + * This method is called after 'KieSession.destroy()' is called + * + * @param policySession the 'PolicySession' object that wrapped the + * 'KieSession' + */ + public void destroyKieSession(PolicySession policySession); + + /** + * called before the Policy Engine is started + */ + public void beforeStartEngine() throws IllegalStateException; + + /** + * called immediately after the Policy Engine is started + */ + public void afterStartEngine(); + + /** + * called before the Policy Engine is shut down + */ + public void beforeShutdownEngine(); + + /** + * called after the Policy Engine is shut down + */ + public void afterShutdownEngine(); + + /** + * called before creating a controller with name 'name' + * + * @param name name of the the controller + * @param properties configuration properties + */ + public void beforeCreateController(String name, Properties properties); + + /** + * NOTE: temporary, should pass the Policy Controller already created + * + * called after creating a controller with name 'name' + * + * @param name name of the the controller + * @param properties configuration properties + */ + public void afterCreateController(String name); + + /** + * NOTE: temporary, should pass the Policy Controller + * + * called before starting a controller with name 'name' + * + * @param name name of the the controller + */ + public void beforeStartController(String name); + + /** + * NOTE: temporary, should pass the Policy Controller + * + * called after starting a controller with name 'name' + * + * @param name name of the the controller + */ + public void afterStartController(String name); + + /** + * NOTE: this method is probably temporary + * + * @return 'true' if persistence is enabled, and 'false' if not, or if + * this feature is not related to persistence. + */ + public boolean isPersistenceEnabled(); +} diff --git a/policy-core/src/main/java/org/openecomp/policy/drools/core/PolicyContainer.java b/policy-core/src/main/java/org/openecomp/policy/drools/core/PolicyContainer.java new file mode 100644 index 00000000..ae7cd622 --- /dev/null +++ b/policy-core/src/main/java/org/openecomp/policy/drools/core/PolicyContainer.java @@ -0,0 +1,828 @@ +/*- + * ============LICENSE_START======================================================= + * policy-core + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.policy.drools.core; + +import java.io.IOException; +import java.util.Collection; +import java.util.Date; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Properties; +import java.util.concurrent.ConcurrentHashMap; + +import javax.persistence.EntityManagerFactory; +import javax.persistence.Persistence; + +import org.eclipse.persistence.config.PersistenceUnitProperties; +import org.kie.api.KieBase; +import org.kie.api.KieServices; +import org.kie.api.builder.KieScanner; +import org.kie.api.builder.Message; +import org.kie.api.builder.ReleaseId; +import org.kie.api.builder.Results; +import org.kie.api.runtime.Environment; +import org.kie.api.runtime.EnvironmentName; +import org.kie.api.runtime.KieContainer; +import org.kie.api.runtime.KieSession; +import org.kie.api.runtime.KieSessionConfiguration; + +import bitronix.tm.Configuration; +import bitronix.tm.TransactionManagerServices; +import bitronix.tm.resource.jdbc.PoolingDataSource; + +import org.openecomp.policy.common.ia.IntegrityAudit; +import org.openecomp.policy.common.ia.IntegrityAuditProperties; +import org.openecomp.policy.drools.properties.Startable; +import org.openecomp.policy.common.logging.flexlogger.FlexLogger; +import org.openecomp.policy.common.logging.flexlogger.Logger; +import org.openecomp.policy.common.logging.eelf.MessageCodes; +import org.openecomp.policy.common.logging.eelf.PolicyLogger; +import org.openecomp.policy.common.logging.flexlogger.PropertyUtil; + +/** + * This class is a wrapper around 'KieContainer', which adds the ability + * to automatically create and track KieSession instances. + */ +public class PolicyContainer implements Startable +{ + // get an instance of logger + private static Logger logger = FlexLogger.getLogger(PolicyContainer.class); + // 'KieServices' singleton + static private KieServices kieServices = KieServices.Factory.get(); + + // set of all 'PolicyContainer' instances + static private HashSet<PolicyContainer> containers = + new HashSet<PolicyContainer>(); + + // maps feature objects to per-PolicyContainer data + private ConcurrentHashMap<Object, Object> adjuncts = + new ConcurrentHashMap<Object, Object>(); + + // 'KieContainer' associated with this 'PolicyContainer' + private KieContainer kieContainer; + + // indicates whether the PolicyContainer is 'started' + // (started = sessions created, threads running) + private volatile boolean isStarted = false; + + // maps session name into the associated 'PolicySession' instance + private HashMap<String, PolicySession> sessions = + new HashMap<String, PolicySession>(); + + // if not null, this is a 'KieScanner' looking for updates + private KieScanner scanner = null; + + // indicates whether the scanner has been started + // (it can block for a long time) + private boolean scannerStarted = false; + + // Used to set relative pathing to config files for unit test environment + public static boolean isUnitTesting = false; + + /** + * uses 'groupId', 'artifactId' and 'version', and fetches the associated + * artifact and remaining dependencies from the Maven repository to create + * the 'PolicyContainer' and associated 'KieContainer'. + * + * An exception occurs if the creation of the 'KieContainer' fails. + * + * @param groupId the 'groupId' associated with the artifact + * @param artifactId the artifact name + * @param version a comma-separated list of possible versions + */ + public PolicyContainer(String groupId, String artifactId, String version) + { + this(kieServices.newReleaseId(groupId, artifactId, version)); + } + + /** + * uses the 'groupId', 'artifactId' and 'version' information in 'ReleaseId', + * and fetches the associated artifact and remaining dependencies from the + * Maven repository to create the 'PolicyContainer' and associated + * 'KieContainer'. + * + * An exception occurs if the creation of the 'KieContainer' fails. + * + * @param releaseId indicates the artifact that is to be installed in this + * container + */ + public PolicyContainer(ReleaseId releaseId) + { + if (releaseId.getVersion().contains(",")) + { + // this is actually a comma-separated list of release ids + releaseId = loadArtifact(releaseId.getGroupId(), + releaseId.getArtifactId(), + releaseId.getVersion()); + } + else + { + kieContainer = kieServices.newKieContainer(releaseId); + } + synchronized(containers) + { + if(releaseId != null){ + logger.info("Add a new kieContainer in containers: releaseId: " + releaseId.toString()); + }else{ + logger.warn("input releaseId is null"); + } + containers.add(this); + } + startScanner(releaseId); + } + + /** + * Load an artifact into a new KieContainer. This method handles the + * case where the 'version' is actually a comma-separated list of + * versions. + * + * @param groupId the 'groupId' associated with the artifact + * @param artifactId the artifact name + * @param version a comma-separated list of possible versions + */ + private ReleaseId loadArtifact + (String groupId, String artifactId, String version) + { + String[] versions = version.split(","); + if (versions.length > 1) + { + logger.info("Multiple KieContainer versions are specified: " + + version); + } + + // indicates a 'newKieContainer' call failed + RuntimeException exception = null; + + // set prior to every 'newKieContainer' invocation + // (if we are able to create the container, it will be the last + // one that was successful) + ReleaseId releaseId = null; + for (String ver : versions) + { + try + { + // Create a 'ReleaseId' object describing the artifact, and + // create a 'KieContainer' based upon it. + logger.info("Create new KieContainer start, version = " + + ver + " ..."); + + releaseId = kieServices.newReleaseId(groupId, artifactId, ver); + kieContainer = kieServices.newKieContainer(releaseId); + + // clear any exception, and break out of the loop + exception = null; + break; + } + catch (RuntimeException e) + { + exception = e; + } + } + if (exception != null) + { + // all of the 'newKieContainer' invocations failed -- throw the + // most recent exception + throw(exception); + } + return(releaseId); + } + + /** + * @return the name of the container, which is the String equivalent of + * the 'ReleaseId'. It has the form: + * + * (groupId + ":" + artifactId + ":" + version) + * + * Note that the name changes after a successful call to 'updateToVersion', + * although typically only the 'version' part changes. + */ + public String getName() + { + return(kieContainer.getReleaseId().toString()); + } + + /** + * @return the associated 'KieContainer' instance + */ + public KieContainer getKieContainer() + { + return(kieContainer); + } + + /** + * @return the 'ClassLoader' associated with the 'KieContainer' instance + */ + public ClassLoader getClassLoader() + { + return(kieContainer.getClassLoader()); + } + + /** + * @return the Maven GroupId of the top-level artifact wrapped + * by the container. + */ + public String getGroupId() + { + return(kieContainer.getReleaseId().getGroupId()); + } + + /** + * @return the Maven ArtifactId of the top-level artifact wrapped + * by the container. + */ + public String getArtifactId() + { + return(kieContainer.getReleaseId().getArtifactId()); + } + + /** + * @return the version of the top-level artifact wrapped by the + * container (this may change as updates occur) + */ + public String getVersion() + { + return(kieContainer.getReleaseId().getVersion()); + } + + /** + * Fetch the named 'PolicySession'. + * + * @param name the name of the KieSession (which is also the name of + * the associated PolicySession) + * @return a PolicySession if found, 'null' if not + */ + public PolicySession getPolicySession(String name) + { + return(sessions.get(name)); + } + + /** + * Internal method to create a PolicySession, possibly restoring it + * from persistent storage. + * + * @param name of the KieSession and PolicySession + * @param kieBaseName name of the associated 'KieBase' instance + * @return a new or existing PolicySession, or 'null' if not found + */ + private PolicySession activatePolicySession(String name, String kieBaseName) + { + synchronized(sessions) + { + logger.info("activatePolicySession:name :" + name); + PolicySession session = sessions.get(name); + if (session == null) + { + KieSession kieSession = null; + + // loop through all of the features, and give each one + // a chance to create the 'KieSession' + for (FeatureAPI feature : FeatureAPI.impl.getList()) + { + if ((kieSession = feature.activatePolicySession + (this, name, kieBaseName)) != null) + break; + } + + // if none of the features created the session, create one now + if (kieSession == null) + { + kieSession = kieContainer.newKieSession(name); + } + + if (kieSession != null) + { + // creation of 'KieSession' was successful - build + // a PolicySession + session = new PolicySession(name, this, kieSession); + sessions.put(name, session); + logger.info("activatePolicySession:new session was added in sessions with name " + name); + } + } + logger.info("activatePolicySession:session - " + + (session == null ? "null" : session.getFullName()) + + " is returned."); + return(session); + } + } + + /** + * This creates a 'PolicySession' instance within this 'PolicyContainer', + * and ties it to the specified 'KieSession'. 'name' must not currently + * exist within the 'PolicyContainer', and the 'KieBase' object associated + * with 'KieSession' must belong to the 'KieContainer'. This method provides + * a way for 'KieSession' instances that are created programmatically to fit + * into this framework. + * + * @param name the name for the new 'PolicySession' + * @param kieSession a 'KieSession' instance, that will be included in + * this infrastructure + * @return the new 'PolicySession' + * @throws IllegalArgumentException if 'kieSession' does not reside within + * this container + * @throws IllegalStateException if a 'PolicySession' already exists + * with this name + */ + public PolicySession adoptKieSession(String name, KieSession kieSession) + throws IllegalArgumentException, IllegalStateException + { + + if(name == null){ + logger.warn("adoptKieSession:input name is null"); + }else if(kieSession == null){ + logger.warn("adoptKieSession:input kieSession is null"); + }else { + logger.info("adoptKieSession:name: " + name + " kieSession: " + kieSession); + } + // fetch KieBase, and verify it belongs to this KieContainer + boolean match = false; + KieBase kieBase = kieSession.getKieBase(); + logger.info("adoptKieSession:kieBase: " + kieBase); + for (String kieBaseName : kieContainer.getKieBaseNames()) + { + logger.info("adoptKieSession:kieBaseName: " + kieBaseName); + if (kieBase == kieContainer.getKieBase(kieBaseName)) + { + match = true; + break; + } + } + logger.info("adoptKieSession:match " + match); + // if we don't have a match yet, the last chance is to look at the + // default KieBase, if it exists + if (!match && kieBase != kieContainer.getKieBase()) + { + throw(new IllegalArgumentException + ("KieSession '" + name + "' does not reside within container " + + getName())); + } + + synchronized (sessions) + { + if (sessions.get(name) != null) + { + throw(new IllegalStateException + ("PolicySession '" + name + "' already exists")); + } + + // create the new 'PolicySession', add it to the table, + // and return the object to the caller + logger.info("adoptKieSession:create a new policySession with name " + name); + PolicySession policySession = + new PolicySession(name, this, kieSession); + sessions.put(name, policySession); + return(policySession); + } + } + + /** + * This call 'KieContainer.updateToVersion()', and returns the associated + * response as a String. If successful, the name of this 'PolicyContainer' + * changes to match the new version. + * + * @param newVersion this is the version to update to (the 'groupId' + * and 'artifactId' remain the same) + * @return the list of messages associated with the update (not sure if + * this can be 'null', or how to determine success/failure) + */ + public String updateToVersion(String newVersion) + { + ReleaseId releaseId = kieContainer.getReleaseId(); + Results results = this.updateToVersion + (kieServices.newReleaseId(releaseId.getGroupId(), + releaseId.getArtifactId(), + newVersion)); + + List<Message> messages = (results == null ? null : results.getMessages()); + return(messages == null ? null : messages.toString()); + } + + /** + * This calls 'KieContainer.updateToVersion()', and returns the associated + * response. If successful, the name of this 'PolicyContainer' changes to + * match the new version. + * + * @param releaseId the new artifact (usually new version) to be installed + * @return the 'Results' parameter from 'KieContainer.updateToVersion' + */ + public Results updateToVersion(ReleaseId releaseId) + { + if(releaseId == null){ + logger.warn("updateToVersion:input releaseId is null"); + }else { + logger.info("updateToVersion:releaseId " + releaseId.toString()); + } + return(kieContainer.updateToVersion(releaseId)); + } + + /** + * @return all existing 'PolicyContainer' instances + */ + public static Collection<PolicyContainer> getPolicyContainers() + { + synchronized(containers) + { + return(new HashSet<PolicyContainer>(containers)); + } + } + + /** + * @return all of the 'PolicySession' instances + */ + public Collection<PolicySession> getPolicySessions() + { + // KLUDGE WARNING: this is a temporary workaround -- if there are + // no features, we don't have persistence, and 'activate' is never + // called. In this case, make sure the container is started. + if (FeatureAPI.impl.getList().size() == 0) + { + start(); + } + + // return current set of PolicySessions + synchronized(sessions) + { + return(new HashSet<PolicySession>(sessions.values())); + } + } + + /** + * This method will start a 'KieScanner' (if not currently running), + * provided that the ReleaseId version is 'LATEST' or 'RELEASE', + * or refers to a SNAPSHOT version. + * + * @param releaseId the release id used to create the container + */ + public synchronized void startScanner(ReleaseId releaseId) + { + String version = releaseId.getVersion(); + if (scannerStarted == false && scanner == null && version != null + && (version.equals("LATEST") || version.equals("RELEASE") + || version.endsWith("-SNAPSHOT"))) + { + // create the scanner, and poll at 60 second intervals + try + { + scannerStarted = true; + + // start this in a separate thread -- it can block for a long time + new Thread("Scanner Starter " + getName()) + { + public void run() + { + scanner = kieServices.newKieScanner(kieContainer); + scanner.start(60000L); + } + }.start(); + } + catch (Exception e) + { + // sometimes the scanner initialization fails for some reason + logger.error(MessageCodes.EXCEPTION_ERROR, e, "main", "startServer"); + } + } + } + + /** + * Insert a fact into a specific named session + * + * @param name this is the session name + * @param object this is the fact to be inserted into the session + * @return 'true' if the named session was found, 'false' if not + */ + public boolean insert(String name, Object object) + { + // TODO: Should the definition of 'name' be expanded to include an + // alternate entry point as well? For example, 'name.entryPoint' (or + // something other than '.' if that is a problem). + synchronized (sessions) + { + PolicySession session = sessions.get(name); + if (session != null) + { + session.getKieSession().insert(object); + return(true); + } + } + return(false); + } + + /** + * Insert a fact into all sessions associated with this container + * + * @param object this is the fact to be inserted into the sessions + * @return 'true' if the fact was inserted into at least one session, + * 'false' if not + */ + public boolean insertAll(Object object) + { + boolean rval = false; + synchronized (sessions) + { + for (PolicySession session : sessions.values()) + { + session.getKieSession().insert(object); + rval = true; + } + } + return(rval); + } + + /*************************/ + /* 'Startable' interface */ + /*************************/ + + /** + * {@inheritDoc} + */ + public synchronized boolean start() + { + if (!isStarted) + { + // This will create all 'PolicySession' instances specified in the + // 'kmodule.xml' file that don't exist yet + for (String kieBaseName : kieContainer.getKieBaseNames()) + { + for (String kieSessionName : + kieContainer.getKieSessionNamesInKieBase(kieBaseName)) + { + // if the 'PolicySession' does not currently exist, this method + // call will attempt to create it + PolicySession session = + activatePolicySession(kieSessionName, kieBaseName); + if (session != null) + { + session.startThread(); + } + } + } + isStarted = true; + } + return(true); + } + + /** + * {@inheritDoc} + */ + public synchronized boolean stop() + { + if (isStarted) + { + Collection<PolicySession> localSessions; + + synchronized (sessions) + { + // local set containing all of the sessions + localSessions = new HashSet<PolicySession>(sessions.values()); + + // clear the 'name->session' map in 'PolicyContainer' + sessions.clear(); + } + for (PolicySession session : localSessions) + { + // stop session thread + session.stopThread(); + + // free KieSession resources + session.getKieSession().dispose(); + + // notify features + for (FeatureAPI feature : FeatureAPI.impl.getList()) + { + feature.disposeKieSession(session); + } + } + isStarted = false; + } + return(true); + } + + /** + * {@inheritDoc} + */ + public synchronized void shutdown() + { + // Note that this method does not call 'destroy' on the 'KieSession' + // instances, which would remove any associated information in persistent + // storage. Should it do this? + + stop(); + synchronized(containers) + { + containers.remove(this); + } + + // How do we free the resources associated with the KieContainer? + // Is garbage collection sufficient? + } + + /** + * {@inheritDoc} + */ + public boolean isAlive() + { + return(isStarted); + } + + /*************************/ + + /** + * This method is similar to 'shutdown', but it also frees any persistence + * resources as well. + */ + public synchronized void destroy() + { + // we need all KieSession instances running in order to free + // resources associated with persistence + start(); + Collection<PolicySession> localSessions; + + synchronized (sessions) + { + // local set containing all of the sessions + localSessions = new HashSet<PolicySession>(sessions.values()); + + // clear the 'name->session' map in 'PolicyContainer' + sessions.clear(); + } + for (PolicySession session : localSessions) + { + // stop session thread + session.stopThread(); + + // free KieSession resources + session.getKieSession().destroy(); + + // notify features + for (FeatureAPI feature : FeatureAPI.impl.getList()) + { + feature.destroyKieSession(session); + } + } + isStarted = false; + + synchronized(containers) + { + containers.remove(this); + } + + // How do we free the resources associated with the KieContainer? + // Is garbage collection sufficient? + } + + /** + * This method is called when the host goes from the 'standby->active' state. + */ + static public void activate() + { + // start all of the 'PolicyContainer' instances + for (PolicyContainer container : containers) + { + try + { + container.start(); + } + catch (Exception e) + { + e.printStackTrace(); + logger.error(MessageCodes.EXCEPTION_ERROR, e, + "activate", + "PolicyContainer.start()"); + } + } + } + + /** + * This method is called when the host goes from the 'active->standby' state. + */ + static public void deactivate() + { + // deactivate all of the 'PolicyContainer' instances + for (PolicyContainer container : containers) + { + try + { + container.stop(); + } + catch (Exception e) + { + e.printStackTrace(); + logger.error(MessageCodes.EXCEPTION_ERROR, e, + "deactivate", + "PolicyContainer.stop()"); + } + } + } + + /** + * This method does the following: + * + * 1) Initializes logging + * 2) Starts the DroolsPDP Integrity Monitor + * 3) Initilaizes persistence + * + * It no longer reads in properties files, o creates 'PolicyContainer' + * instances. + * + * @param args standard 'main' arguments, which are currently ignored + */ + public static void globalInit(String args[]) + { + + /* + * When JUnit testing, working directory should be + * "../policy-management". In test environment, command line argument + * should specify the relative path from this directory to the config + * directory ("src/test/server/config") + */ + String configDir = "config"; + if (isUnitTesting) { + configDir = "src/test/server/config"; + } + System.out.println("PolicyContainer.main: configDir=" + configDir); + + logger.info("Calling initlogger"); + + initlogger(configDir); + logger.info("initlogger returned"); + + // invoke 'globalInit' on all of the features + for (FeatureAPI feature : FeatureAPI.impl.getList()) + { + feature.globalInit(args, configDir); + } + } + + /** + * Read in the logger properties + */ + private static void initlogger(String configDir){ + try { + Properties properties = + PropertyUtil.getProperties(configDir + "/policyLogger.properties"); + try { + + PolicyLogger.init(properties); + + } catch (Exception e) { + logger.error(MessageCodes.MISS_PROPERTY_ERROR, e, "initlogger"); + } + } catch (IOException e1) { + logger.error(MessageCodes.MISS_PROPERTY_ERROR, e1, "initlogger"); + } + } + + /** + * Fetch the adjunct object associated with a given feature + * + * @param object this is typically the singleton feature object that is + * used as a key, but it might also be useful to use nested objects + * within the feature as keys. + * @return a feature-specific object associated with the key, or 'null' + * if it is not found. + */ + public Object getAdjunct(Object object) + { + return(adjuncts.get(object)); + } + + /** + * Store the adjunct object associated with a given feature + * + * @param object this is typically the singleton feature object that is + * used as a key, but it might also be useful to use nested objects + * within the feature as keys. + * @param value a feature-specific object associated with the key, or 'null' + * if the feature-specific object should be removed + */ + public void setAdjunct(Object object, Object value) + { + if (value == null) + { + adjuncts.remove(object); + } + else + { + adjuncts.put(object, value); + } + } +} diff --git a/policy-core/src/main/java/org/openecomp/policy/drools/core/PolicySession.java b/policy-core/src/main/java/org/openecomp/policy/drools/core/PolicySession.java new file mode 100644 index 00000000..89341d6b --- /dev/null +++ b/policy-core/src/main/java/org/openecomp/policy/drools/core/PolicySession.java @@ -0,0 +1,349 @@ +/*- + * ============LICENSE_START======================================================= + * policy-core + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.policy.drools.core; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.util.Properties; + +import org.kie.api.runtime.KieSession; +import org.kie.api.event.rule.AfterMatchFiredEvent; +import org.kie.api.event.rule.AgendaEventListener; +import org.kie.api.event.rule.AgendaGroupPoppedEvent; +import org.kie.api.event.rule.AgendaGroupPushedEvent; +import org.kie.api.event.rule.BeforeMatchFiredEvent; +import org.kie.api.event.rule.MatchCancelledEvent; +import org.kie.api.event.rule.MatchCreatedEvent; +import org.kie.api.event.rule.ObjectDeletedEvent; +import org.kie.api.event.rule.ObjectInsertedEvent; +import org.kie.api.event.rule.ObjectUpdatedEvent; +import org.kie.api.event.rule.RuleRuntimeEventListener; +import org.kie.api.event.rule.RuleFlowGroupActivatedEvent; +import org.kie.api.event.rule.RuleFlowGroupDeactivatedEvent; + +import org.openecomp.policy.drools.core.jmx.PdpJmx; +import org.openecomp.policy.common.logging.flexlogger.FlexLogger; +import org.openecomp.policy.common.logging.flexlogger.Logger; +import org.openecomp.policy.common.logging.eelf.MessageCodes; + +/** + * This class is a wrapper around 'KieSession', which adds the following: + * + * 1) A thread running 'KieSession.fireUntilHalt()' + * 2) Access to UEB + * 3) Logging of events + */ +public class PolicySession + implements AgendaEventListener, RuleRuntimeEventListener +{ + // get an instance of logger + private static Logger logger = FlexLogger.getLogger(PolicySession.class); + // name of the 'PolicySession' and associated 'KieSession' + private String name; + + // the associated 'PolicyContainer', which may have additional + // 'PolicySession' instances in addition to this one + private PolicyContainer container; + + // associated 'KieSession' instance + private KieSession kieSession; + + // if not 'null', this is the thread running 'kieSession.fireUntilHalt()' + private Thread thread = null; + + // supports 'getCurrentSession()' method + static private ThreadLocal<PolicySession> policySession = + new ThreadLocal<PolicySession>(); + + /** + * Internal constructor - create a 'PolicySession' instance + * + * @param name the name of this 'PolicySession' (and 'kieSession') + * @param container the 'PolicyContainer' instance containing this session + * @param kieSession the associated 'KieSession' instance + */ + protected PolicySession(String name, + PolicyContainer container, KieSession kieSession) + { + this.name = name; + this.container = container; + this.kieSession = kieSession; + kieSession.addEventListener((AgendaEventListener)this); + kieSession.addEventListener((RuleRuntimeEventListener)this); + } + + /** + * @return the 'PolicyContainer' object containing this session + */ + public PolicyContainer getPolicyContainer() + { + return(container); + } + + /** + * @return the associated 'KieSession' instance + */ + public KieSession getKieSession() + { + return(kieSession); + } + + /** + * @return the local name of this session, which should either match the + * name specified in 'kmodule.xml' file associated with this session, or the + * name passed on the 'PolicyContainer.adoptKieSession' method. + */ + public String getName() + { + return(name); + } + + /** + * @return the 'PolicyContainer' name, followed by ':', followed by the + * local name of the session. It should be useful in log messages. + */ + public String getFullName() + { + return(container.getName() + ":" + name); + } + + /** + * this starts a separate thread, which invokes 'KieSession.fireUntilHalt()'. + * It does nothing if the thread already exists. + */ + public synchronized void startThread() + { + if (thread == null) + { + logger.info("startThread with name " + getFullName()); + thread = new Thread("Session " + getFullName()) + { + public void run() + { + // set thread local variable + policySession.set(PolicySession.this); + + // We want to continue, despite any exceptions that occur + // while rules are fired. + boolean repeat = true; + while (repeat) + { + if(this.isInterrupted()){ + break; + } + try + { + kieSession.fireAllRules(); + + } + catch (Throwable e) + { + logger.error(MessageCodes.EXCEPTION_ERROR, e, "startThread", "kieSession.fireUntilHalt"); + } + try { + Thread.sleep(5000); + } catch (InterruptedException e) { + break; + } + } + logger.info("fireUntilHalt() returned"); + } + }; + thread.start(); + } + } + + /** + * if a thread is currently running, this invokes 'KieSession.halt()' to + * stop it. + */ + public synchronized void stopThread() + { + if (thread != null) + { + // this should cause the thread to exit + thread.interrupt(); + try + { + // wait for the thread to stop + thread.join(); + } + catch (Exception e) + { + logger.error(MessageCodes.EXCEPTION_ERROR, e, "stopThread", "thread.join"); + } + thread = null; + } + } + + /** + * @return the 'PolicySession' instance associated with the current thread + * (Note that this only works if the current thread is the one running + * 'kieSession.fireUntilHalt()'.) + */ + public static PolicySession getCurrentSession() + { + return(policySession.get()); + } + + /***********************************/ + /* 'AgendaEventListener' interface */ + /***********************************/ + + /** + * {@inheritDoc} + */ + @Override + public void afterMatchFired(AfterMatchFiredEvent event) + { + logger.debug("afterMatchFired: " + getFullName() + + ": AgendaEventListener.afterMatchFired(" + event + ")"); + PdpJmx.getInstance().ruleFired(); + } + + /** + * {@inheritDoc} + */ + @Override + public void afterRuleFlowGroupActivated(RuleFlowGroupActivatedEvent event) + { + logger.debug("afterRuleFlowGroupActivated: " + getFullName() + + ": AgendaEventListener.afterRuleFlowGroupActivated(" + event + ")"); + } + + /** + * {@inheritDoc} + */ + @Override + public void afterRuleFlowGroupDeactivated + (RuleFlowGroupDeactivatedEvent event) + { + logger.debug("afterRuleFlowGroupDeactivated: " + getFullName() + + ": AgendaEventListener.afterRuleFlowGroupDeactivated(" + event + ")"); + } + + /** + * {@inheritDoc} + */ + @Override + public void agendaGroupPopped(AgendaGroupPoppedEvent event) + { + logger.debug("agendaGroupPopped: " + getFullName() + + ": AgendaEventListener.agendaGroupPopped(" + event + ")"); + } + + /** + * {@inheritDoc} + */ + @Override + public void agendaGroupPushed(AgendaGroupPushedEvent event) + { + logger.debug("agendaGroupPushed: " + getFullName() + + ": AgendaEventListener.agendaGroupPushed(" + event + ")"); + } + + /** + * {@inheritDoc} + */ + @Override + public void beforeMatchFired(BeforeMatchFiredEvent event) + { + logger.debug("beforeMatchFired: " + getFullName() + + ": AgendaEventListener.beforeMatchFired(" + event + ")"); + } + + /** + * {@inheritDoc} + */ + @Override + public void beforeRuleFlowGroupActivated + (RuleFlowGroupActivatedEvent event) + { + logger.debug("beforeRuleFlowGroupActivated: " + getFullName() + + ": AgendaEventListener.beforeRuleFlowGroupActivated(" + event + ")"); + } + + /** + * {@inheritDoc} + */ + @Override + public void beforeRuleFlowGroupDeactivated + (RuleFlowGroupDeactivatedEvent event) + { + logger.debug("beforeRuleFlowGroupDeactivated: " + getFullName() + + ": AgendaEventListener.beforeRuleFlowGroupDeactivated(" + event + ")"); + } + + /** + * {@inheritDoc} + */ + @Override + public void matchCancelled(MatchCancelledEvent event) + { + logger.debug("matchCancelled: " + getFullName() + + ": AgendaEventListener.matchCancelled(" + event + ")"); + } + + /** + * {@inheritDoc} + */ + @Override + public void matchCreated(MatchCreatedEvent event) + { + logger.debug("matchCreated: " + getFullName() + + ": AgendaEventListener.matchCreated(" + event + ")"); + } + + /****************************************/ + /* 'RuleRuntimeEventListener' interface */ + /****************************************/ + + /** + * {@inheritDoc} + */ + @Override + public void objectDeleted(ObjectDeletedEvent event) + { + logger.debug("objectDeleted: " + getFullName() + + ": AgendaEventListener.objectDeleted(" + event + ")"); + } + + /** + * {@inheritDoc} + */ + @Override + public void objectInserted(ObjectInsertedEvent event) + { + logger.debug("objectInserted: " + getFullName() + + ": AgendaEventListener.objectInserted(" + event + ")"); + } + + /** + * {@inheritDoc} + */ + @Override + public void objectUpdated(ObjectUpdatedEvent event) + { + logger.debug("objectUpdated: " + getFullName() + + ": AgendaEventListener.objectUpdated(" + event + ")"); + } +} diff --git a/policy-core/src/main/java/org/openecomp/policy/drools/core/jmx/PdpJmx.java b/policy-core/src/main/java/org/openecomp/policy/drools/core/jmx/PdpJmx.java new file mode 100644 index 00000000..7fa0dd0a --- /dev/null +++ b/policy-core/src/main/java/org/openecomp/policy/drools/core/jmx/PdpJmx.java @@ -0,0 +1,47 @@ +/*- + * ============LICENSE_START======================================================= + * policy-core + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.policy.drools.core.jmx; + +import java.util.concurrent.atomic.AtomicLong; + +public class PdpJmx implements PdpJmxMBean { + + private static PdpJmx instance = new PdpJmx(); + private final AtomicLong updates = new AtomicLong(); + private final AtomicLong actions = new AtomicLong(); + + public static PdpJmx getInstance() { + return instance; + } + + public long getUpdates(){ + return updates.longValue(); + } + public long getRulesFired(){ + return actions.longValue(); + } + public void updateOccured(){ + updates.incrementAndGet(); + } + public void ruleFired(){ + actions.incrementAndGet(); + } +} diff --git a/policy-core/src/main/java/org/openecomp/policy/drools/core/jmx/PdpJmxListener.java b/policy-core/src/main/java/org/openecomp/policy/drools/core/jmx/PdpJmxListener.java new file mode 100644 index 00000000..4b48da07 --- /dev/null +++ b/policy-core/src/main/java/org/openecomp/policy/drools/core/jmx/PdpJmxListener.java @@ -0,0 +1,64 @@ +/*- + * ============LICENSE_START======================================================= + * policy-core + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.policy.drools.core.jmx; + +import java.lang.management.ManagementFactory; + +import javax.management.InstanceAlreadyExistsException; +import javax.management.InstanceNotFoundException; +import javax.management.MBeanRegistrationException; +import javax.management.MBeanServer; +import javax.management.MalformedObjectNameException; +import javax.management.NotCompliantMBeanException; +import javax.management.ObjectName; + +import org.openecomp.policy.common.logging.flexlogger.FlexLogger; +import org.openecomp.policy.common.logging.flexlogger.Logger; +import org.openecomp.policy.common.logging.eelf.MessageCodes; + +public class PdpJmxListener { + + public static final Logger logger = FlexLogger.getLogger(PdpJmxListener.class); + + public static void stop() { + final MBeanServer server = ManagementFactory.getPlatformMBeanServer(); + try { + server.unregisterMBean(new ObjectName("PolicyEngine:type=PdpJmx")); + } catch (MBeanRegistrationException | InstanceNotFoundException + | MalformedObjectNameException e) { + logger.error(MessageCodes.EXCEPTION_ERROR, e, "PdpJmxListener.stop()", "Could not unregister PolicyEngine:type=PdpJmx MBean with the MBean server"); + } + + } + + + public static void start() { + final MBeanServer server = ManagementFactory.getPlatformMBeanServer(); + try { + server.registerMBean(PdpJmx.getInstance(), new ObjectName("PolicyEngine:type=PdpJmx")); + } catch (InstanceAlreadyExistsException | MBeanRegistrationException + | NotCompliantMBeanException | MalformedObjectNameException e) { + logger.error(MessageCodes.EXCEPTION_ERROR, e, "PdpJmxListener.start()", "Could not register PolicyEngine:type=PdpJmx MBean with the MBean server"); + } + + } + +} diff --git a/policy-core/src/main/java/org/openecomp/policy/drools/core/jmx/PdpJmxMBean.java b/policy-core/src/main/java/org/openecomp/policy/drools/core/jmx/PdpJmxMBean.java new file mode 100644 index 00000000..a947e82b --- /dev/null +++ b/policy-core/src/main/java/org/openecomp/policy/drools/core/jmx/PdpJmxMBean.java @@ -0,0 +1,27 @@ +/*- + * ============LICENSE_START======================================================= + * policy-core + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.policy.drools.core.jmx; + +public interface PdpJmxMBean { + + public long getRulesFired(); + public long getUpdates(); +} diff --git a/policy-core/src/main/java/org/openecomp/policy/drools/properties/Lockable.java b/policy-core/src/main/java/org/openecomp/policy/drools/properties/Lockable.java new file mode 100644 index 00000000..fd8681c3 --- /dev/null +++ b/policy-core/src/main/java/org/openecomp/policy/drools/properties/Lockable.java @@ -0,0 +1,45 @@ +/*- + * ============LICENSE_START======================================================= + * policy-core + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.policy.drools.properties; + +/** + * Marks a entity as able to lock and unlock. + */ +public interface Lockable { + + /** + * locks this entity + * @return true is the lock operation was successful, false otherwise + */ + public boolean lock(); + + /** + * unlocks this entity + * @return true is the unlock operation was successful, false otherwise + */ + public boolean unlock(); + + /** + * is this entity locked? + * @return true if the entity is in a locked state, false otherwise + */ + public boolean isLocked(); +} diff --git a/policy-core/src/main/java/org/openecomp/policy/drools/properties/PolicyProperties.java b/policy-core/src/main/java/org/openecomp/policy/drools/properties/PolicyProperties.java new file mode 100644 index 00000000..13580219 --- /dev/null +++ b/policy-core/src/main/java/org/openecomp/policy/drools/properties/PolicyProperties.java @@ -0,0 +1,96 @@ +/*- + * ============LICENSE_START======================================================= + * policy-core + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.policy.drools.properties; + +public interface PolicyProperties { + + /* Controller Properties */ + + public static final String PROPERTY_CONTROLLER_NAME = "controller.name"; + + /* Generic property suffixes */ + + public static final String PROPERTY_TOPIC_SERVERS_SUFFIX = ".servers"; + public static final String PROPERTY_TOPIC_API_KEY_SUFFIX = ".apiKey"; + public static final String PROPERTY_TOPIC_API_SECRET_SUFFIX = ".apiSecret"; + public static final String PROPERTY_TOPIC_AAF_MECHID_SUFFIX = ".aafMechId"; + public static final String PROPERTY_TOPIC_AAF_PASSWORD_SUFFIX = ".aafPassword"; + public static final String PROPERTY_TOPIC_EVENTS_SUFFIX =".events"; + public static final String PROPERTY_TOPIC_EVENTS_FILTER_SUFFIX =".filter"; + public static final String PROPERTY_TOPIC_EVENTS_CUSTOM_MODEL_CODER_GSON_SUFFIX =".events.custom.gson"; + public static final String PROPERTY_TOPIC_EVENTS_CUSTOM_MODEL_CODER_JACKSON_SUFFIX =".events.custom.jackson"; + + public static final String PROPERTY_TOPIC_SOURCE_CONSUMER_GROUP_SUFFIX = ".consumerGroup"; + public static final String PROPERTY_TOPIC_SOURCE_CONSUMER_INSTANCE_SUFFIX = ".consumerInstance"; + public static final String PROPERTY_TOPIC_SOURCE_FETCH_TIMEOUT_SUFFIX = ".fetchTimeout"; + public static final String PROPERTY_TOPIC_SOURCE_FETCH_LIMIT_SUFFIX = ".fetchLimit"; + public static final String PROPERTY_MANAGED_SUFFIX =".managed"; + + public static final String PROPERTY_TOPIC_SINK_PARTITION_KEY_SUFFIX =".partitionKey"; + + /* UEB Properties */ + + public static final String PROPERTY_UEB_SOURCE_TOPICS = "ueb.source.topics"; + public static final String PROPERTY_UEB_SINK_TOPICS = "ueb.sink.topics"; + + /* DMAAP Properties */ + + public static final String PROPERTY_DMAAP_SOURCE_TOPICS = "dmaap.source.topics"; + public static final String PROPERTY_DMAAP_SINK_TOPICS = "dmaap.sink.topics"; + + /* HTTP Server Properties */ + + public static final String PROPERTY_HTTP_SERVER_SERVICES = "http.server.services"; + + public static final String PROPERTY_HTTP_HOST_SUFFIX = ".host"; + public static final String PROPERTY_HTTP_PORT_SUFFIX = ".port"; + public static final String PROPERTY_HTTP_CONTEXT_URIPATH_SUFFIX = ".contextUriPath"; + + public static final String PROPERTY_HTTP_AUTH_USERNAME_SUFFIX = ".userName"; + public static final String PROPERTY_HTTP_AUTH_PASSWORD_SUFFIX = ".password"; + public static final String PROPERTY_HTTP_AUTH_URIPATH_SUFFIX = ".authUriPath"; + + public static final String PROPERTY_HTTP_REST_CLASSES_SUFFIX = ".restClasses"; + public static final String PROPERTY_HTTP_REST_PACKAGES_SUFFIX = ".restPackages"; + public static final String PROPERTY_HTTP_REST_URIPATH_SUFFIX = ".restUriPath"; + + public static final String PROPERTY_HTTP_HTTPS_SUFFIX = ".https"; + + /* HTTP Client Properties */ + + public static final String PROPERTY_HTTP_CLIENT_SERVICES = "http.client.services"; + + public static final String PROPERTY_HTTP_URL_SUFFIX = PROPERTY_HTTP_CONTEXT_URIPATH_SUFFIX; + + /* Drools Properties */ + + public static final String RULES_GROUPID = "rules.groupId"; + public static final String RULES_ARTIFACTID = "rules.artifactId"; + public static final String RULES_VERSION = "rules.version"; + + /* Management Server Properties */ + + public static final String ENV_MANAGEMENT_SERVER_PORT = "ENGINE_MANAGEMENT_PORT"; + public static final String ENV_MANAGEMENT_SERVER_HOST = "ENGINE_MANAGEMENT_HOST"; + public static final String ENV_MANAGEMENT_AUTH_USER = "ENGINE_MANAGEMENT_USER"; + public static final String ENV_MANAGEMENT_AUTH_PASSWD = "ENGINE_MANAGEMENT_PASSWORD"; + +} diff --git a/policy-core/src/main/java/org/openecomp/policy/drools/properties/Startable.java b/policy-core/src/main/java/org/openecomp/policy/drools/properties/Startable.java new file mode 100644 index 00000000..bb6334a2 --- /dev/null +++ b/policy-core/src/main/java/org/openecomp/policy/drools/properties/Startable.java @@ -0,0 +1,65 @@ +/*- + * ============LICENSE_START======================================================= + * policy-core + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.policy.drools.properties; + +/** + * Declares the Startable property of any class class implementing + * this interface. This implies that the implementing class supports + * start-like operations. + */ +public interface Startable { + + /** + * Start operation. This operation starts the entity. + * + * @return boolean. true if the start operation was successful, + * otherwise false. + * @throws IllegalStateException. if the element is in a state that + * conflicts with the start operation. + */ + public boolean start() throws IllegalStateException; + + /** + * Stop operation. The entity can be restarted again by invoking + * the start operation. + * + * @return boolean. true if the stop operation was successful, + * otherwise false. + * @throws IllegalStateException. if the element is in a state that + * conflicts with the stop operation. + */ + public boolean stop()throws IllegalStateException; + + /** + * shutdown operation. The terminate operation yields the entity + * unusuable. It cannot be (re)started. + * + * @throws IllegalStateException. if the element is in a state that + * conflicts with the stop operation. + */ + public void shutdown()throws IllegalStateException; + + /** + * is it alive? + * @return boolean. true if alive, otherwise false + */ + public boolean isAlive(); +} diff --git a/policy-core/src/main/resources/META-INF/jndi.properties b/policy-core/src/main/resources/META-INF/jndi.properties new file mode 100644 index 00000000..033a08aa --- /dev/null +++ b/policy-core/src/main/resources/META-INF/jndi.properties @@ -0,0 +1,21 @@ +### +# ============LICENSE_START======================================================= +# policy-core +# ================================================================================ +# Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. +# ================================================================================ +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============LICENSE_END========================================================= +### + +java.naming.factory.initial=bitronix.tm.jndi.BitronixInitialContextFactory diff --git a/policy-core/src/main/resources/META-INF/persistence.xml b/policy-core/src/main/resources/META-INF/persistence.xml new file mode 100644 index 00000000..34685b0e --- /dev/null +++ b/policy-core/src/main/resources/META-INF/persistence.xml @@ -0,0 +1,70 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + ============LICENSE_START======================================================= + policy-core + ================================================================================ + Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + ================================================================================ + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + ============LICENSE_END========================================================= + --> + +<persistence version="2.1" + xmlns="http://xmlns.jcp.org/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd"> + + <persistence-unit name="ncompPU" transaction-type="RESOURCE_LOCAL"> + <!-- This is for database access by non-drools methods --> + <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider> + <class>org.openecomp.policy.common.im.jpa.StateManagementEntity</class> + <class>org.openecomp.policy.drools.persistence.DroolsPdpEntity</class> + <class>org.openecomp.policy.drools.persistence.DroolsSessionEntity</class> + <class>org.drools.persistence.info.SessionInfo</class> + <class>org.drools.persistence.info.WorkItemInfo</class> + <class>org.openecomp.policy.common.ia.jpa.IntegrityAuditEntity</class> + + <properties> + <!-- Properties are passed in --> + </properties> + </persistence-unit> + + <persistence-unit name="ncompsessionsPU" transaction-type="JTA"> + <!-- Used for drools session data access --> + <provider>org.hibernate.jpa.HibernatePersistenceProvider</provider> + <class>org.drools.persistence.info.SessionInfo</class> + <class>org.drools.persistence.info.WorkItemInfo</class> + <properties> + <property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect" /> + <property name="hibernate.max_fetch_depth" value="3" /> + <property name="hibernate.hbm2ddl.auto" value="update" /> + <property name="hibernate.show_sql" value="false" /> + <property name="hibernate.transaction.manager_lookup_class" + value="org.hibernate.transaction.BTMTransactionManagerLookup" /> + </properties> + </persistence-unit> + + + <persistence-unit name="schemaPU" transaction-type="RESOURCE_LOCAL"> + <!-- Limited use for generating the DB and schema files for ncomp DB - uses eclipselink for convenience --> + <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider> + <class>org.drools.persistence.info.SessionInfo</class> + <class>org.drools.persistence.info.WorkItemInfo</class> + <class>org.openecomp.policy.common.ia.jpa.IntegrityAuditEntity</class> + <properties> + <property name="javax.persistence.schema-generation.database.action" value="drop-and-create"/> + <property name="javax.persistence.schema-generation.scripts.action" value="drop-and-create"/> + <property name="javax.persistence.schema-generation.scripts.create-target" value="./sql/generatedCreateNcomp.ddl"/> + <property name="javax.persistence.schema-generation.scripts.drop-target" value="./sql/generatedDropNcomp.ddl"/> + </properties> + </persistence-unit> +</persistence> |