diff options
203 files changed, 33981 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..37cd4d1e --- /dev/null +++ b/.gitignore @@ -0,0 +1,7 @@ +.project +.settings +.classpath +.jupiter +.pydevproject +target +.metadata/ diff --git a/.gitreview b/.gitreview new file mode 100644 index 00000000..6a107fd8 --- /dev/null +++ b/.gitreview @@ -0,0 +1,4 @@ +[gerrit] +host=gerrit.openecomp.org +port=29418 +project=policy/drools-pdp.git diff --git a/LICENSE.txt b/LICENSE.txt new file mode 100644 index 00000000..dde205e9 --- /dev/null +++ b/LICENSE.txt @@ -0,0 +1,16 @@ +Copyright © 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. + +ECOMP and OpenECOMP are trademarks and service marks of AT&T Intellectual Property. diff --git a/README.md b/README.md new file mode 100644 index 00000000..6614ee66 --- /dev/null +++ b/README.md @@ -0,0 +1,3 @@ +This source repository contains the OpenECOMP Policy DroolsPDP code. The settings file only needs to support the standard Maven repositories (e.g. central = http://repo1.maven.org/maven2/), and any proxy settings needed in your environment. + +To build it using Maven 3, first build 'policy-common-modules' (which contains dependencies), and then run: mvn clean install diff --git a/packages/base/.gitignore b/packages/base/.gitignore new file mode 100644 index 00000000..b83d2226 --- /dev/null +++ b/packages/base/.gitignore @@ -0,0 +1 @@ +/target/ diff --git a/packages/base/pom.xml b/packages/base/pom.xml new file mode 100644 index 00000000..80ba20b6 --- /dev/null +++ b/packages/base/pom.xml @@ -0,0 +1,95 @@ +<!-- + ============LICENSE_START======================================================= + Policy Packages + ================================================================================ + 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/xsd/maven-4.0.0.xsd"> + + <modelVersion>4.0.0</modelVersion> + + <parent> + <groupId>org.openecomp.policy.drools-pdp</groupId> + <artifactId>packages</artifactId> + <version>1.0.0-SNAPSHOT</version> + </parent> + + <artifactId>base</artifactId> + <packaging>pom</packaging> + + <name>Base Package</name> + <description>D2 ECOMP Policy Drools PDP Packaging</description> + + <build> + <plugins> + <plugin> + <artifactId>maven-assembly-plugin</artifactId> + <executions> + <execution> + <goals> + <goal>single</goal> + </goals> + <phase>package</phase> + <configuration> + <descriptors> + <descriptor>src/assembly/zip.xml</descriptor> + </descriptors> + <appendAssemblyId>false</appendAssemblyId> + </configuration> + </execution> + </executions> + </plugin> + </plugins> + </build> + + <profiles> + <profile> + <id>unix_pe_version</id> + <activation> + <os> + <family>!windows</family> + </os> + </activation> + <build> + <plugins> + <plugin> + <groupId>org.codehaus.mojo</groupId> + <artifactId>exec-maven-plugin</artifactId> + <executions> + <execution> + <id>create-version-file</id> + <goals> + <goal>exec</goal> + </goals> + <phase>prepare-package</phase> + <configuration> + <executable>/bin/bash</executable> + <arguments> + <argument>-c</argument> + <argument>mkdir -p target ; echo -e 'version="${project.version}"\ndescription="Open ECOMP Drools PDP"\nbuildTag="'"${BUILD_TAG}"'"\ncommit="'"${GIT_COMMIT}"'"\ntimestamp="${maven.build.timestamp}"' >target/build.info</argument> + </arguments> + </configuration> + </execution> + </executions> + </plugin> + </plugins> + </build> + </profile> + </profiles> + +</project> diff --git a/packages/base/src/assembly/zip.xml b/packages/base/src/assembly/zip.xml new file mode 100644 index 00000000..1f3b206f --- /dev/null +++ b/packages/base/src/assembly/zip.xml @@ -0,0 +1,42 @@ +<!-- + ============LICENSE_START======================================================= + Base Package + ================================================================================ + 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========================================================= + --> + +<assembly> + <id>base</id> + <formats> + <format>tar.gz</format> + </formats> + <includeBaseDirectory>false</includeBaseDirectory> + <fileSets> + <fileSet> + <directory>${project.build.directory}</directory> + <outputDirectory>etc</outputDirectory> + <includes><include>build.info</include></includes> + <fileMode>700</fileMode> + <directoryMode>700</directoryMode> + </fileSet> + <fileSet> + <directory>src/files</directory> + <outputDirectory>.</outputDirectory> + <fileMode>700</fileMode> + <directoryMode>700</directoryMode> + </fileSet> + </fileSets> +</assembly> diff --git a/packages/base/src/files/bin/db_upgrade_droolspdp.sh b/packages/base/src/files/bin/db_upgrade_droolspdp.sh new file mode 100644 index 00000000..738317de --- /dev/null +++ b/packages/base/src/files/bin/db_upgrade_droolspdp.sh @@ -0,0 +1,154 @@ +#!/bin/bash + +### +# ============LICENSE_START======================================================= +# Base Package +# ================================================================================ +# 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========================================================= +### + +# +# db_upgrade_droolspdp.sh: Run this script to upgrade drools database to a given release level, +# it is recommended that you switch to the policy user to run this script +# +# Usage : db_upgrade_droolspdp.sh target_db_release_level db_user_id db_user_password +# Example: db_upgrade_droolspdp.sh 151000 policy_user password +# +# Assumption: 1. DB upgrade sql script in $POLICY_HOME/data/mysql folder with read permission +# 2. DB user has privilege to create/drop/alter database table +# +# Note: The default location for db release script is $POLICY_HOME/data/mysql +# The release level is represented as Two-digit-Year+Two-digit-Month+two-digit-Sub-release (151000, 151001) +# Drools database version is represented by record with the_key of 'DROOLS_VERSION' +# + +TARGET_RELEASE="" +CURRENT_RELEASE="" +DB_UPGRADE_USER="" +DB_UPGRADE_PASSWORD="" +DB_UPGRADE_DIR=$POLICY_HOME/data/mysql +DATE=`date +"%Y%m%d%H%M%S"` +LOG="" +ERR="" + +function get_current_release_level +{ + echo "Get current release level started ...@`date`" | tee -a $LOG + # display output vertical + query="select version from support.db_version where the_key = 'DROOLS_VERSION' \G" + CURRENT_RELEASE=`${MYSQL} --skip-column-names --execute "${query}" 2>$ERR | grep -v "*"` + echo "CURRENT_RELEASE: [$CURRENT_RELEASE]" | tee -a $LOG + echo "Get current release level completed ...@`date`" | tee -a $LOG +} + +function evaluate_upgrade_downgrade +{ + echo "CURRENT_RELEASE --> [$CURRENT_RELEASE]" | tee -a $LOG + echo "TARGET_RELEASE --> [$TARGET_RELEASE] " | tee -a $LOG + if [[ "${CURRENT_RELEASE}" < "${TARGET_RELEASE}" ]]; then + # perform db upgrade + UPGRADE_LIST=/tmp/db_upgrade_droolspdp_list.$$ + find ${DB_UPGRADE_DIR} -name "*_upgrade_script.sql" 2>/dev/null | grep "droolspdp" | sort > $UPGRADE_LIST + while read -r file + do + RELEASE=`basename $file | cut -d'_' -f1` + #echo "[$RELEASE] [$TARGET_RELEASE]" | tee -a $LOG + if [ "${RELEASE}" -gt "${CURRENT_RELEASE}" ] && [ "${RELEASE}" -le "${TARGET_RELEASE}" ]; then + run_script "UPGRADE" "${file}" 2>&1 | tee -a $LOG + fi + done < $UPGRADE_LIST + rm -f $UPGRADE_LIST + set_current_release_level $TARGET_RELEASE + elif [[ "${CURRENT_RELEASE}" > "${TARGET_RELEASE}" ]]; then + # perform db downgrade + DOWNGRADE_LIST=/tmp/db_downgrade_list.$$ + find ${DB_UPGRADE_DIR} -name "*_downgrade_script.sql" 2>/dev/null | grep "droolspdp" | sort -r > $DOWNGRADE_LIST + while read -r file + do + RELEASE=`basename $file | cut -d'_' -f1` + #echo "[$RELEASE] [$TARGET_RELEASE]" | tee -a $LOG + if [ "${RELEASE}" -le "${CURRENT_RELEASE}" ] && [ "${RELEASE}" -gt "${TARGET_RELEASE}" ]; then + run_script "DOWNGRADE" "${file}" + fi + done < $DOWNGRADE_LIST + rm -f $DOWNGRADE_LIST + set_current_release_level $TARGET_RELEASE + else + echo "CURRENT DB RELEASE LEVEL THE SAME AS TARGET RELEASE LEVEL, NO ACTION TAKEN ..." | tee -a $LOG + fi +} + +function run_script +{ + action="${1}" + script="${2}" + echo "Perform DB $action use $script ..." | tee -a $LOG + echo "--" | tee -a $LOG + ${MYSQL} --verbose < "${script}" 2>$ERR | tee -a $LOG + echo "--" | tee -a $LOG +} + +function set_current_release_level +{ + RELEASE="${1}" + echo "Set current release level to [$RELEASE] started ...@`date`" | tee -a $LOG + update_statement="insert into support.db_version (the_key, version) values ('DROOLS_VERSION', '${RELEASE}') on duplicate key update version='${RELEASE}';" + ${MYSQL} --execute "${update_statement}" + + echo "" | tee -a $LOG + echo "CURRENT_RELEASE set to: [$RELEASE]" | tee -a $LOG + echo "" | tee -a $LOG + echo "Set current release level completed ...@`date`" | tee -a $LOG +} + +function check_directory +{ + if [ ! -d $DB_UPGRADE_DIR ]; then + echo "ERROR, DIRECTORY NOT EXIST: $DB_UPGRADE_DIR, PROCESS EXIT ..." + exit; + else + if [ ! -d $DB_UPGRADE_DIR/logs ]; then + mkdir $DB_UPGRADE_DIR/logs + fi + fi +} + +# MAIN +#check_directory +LOG=$POLICY_HOME/logs/db_upgrade_droolspdp_$DATE.log +ERR=$POLICY_HOME/logs/db_upgrade_droolspdp_$DATE.err +echo "db_upgrade_droolspdp.sh started ..." | tee -a $LOG +if [ $# -eq 3 ]; then + TARGET_RELEASE="${1}" + DB_UPGRADE_USER="${2}" + DB_UPGRADE_PASSWORD="${3}" + echo "TARGET_RELEASE : $TARGET_RELEASE" | tee -a $LOG + echo "DB_UPGRADE_USER: $DB_UPGRADE_USER" | tee -a $LOG + echo "DB_UPGRADE_DIR : $DB_UPGRADE_DIR" | tee -a $LOG + # + if [ ${#TARGET_RELEASE} -ne 6 ]; then + echo "ERROR, TARGET_RELEASE MUST BE 6 DIGITS: $TARGET_RELEASE" | tee -a $LOG | tee -a $ERR + else + typeset -r MYSQL="mysql -u${DB_UPGRADE_USER} -p${DB_UPGRADE_PASSWORD} "; + get_current_release_level + evaluate_upgrade_downgrade + fi +else + echo "Usage : db_upgrade_droolspdp.sh target_release_level db_user_id db_user_password" | tee -a $LOG + echo "Example: db_upgrade_droolspdp.sh 151000 policy_user password" | tee -a $LOG +fi + +echo "db_upgrade_droolspdp.sh completed ..." | tee -a $LOG diff --git a/packages/base/src/files/bin/db_upgrade_droolspdp_remote.sh b/packages/base/src/files/bin/db_upgrade_droolspdp_remote.sh new file mode 100644 index 00000000..96cfda1c --- /dev/null +++ b/packages/base/src/files/bin/db_upgrade_droolspdp_remote.sh @@ -0,0 +1,151 @@ +#!/bin/bash +# +# db_upgrade_droolspdp_remote.sh: This script is to perform database schema upgrade on remote db, +# no shecma downgrade will be performed in case db_version is higher then target_version +# +# Logic: 1. Get target schema version from db scripts in $POLICY_HOME/data/mysql +# 2. Get current db schema version from support.db_version table (of target system) +# 3. Apply db upgrade script in order if target_version is HIGHER than db_version +# 4. Print out warning message if target_version is LOWER than db_version +# 4. Print out message if target_version is EQUAL to db_version +# +# +# Usage : db_upgrade_droolspdp_remote.sh db_user_id db_user_password hostname +# Example: db_upgrade_droolspdp_remote.sh policy_user password policydb +# +# Assumption: 1. DB schema upgrade script in $POLICY_HOME/data/mysql folder with read permission +# 2. DB user has privilege to create/drop/alter database table +# +# Note: The default location for db schema upgrade script is $POLICY_HOME/data/mysql +# The release level is represented as Two-digit-Year+Two-digit-Month+two-digit-Sub-release (151000, 151001) +# +# + +TARGET_SCHEMA_VERSION="" +CURRENT_SCHEMA_VERSION="" +DB_UPGRADE_USER="" +DB_UPGRADE_PASSWORD="" +DB_HOSTNAME="" +DB_UPGRADE_DIR=$POLICY_HOME/data/mysql +DATE=`date +"%Y%m%d%H%M%S"` +LOG="" +ERR="" + +function get_current_schema_version +{ + echo "Get current schema version from [${DB_HOSTNAME}] started ...@`date`" | tee -a $LOG + # display output vertical + query="select version from support.db_version where the_key = 'DROOLS_VERSION' \G" + CURRENT_SCHEMA_VERSION=`${MYSQL} --skip-column-names --execute "${query}" 2>$ERR | grep -v "*"` + error_msg=`cat $ERR | grep "doesn't exist"` + if [ "${error_msg}" != "" ]; then + echo "Create support.db_version table ..." | tee -a $LOG + sql="create table support.db_version(the_key varchar(20) not null, version varchar(20), primary key(the_key));" + ${MYSQL} --execute "${sql}" + CURRENT_SCHEMA_VERSION="00" + fi + echo "CURRENT_SCHEMA_VERSION: [$CURRENT_SCHEMA_VERSION]" | tee -a $LOG + echo "Get current schema version from [${DB_HOSTNAME}] completed ...@`date`" | tee -a $LOG +} + +function get_target_schema_version +{ + UPGRADE_LIST=/tmp/db_upgrade_list.$$ + find ${DB_UPGRADE_DIR} -name "*_upgrade_script.sql" 2>/dev/null | grep "droolspdp" | sort -r | head -1 > $UPGRADE_LIST + while read -r file + do + TARGET_SCHEMA_VERSION=`basename $file | cut -d'_' -f1` + echo "TARGET_SCHEMA_VERSION: [$TARGET_SCHEMA_VERSION]" | tee -a $LOG + break + done < $UPGRADE_LIST + rm -f $UPGRADE_LIST +} + +function evaluate_upgrade_downgrade +{ + echo "CURRENT_SCHEMA_VERSION --> [$CURRENT_SCHEMA_VERSION]" | tee -a $LOG + echo "TARGET_SCHEMA_VERSION --> [$TARGET_SCHEMA_VERSION] " | tee -a $LOG + if [[ "${CURRENT_SCHEMA_VERSION}" < "${TARGET_SCHEMA_VERSION}" ]]; then + # perform db upgrade + UPGRADE_LIST=/tmp/db_upgrade_list.$$ + find ${DB_UPGRADE_DIR} -name "*_upgrade_script.sql" 2>/dev/null | grep "droolspdp" | sort > $UPGRADE_LIST + while read -r file + do + DB_VERSION=`basename $file | cut -d'_' -f1` + #echo "[$DB_VERSION] [$TARGET_SCHEMA_VERSION]" | tee -a $LOG + if [ "${DB_VERSION}" -gt "${CURRENT_SCHEMA_VERSION}" ] && [ "${DB_VERSION}" -le "${TARGET_SCHEMA_VERSION}" ]; then + run_script "UPGRADE" "${file}" 2>&1 | tee -a $LOG + fi + done < $UPGRADE_LIST + rm -f $UPGRADE_LIST + set_current_release_level $TARGET_SCHEMA_VERSION + elif [[ "${CURRENT_SCHEMA_VERSION}" > "${TARGET_SCHEMA_VERSION}" ]]; then + # db downgrade + echo "WARNING: Target db schema version is LOWER than current db scema version, please run downgrade script manually." | tee -a $LOG | tee -a $ERR + else + echo "CURRENT SCHEMA VERSION THE SAME AS TARGET SCHEMA VERSION, NO ACTION TAKEN ..." | tee -a $LOG + fi +} + +function run_script +{ + action="${1}" + script="${2}" + echo "Perform DB $action on [${DB_HOSTNAME}] use $script ..." | tee -a $LOG + echo "--" | tee -a $LOG + ${MYSQL} --verbose < "${script}" 2>$ERR | tee -a $LOG + echo "--" | tee -a $LOG +} + +function set_current_release_level +{ + DB_VERSION="${1}" + echo "Set current release level on [${DB_HOSTNAME}] to [$DB_VERSION] started ...@`date`" | tee -a $LOG + update_statement="insert into support.db_version (the_key, version) values ('DROOLS_VERSION', '${DB_VERSION}') on duplicate key update version='${DB_VERSION}';" + ${MYSQL} --execute "${update_statement}" + + echo "" | tee -a $LOG + echo "CURRENT_SCHEMA_VERSION set to: [$DB_VERSION]" | tee -a $LOG + echo "" | tee -a $LOG + echo "Set current release level on [${DB_HOSTNAME}] to [$DB_VERSION] completed ...@`date`" | tee -a $LOG +} + +function check_directory +{ + if [ ! -d $DB_UPGRADE_DIR ]; then + echo "ERROR, DIRECTORY NOT EXIST: $DB_UPGRADE_DIR, PROCESS EXIT ..." + exit; + else + if [ ! -d $DB_UPGRADE_DIR/logs ]; then + mkdir $DB_UPGRADE_DIR/logs + fi + fi +} + +# MAIN +#check_directory +LOG=$POLICY_HOME/logs/db_upgrade_droolspdp_remote_$DATE.log +ERR=$POLICY_HOME/logs/db_upgrade_droolspdp_remote_$DATE.err +echo "db_upgrade_droolspdp_remote.sh started ..." | tee -a $LOG +if [ $# -eq 3 ]; then + DB_UPGRADE_USER="${1}" + DB_UPGRADE_PASSWORD="${2}" + DB_HOSTNAME="${3}" + echo "DB_UPGRADE_USER: $DB_UPGRADE_USER" | tee -a $LOG + echo "DB_UPGRADE_DIR : $DB_UPGRADE_DIR" | tee -a $LOG + echo "DB_HOSTNAME : $DB_HOSTNAME" | tee -a $LOG + # + typeset -r MYSQL="mysql -u${DB_UPGRADE_USER} -p${DB_UPGRADE_PASSWORD} -h ${DB_HOSTNAME}"; + get_target_schema_version + if [ ${#TARGET_SCHEMA_VERSION} -ne 6 ]; then + echo "ERROR, TARGET_SCHEMA_VERSION MUST BE 6 DIGITS: $TARGET_SCHEMA_VERSION" | tee -a $LOG | tee -a $ERR + else + get_current_schema_version + evaluate_upgrade_downgrade + fi +else + echo "Usage : db_upgrade_droolspdp_remote.sh db_user_id db_user_password db_hostname" | tee -a $LOG + echo "Example: db_upgrade_droolspdp_remote.sh policy_user password policydb" | tee -a $LOG +fi + +echo "db_upgrade_droolspdp_remote.sh completed ..." | tee -a $LOG diff --git a/packages/base/src/files/bin/monitor.sh b/packages/base/src/files/bin/monitor.sh new file mode 100644 index 00000000..f4fad486 --- /dev/null +++ b/packages/base/src/files/bin/monitor.sh @@ -0,0 +1,148 @@ +#!/bin/bash + +### +# ============LICENSE_START======================================================= +# Base Package +# ================================================================================ +# 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========================================================= +### + +function usage() { + echo -n "syntax: $(basename $0) " + echo "[--debug]" +} + +function log() { + echo "$(date +"%Y-%m-%d_%H-%M-%S") $1" >> ${POLICY_HOME}/logs/monitor.log +} + +function monitor() { + if [[ $DEBUG == y ]]; then + echo "-- ${FUNCNAME[0]} --" + set -x + fi + + CONTROLLER=$1 + STATUS=$2 + + if [[ -z ${CONTROLLER} ]]; then + log "WARNING: invalid invocation: no component provided" + return + fi + + if [[ -z ${STATUS} ]]; then + log "WARNING: invalid invocation: no on/off/uninstalled switch provided for ${CONTROLLER}" + return + fi + + if [[ "${STATUS}" == "off" ]]; then + off ${CONTROLLER} + else + if [[ "${STATUS}" == "on" ]]; then + on ${CONTROLLER} + fi + fi +} + +function on() { + if [[ $DEBUG == y ]]; then + echo "-- ${FUNCNAME[0]} --" + set -x + fi + + CONTROLLER=$1 + NAGIOS_COMPONENT_SERVICE="Check_${CONTROLLER}-AliveStatus_AP_24094" + + ${POLICY_HOME}/bin/${CONTROLLER} status + if [[ $? != 0 ]]; then + log "starting ${CONTROLLER}" + + # need to make sure we don't pass the lock file descriptor + ${POLICY_HOME}/bin/${CONTROLLER} umstart {cfg}>&- + else + log "OK: ${CONTROLLER} (UP)" + fi +} + +function off() { + if [[ $DEBUG == y ]]; then + echo "-- ${FUNCNAME[0]} --" + set -x + fi + + CONTROLLER=$1 + NAGIOS_COMPONENT_SERVICE="Check_${CONTROLLER}-AliveStatus_AP_24094" + + ${POLICY_HOME}/bin/${CONTROLLER} status + if [[ $? != 0 ]]; then + log "OK: ${CONTROLLER} (DOWN)" + + else + log "stopping ${CONTROLLER}" + ${POLICY_HOME}/bin/${CONTROLLER} umstop + fi +} + +function process_config() { + if [[ $DEBUG == y ]]; then + echo "-- ${FUNCNAME[0]} --" + set -x + fi + + CONF_FILE=${POLICY_HOME}/etc/monitor/monitor.cfg + while read line || [ -n "${line}" ]; do + if [[ -n ${line} ]] && [[ ${line} != *#* ]]; then + controller=$(echo "${line}" | awk -F = '{print $1;}') + status=$(echo "${line}" | awk -F = '{print $2;}') + if [[ -n ${controller} ]] && [[ -n ${status} ]]; then + monitor ${controller} ${status} + fi + fi + done < "${CONF_FILE}" + return 0 +} + +log "Enter monitor" + +DEBUG=n +until [[ -z "$1" ]]; do + case $1 in + -d|--debug|debug) DEBUG=y + set -x + ;; + *) usage + exit 1 + ;; + esac + shift +done + +if pidof -o %PPID -x $(basename $0) > /dev/null 2>&1; then + log "WARNING: $(basename $0) from the previous iteration still running. Exiting." + exit 1 +fi + +. ${POLICY_HOME}/etc/profile.d/env.sh + +if [[ ${NAGIOS_NRDP_DISABLED} == true ]]; then + log "Nagios NRDS is disabled." +fi + +if flock ${cfg} ; then + process_config +fi {cfg}>>${POLICY_HOME}/etc/monitor/monitor.cfg.lock + + diff --git a/packages/base/src/files/bin/policy.sh b/packages/base/src/files/bin/policy.sh new file mode 100644 index 00000000..67f56caf --- /dev/null +++ b/packages/base/src/files/bin/policy.sh @@ -0,0 +1,154 @@ +#!/bin/bash + +### +# ============LICENSE_START======================================================= +# Base Package +# ================================================================================ +# 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========================================================= +### + +function usage() { + echo -n "syntax: $(basename $0) " + echo -n "[--debug] " + echo "status|start|stop" +} + +function check_x_file() { + if [[ $DEBUG == y ]]; then + echo "-- ${FUNCNAME[0]} --" + set -x + fi + + FILE=$1 + if [[ ! -f ${FILE} || ! -x ${FILE} ]]; then + return 1 + fi + + return 0 +} + +function policy_op() { + if [[ $DEBUG == y ]]; then + echo "-- ${FUNCNAME[0]} --" + set -x + fi + + operation=$1 + + cd $POLICY_HOME + echo "[drools-pdp-controllers]" + for binScript in bin/*-controller; do + if check_x_file "${binScript}"; then + trap "rm -f /tmp/out$$" EXIT + ${binScript} ${operation} >/tmp/out$$ + echo " L [${controller}]: $(sed ':a;N;$!ba;s/\n/ /g' /tmp/out$$)" + else + echo " L [${controller}]: -" + fi + done +} + +function policy_status() { + if [[ $DEBUG == y ]]; then + echo "-- ${FUNCNAME[0]} --" + set -x + fi + + policy_op "status" + + NUM_CRONS=$(crontab -l 2> /dev/null | wc -l) + echo " ${NUM_CRONS} cron jobs installed." + +} + +function policy_start() { + if [[ $DEBUG == y ]]; then + echo "-- ${FUNCNAME[0]} --" + set -x + fi + + policy_op "start" +} + + +function policy_stop() { + if [[ $DEBUG == y ]]; then + echo "-- ${FUNCNAME[0]} --" + set -x + fi + + policy_op "stop" +} + +######################################################################### +## +## script execution body +## +######################################################################### + +DEBUG=n +OPERATION=none + +until [[ -z "$1" ]]; do + case $1 in + -d|--debug|debug) DEBUG=y + set -x + ;; + -i|--status|status) OPERATION=status + ;; + -s|--start|start) OPERATION=start + ;; + -h|--stop|stop|--halt|halt) OPERATION=halt + ;; + *) usage + exit 1 + ;; + esac + shift +done + +# operation validation +case $OPERATION in + status) ;; + start) ;; + halt) ;; + *) echo "invalid operation \(${OPERATION}\): must be in {status|start|stop}"; + usage + exit 1 + ;; +esac + +if [[ -z ${POLICY_HOME} ]]; then + echo "error: POLICY_HOME is unset." + exit 1 +fi + +# operation validation +case $OPERATION in + status) + policy_status + ;; + start) + policy_start + ;; + halt) + policy_stop + ;; + *) echo "invalid operation \(${OPERATION}\): must be in {status|start|stop}"; + usage + exit 1 + ;; +esac diff --git a/packages/base/src/files/data/mysql/160400_droolspdp_downgrade_script.sql b/packages/base/src/files/data/mysql/160400_droolspdp_downgrade_script.sql new file mode 100644 index 00000000..44f49198 --- /dev/null +++ b/packages/base/src/files/data/mysql/160400_droolspdp_downgrade_script.sql @@ -0,0 +1,23 @@ +/*- + * ============LICENSE_START======================================================= + * Base Package + * ================================================================================ + * 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========================================================= + */ + +drop table if exists drools.sessioninfo; +drop table if exists drools.WORKITEMINFO; +drop table if exists drools.droolspdpentity; diff --git a/packages/base/src/files/data/mysql/160400_droolspdp_upgrade_script.sql b/packages/base/src/files/data/mysql/160400_droolspdp_upgrade_script.sql new file mode 100644 index 00000000..03e96521 --- /dev/null +++ b/packages/base/src/files/data/mysql/160400_droolspdp_upgrade_script.sql @@ -0,0 +1,57 @@ +/*- + * ============LICENSE_START======================================================= + * Base Package + * ================================================================================ + * 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========================================================= + */ + +-- use BLOB instead of LONGVARBINARY +drop table if exists drools.sessioninfo; +CREATE TABLE drools.SESSIONINFO +( +ID BIGINT NOT NULL, +LASTMODIFICATIONDATE TIMESTAMP, +RULESBYTEARRAY BLOB, +STARTDATE TIMESTAMP default current_timestamp, +OPTLOCK INTEGER, +PRIMARY KEY (ID) +); + +drop table if exists drools.WORKITEMINFO; +CREATE TABLE drools.WORKITEMINFO +( +WORKITEMID BIGINT NOT NULL, +CREATIONDATE TIMESTAMP default current_timestamp, +`NAME` VARCHAR(500), +PROCESSINSTANCEID BIGINT, +STATE BIGINT, +OPTLOCK INTEGER, +WORKITEMBYTEARRAY BLOB, +PRIMARY KEY (WORKITEMID) +); + +drop table if exists drools.droolspdpentity; +CREATE TABLE drools.DROOLSPDPENTITY +( + PDPID VARCHAR(100) NOT NULL, + DESIGNATED BOOLEAN NOT NULL DEFAULT FALSE, + PRIORITY INT NOT NULL DEFAULT 0, + UPDATEDDATE DATE NOT NULL, + GROUPID VARCHAR(100) NOT NULL, + SESSIONID BIGINT NOT NULL +); + + diff --git a/packages/base/src/files/data/mysql/160401_droolspdp_downgrade_script.sql b/packages/base/src/files/data/mysql/160401_droolspdp_downgrade_script.sql new file mode 100644 index 00000000..c8bbe035 --- /dev/null +++ b/packages/base/src/files/data/mysql/160401_droolspdp_downgrade_script.sql @@ -0,0 +1,30 @@ +/*- + * ============LICENSE_START======================================================= + * Base Package + * ================================================================================ + * 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========================================================= + */ + +drop table if exists drools.droolspdpentity; +CREATE TABLE drools.DROOLSPDPENTITY +( + PDPID VARCHAR(100) NOT NULL, + DESIGNATED BOOLEAN NOT NULL DEFAULT FALSE, + PRIORITY INT NOT NULL DEFAULT 0, + UPDATEDDATE DATE NOT NULL, + GROUPID VARCHAR(100) NOT NULL, + SESSIONID BIGINT NOT NULL +); diff --git a/packages/base/src/files/data/mysql/160401_droolspdp_upgrade_script.sql b/packages/base/src/files/data/mysql/160401_droolspdp_upgrade_script.sql new file mode 100644 index 00000000..e7d92216 --- /dev/null +++ b/packages/base/src/files/data/mysql/160401_droolspdp_upgrade_script.sql @@ -0,0 +1,30 @@ +/*- + * ============LICENSE_START======================================================= + * Base Package + * ================================================================================ + * 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========================================================= + */ + +drop table if exists drools.droolspdpentity; +CREATE TABLE drools.DROOLSPDPENTITY +( + PDPID VARCHAR(100) NOT NULL, + DESIGNATED BOOLEAN NOT NULL DEFAULT FALSE, + PRIORITY INT NOT NULL DEFAULT 0, + UPDATEDDATE TIMESTAMP NOT NULL, + GROUPID VARCHAR(100) NOT NULL, + SESSIONID BIGINT NOT NULL +); diff --git a/packages/base/src/files/data/mysql/160700_droolspdp_downgrade_script.sql b/packages/base/src/files/data/mysql/160700_droolspdp_downgrade_script.sql new file mode 100644 index 00000000..c8613bb7 --- /dev/null +++ b/packages/base/src/files/data/mysql/160700_droolspdp_downgrade_script.sql @@ -0,0 +1,25 @@ +/*- + * ============LICENSE_START======================================================= + * Base Package + * ================================================================================ + * 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========================================================= + */ + +drop table if exists drools.droolssessionentity; +drop table if exists drools.droolspdpentity; +drop table if exists drools.sessioninfo; +drop table if exists drools.WORKITEMINFO; + diff --git a/packages/base/src/files/data/mysql/160700_droolspdp_upgrade_script.sql b/packages/base/src/files/data/mysql/160700_droolspdp_upgrade_script.sql new file mode 100644 index 00000000..3350859e --- /dev/null +++ b/packages/base/src/files/data/mysql/160700_droolspdp_upgrade_script.sql @@ -0,0 +1,68 @@ +/*- + * ============LICENSE_START======================================================= + * Base Package + * ================================================================================ + * 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========================================================= + */ + +drop table if exists drools.droolssessionentity; +drop table if exists drools.droolspdpentity; + +CREATE TABLE drools.DROOLSPDPENTITY +( + PDPID VARCHAR(100) NOT NULL, + DESIGNATED BOOLEAN NOT NULL DEFAULT FALSE, + PRIORITY INT NOT NULL DEFAULT 0, + UPDATEDDATE TIMESTAMP NOT NULL, + GROUPID VARCHAR(100) NOT NULL, + SESSIONID BIGINT NOT NULL, + PRIMARY KEY(PDPID) +); + +CREATE TABLE drools.DROOLSSESSIONENTITY +( + PDPID VARCHAR(100) NOT NULL, + SESSIONNAME VARCHAR(100) NOT NULL, + SESSIONID BIGINT NOT NULL, + PDPENTITY_pdpId BIGINT NOT NULL, + PRIMARY KEY(PDPID,SESSIONNAME) +); +ALTER TABLE drools.DROOLSSESSIONENTITY ADD CONSTRAINT FK_DROOLSSESSIONENTITY_DROOLSPDPENTITY_PDPID +FOREIGN KEY (PDPID) REFERENCES drools.DROOLSPDPENTITY (PDPID); + +drop table if exists drools.sessioninfo; +CREATE TABLE drools.SESSIONINFO +( +ID BIGINT NOT NULL, +LASTMODIFICATIONDATE TIMESTAMP, +RULESBYTEARRAY BLOB, +STARTDATE TIMESTAMP default current_timestamp, +OPTLOCK INTEGER, +PRIMARY KEY (ID) +); + +drop table if exists drools.WORKITEMINFO; +CREATE TABLE drools.WORKITEMINFO +( +WORKITEMID BIGINT NOT NULL, +CREATIONDATE TIMESTAMP default current_timestamp, +`NAME` VARCHAR(500), +PROCESSINSTANCEID BIGINT, +STATE BIGINT, +OPTLOCK INTEGER, +WORKITEMBYTEARRAY BLOB, +PRIMARY KEY (WORKITEMID) +); diff --git a/packages/base/src/files/data/mysql/161000_droolspdp_downgrade_script.sql b/packages/base/src/files/data/mysql/161000_droolspdp_downgrade_script.sql new file mode 100644 index 00000000..b1ab793c --- /dev/null +++ b/packages/base/src/files/data/mysql/161000_droolspdp_downgrade_script.sql @@ -0,0 +1,47 @@ +/*- + * ============LICENSE_START======================================================= + * Base Package + * ================================================================================ + * 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========================================================= + */ + +drop table if exists drools.droolssessionentity; +drop table if exists drools.droolspdpentity; + +CREATE TABLE drools.DROOLSPDPENTITY +( + PDPID VARCHAR(100) NOT NULL, + DESIGNATED BOOLEAN NOT NULL DEFAULT FALSE, + PRIORITY INT NOT NULL DEFAULT 0, + UPDATEDDATE TIMESTAMP NOT NULL, + GROUPID VARCHAR(100) NOT NULL, + SESSIONID BIGINT NOT NULL, + PRIMARY KEY(PDPID) +); + +CREATE TABLE drools.DROOLSSESSIONENTITY +( + PDPID VARCHAR(100) NOT NULL, + SESSIONNAME VARCHAR(100) NOT NULL, + SESSIONID BIGINT NOT NULL, + PDPENTITY_pdpId BIGINT NOT NULL, + PRIMARY KEY(PDPID,SESSIONNAME) +); +ALTER TABLE drools.DROOLSSESSIONENTITY ADD CONSTRAINT FK_DROOLSSESSIONENTITY_DROOLSPDPENTITY_PDPID +FOREIGN KEY (PDPID) REFERENCES drools.DROOLSPDPENTITY (PDPID); + +drop table if exists drools.LastSiteEntity; + diff --git a/packages/base/src/files/data/mysql/161000_droolspdp_upgrade_script.sql b/packages/base/src/files/data/mysql/161000_droolspdp_upgrade_script.sql new file mode 100644 index 00000000..9ef24426 --- /dev/null +++ b/packages/base/src/files/data/mysql/161000_droolspdp_upgrade_script.sql @@ -0,0 +1,54 @@ +/*- + * ============LICENSE_START======================================================= + * Base Package + * ================================================================================ + * 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========================================================= + */ + +DROP TABLE if exists drools.DROOLSSESSIONENTITY; +DROP TABLE if exists drools.DROOLSPDPENTITY; + +CREATE TABLE if not exists drools.DROOLSPDPENTITY +( +pdpId VARCHAR(255) NOT NULL, +designated TINYINT(1) default 0 NOT NULL, +priority INTEGER NOT NULL, +site VARCHAR(50), +updatedDate DATETIME NOT NULL, +PRIMARY KEY (pdpId) +); + +CREATE TABLE if not exists drools.DROOLSSESSIONENTITY +( +sessionName VARCHAR(255) NOT NULL, +pdpId VARCHAR(255) NOT NULL, +sessionId BIGINT NOT NULL, +PDPENTITY_pdpId VARCHAR(255), +PRIMARY KEY (sessionName, pdpId) +); + +ALTER TABLE drools.DROOLSSESSIONENTITY ADD CONSTRAINT FK_DROOLSSESSIONENTITY_PDPENTITY_pdpId +FOREIGN KEY (PDPENTITY_pdpId) +REFERENCES drools.DROOLSPDPENTITY (pdpId); + +drop table if exists drools.LastSiteEntity; + +CREATE TABLE `drools`.`LastSiteEntity` +( `id` INT NOT NULL , +`siteName` VARCHAR(50) NOT NULL +); + + diff --git a/packages/base/src/files/data/mysql/161001_droolspdp_downgrade_script.sql b/packages/base/src/files/data/mysql/161001_droolspdp_downgrade_script.sql new file mode 100644 index 00000000..983a9f3c --- /dev/null +++ b/packages/base/src/files/data/mysql/161001_droolspdp_downgrade_script.sql @@ -0,0 +1,56 @@ +/*- + * ============LICENSE_START======================================================= + * Base Package + * ================================================================================ + * 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========================================================= + */ + +set foreign_key_checks=0; + +drop table if exists drools.LastSiteEntity; + +CREATE TABLE `drools`.`LastSiteEntity` +( `id` INT NOT NULL , +`siteName` VARCHAR(50) NOT NULL +); + +drop table if exists drools.DROOLSPDPENTITY; + +CREATE TABLE if not exists drools.DROOLSPDPENTITY +( +pdpId VARCHAR(255) NOT NULL, +designated TINYINT(1) default 0 NOT NULL, +priority INTEGER NOT NULL, +site VARCHAR(50), +updatedDate DATETIME NOT NULL, +PRIMARY KEY (pdpId) +); + +drop table if exists drools.DROOLSSESSIONENTITY; +CREATE TABLE if not exists drools.DROOLSSESSIONENTITY +( +sessionName VARCHAR(255) NOT NULL, +pdpId VARCHAR(255) NOT NULL, +sessionId BIGINT NOT NULL, +PDPENTITY_pdpId VARCHAR(255), +PRIMARY KEY (sessionName, pdpId) +); + +ALTER TABLE drools.DROOLSSESSIONENTITY ADD CONSTRAINT FK_DROOLSSESSIONENTITY_PDPENTITY_pdpId +FOREIGN KEY (PDPENTITY_pdpId) +REFERENCES drools.DROOLSPDPENTITY (pdpId); + +set foreign_key_checks=1; diff --git a/packages/base/src/files/data/mysql/161001_droolspdp_upgrade_script.sql b/packages/base/src/files/data/mysql/161001_droolspdp_upgrade_script.sql new file mode 100644 index 00000000..2731e1bd --- /dev/null +++ b/packages/base/src/files/data/mysql/161001_droolspdp_upgrade_script.sql @@ -0,0 +1,52 @@ +/*- + * ============LICENSE_START======================================================= + * Base Package + * ================================================================================ + * 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========================================================= + */ + +set foreign_key_checks=0; + +drop table if exists drools.LastSiteEntity; + +drop table if exists drools.DROOLSPDPENTITY; + +CREATE TABLE if not exists drools.DROOLSPDPENTITY +( +pdpId VARCHAR(255) NOT NULL, +designated TINYINT(1) default 0 NOT NULL, +priority INTEGER NOT NULL, +site VARCHAR(50), +updatedDate DATETIME NOT NULL, +designatedDate DATETIME NOT NULL, +PRIMARY KEY (pdpId) +); + +drop table if exists drools.DROOLSSESSIONENTITY; +CREATE TABLE if not exists drools.DROOLSSESSIONENTITY +( +sessionName VARCHAR(255) NOT NULL, +pdpId VARCHAR(255) NOT NULL, +sessionId BIGINT NOT NULL, +PDPENTITY_pdpId VARCHAR(255), +PRIMARY KEY (sessionName, pdpId) +); + +ALTER TABLE drools.DROOLSSESSIONENTITY ADD CONSTRAINT FK_DROOLSSESSIONENTITY_PDPENTITY_pdpId +FOREIGN KEY (PDPENTITY_pdpId) +REFERENCES drools.DROOLSPDPENTITY (pdpId); + +set foreign_key_checks=1; diff --git a/packages/base/src/files/data/mysql/161002_droolspdp_downgrade_script.sql b/packages/base/src/files/data/mysql/161002_droolspdp_downgrade_script.sql new file mode 100644 index 00000000..90ed6457 --- /dev/null +++ b/packages/base/src/files/data/mysql/161002_droolspdp_downgrade_script.sql @@ -0,0 +1,21 @@ +/*- + * ============LICENSE_START======================================================= + * Base Package + * ================================================================================ + * 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========================================================= + */ + +drop table if exists drools.IntegrityAuditEntity; diff --git a/packages/base/src/files/data/mysql/161002_droolspdp_upgrade_script.sql b/packages/base/src/files/data/mysql/161002_droolspdp_upgrade_script.sql new file mode 100644 index 00000000..ff99d36a --- /dev/null +++ b/packages/base/src/files/data/mysql/161002_droolspdp_upgrade_script.sql @@ -0,0 +1,41 @@ +/*- + * ============LICENSE_START======================================================= + * Base Package + * ================================================================================ + * 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========================================================= + */ + +drop table if exists drools.IntegrityAuditEntity; +create table if not exists drools.IntegrityAuditEntity +( + id int not null auto_increment, + persistenceUnit varchar(100) not null, + site varchar(100), + nodeType varchar(100), + resourceName varchar(100) not null, + designated boolean default false, + jdbcDriver varchar(100) not null, + jdbcUrl varchar(100) not null, + jdbcUser varchar(30) not null, + jdbcPassword varchar(30) not null, + createdDate TIMESTAMP NOT NULL default current_timestamp, + lastUpdated TIMESTAMP NOT NULL, + primary key(id) +); + +alter table drools.IntegrityAuditEntity add constraint resourceName_uniq unique(resourceName); + + diff --git a/packages/base/src/files/data/mysql/161003_droolspdp_downgrade_script.sql b/packages/base/src/files/data/mysql/161003_droolspdp_downgrade_script.sql new file mode 100644 index 00000000..ba9ac573 --- /dev/null +++ b/packages/base/src/files/data/mysql/161003_droolspdp_downgrade_script.sql @@ -0,0 +1,22 @@ +/*- + * ============LICENSE_START======================================================= + * Base Package + * ================================================================================ + * 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========================================================= + */ + +drop table if exists drools.SEQUENCE; + diff --git a/packages/base/src/files/data/mysql/161003_droolspdp_upgrade_script.sql b/packages/base/src/files/data/mysql/161003_droolspdp_upgrade_script.sql new file mode 100644 index 00000000..7f8c17ca --- /dev/null +++ b/packages/base/src/files/data/mysql/161003_droolspdp_upgrade_script.sql @@ -0,0 +1,29 @@ +/*- + * ============LICENSE_START======================================================= + * Base Package + * ================================================================================ + * 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========================================================= + */ + +drop table if exists drools.SEQUENCE; +CREATE TABLE drools.SEQUENCE +( +SEQ_NAME VARCHAR(50) NOT NULL, +SEQ_COUNT NUMERIC(38), +PRIMARY KEY (SEQ_NAME) +); + +INSERT INTO drools.SEQUENCE (SEQ_NAME,SEQ_COUNT) VALUES ('SEQ_GEN',3050); diff --git a/packages/base/src/files/data/mysql/161004_droolspdp_downgrade_script.sql b/packages/base/src/files/data/mysql/161004_droolspdp_downgrade_script.sql new file mode 100644 index 00000000..0f756585 --- /dev/null +++ b/packages/base/src/files/data/mysql/161004_droolspdp_downgrade_script.sql @@ -0,0 +1,2 @@ +alter table drools.droolsPdpEntity modify updatedDate datetime not null; +alter table drools.droolsPdpEntity modify designatedDate datetime not null; diff --git a/packages/base/src/files/data/mysql/161004_droolspdp_upgrade_script.sql b/packages/base/src/files/data/mysql/161004_droolspdp_upgrade_script.sql new file mode 100644 index 00000000..f3a6cdda --- /dev/null +++ b/packages/base/src/files/data/mysql/161004_droolspdp_upgrade_script.sql @@ -0,0 +1,5 @@ +alter table drools.droolsPdpEntity modify updatedDate timestamp not null; +alter table drools.droolsPdpEntity modify designatedDate timestamp not null; + + +
\ No newline at end of file diff --git a/packages/base/src/files/data/mysql/170200_droolspdp_downgrade_script.sql b/packages/base/src/files/data/mysql/170200_droolspdp_downgrade_script.sql new file mode 100644 index 00000000..928a584e --- /dev/null +++ b/packages/base/src/files/data/mysql/170200_droolspdp_downgrade_script.sql @@ -0,0 +1,21 @@ +/*- + * ============LICENSE_START======================================================= + * Base Package + * ================================================================================ + * 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========================================================= + */ + +alter table drools.IntegrityAuditEntity modify jdbcUrl varchar(100) not null; diff --git a/packages/base/src/files/data/mysql/170200_droolspdp_upgrade_script.sql b/packages/base/src/files/data/mysql/170200_droolspdp_upgrade_script.sql new file mode 100644 index 00000000..93bb69e3 --- /dev/null +++ b/packages/base/src/files/data/mysql/170200_droolspdp_upgrade_script.sql @@ -0,0 +1,21 @@ +/*- + * ============LICENSE_START======================================================= + * Base Package + * ================================================================================ + * 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========================================================= + */ + +alter table drools.IntegrityAuditEntity modify jdbcUrl varchar(200) not null; diff --git a/packages/base/src/files/etc/cron.d/monitor.cron b/packages/base/src/files/etc/cron.d/monitor.cron new file mode 100755 index 00000000..b7321720 --- /dev/null +++ b/packages/base/src/files/etc/cron.d/monitor.cron @@ -0,0 +1 @@ +* * * * * export POLICY_HOME=${{POLICY_HOME}}; ${{POLICY_HOME}}/bin/monitor.sh >/dev/null 2>&1 diff --git a/packages/base/src/files/etc/monitor/monitor.cfg b/packages/base/src/files/etc/monitor/monitor.cfg new file mode 100644 index 00000000..afc6c714 --- /dev/null +++ b/packages/base/src/files/etc/monitor/monitor.cfg @@ -0,0 +1,6 @@ +# Line Format: component=status where +# component=<component name>, e.g. policy-management-controller +# status=on|off where +# on: component is to be monitored and should started +# off: component is to be monitored and should stopped +# There should be no component duplicate lines diff --git a/packages/base/src/files/etc/profile.d/env.sh b/packages/base/src/files/etc/profile.d/env.sh new file mode 100644 index 00000000..be8e7471 --- /dev/null +++ b/packages/base/src/files/etc/profile.d/env.sh @@ -0,0 +1,35 @@ +### +# ============LICENSE_START======================================================= +# Base Package +# ================================================================================ +# 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========================================================= +### + +export POLICY_HOME=${{POLICY_HOME}} +export JAVA_HOME=${{JAVA_HOME}} +export ENGINE_MANAGEMENT_USER=${{ENGINE_MANAGEMENT_USER}} +export ENGINE_MANAGEMENT_PASSWORD=${{ENGINE_MANAGEMENT_PASSWORD}} +export ENGINE_MANAGEMENT_PORT=${{ENGINE_MANAGEMENT_PORT}} +export ENGINE_MANAGEMENT_HOST=${{ENGINE_MANAGEMENT_HOST}} + +for x in $POLICY_HOME/bin $JAVA_HOME/bin $HOME/bin ; do + if [ -d $x ] ; then + case ":$PATH:" in + *":$x:"*) :;; # already there + *) PATH="$x:$PATH";; + esac + fi +done diff --git a/packages/base/src/files/etc/profile.d/su.cfg b/packages/base/src/files/etc/profile.d/su.cfg new file mode 100644 index 00000000..9cacea38 --- /dev/null +++ b/packages/base/src/files/etc/profile.d/su.cfg @@ -0,0 +1 @@ +# name=value pairs for su purposes diff --git a/packages/base/src/files/install/mysql/data/151000_downgrade_script.sql b/packages/base/src/files/install/mysql/data/151000_downgrade_script.sql new file mode 100644 index 00000000..d336c5c0 --- /dev/null +++ b/packages/base/src/files/install/mysql/data/151000_downgrade_script.sql @@ -0,0 +1,75 @@ +/*-
+ * ============LICENSE_START======================================================= + * Base Package + * ================================================================================ + * 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=========================================================
+ */
+
+use xacml;
+
+DROP TABLE IF EXISTS XACML.SYSTEMLOGDB;
+DROP TABLE IF EXISTS XACML.SEQUENCE;
+DROP TABLE IF EXISTS XACML.RULEALGORITHMS;
+DROP TABLE IF EXISTS XACML.ROLES;
+DROP TABLE IF EXISTS XACML.POLICYALGORITHMS;
+DROP TABLE IF EXISTS XACML.POLICY_MANANGEMENT;
+DROP TABLE IF EXISTS XACML.PIPRESOLVERPARAMS;
+DROP TABLE IF EXISTS XACML.PIPRESOLVER;
+DROP TABLE IF EXISTS XACML.PIPCONFIGPARAMS;
+DROP TABLE IF EXISTS XACML.PIPCONFIGURATION;
+DROP TABLE IF EXISTS XACML.PIPTYPE;
+DROP TABLE IF EXISTS XACML.OBADVICEEXPRESSIONS;
+DROP TABLE IF EXISTS XACML.GLOBALROLESETTINGS;
+DROP TABLE IF EXISTS XACML.FUNCTIONARGUMENTS;
+DROP TABLE IF EXISTS XACML.FUNCTIONDEFINITION;
+DROP TABLE IF EXISTS XACML.ECOMPNAME;
+DROP TABLE IF EXISTS XACML.DECISIONSETTINGS;
+DROP TABLE IF EXISTS XACML.ATTRIBUTEASSIGNMENT;
+DROP TABLE IF EXISTS XACML.CONSTRAINTVALUES;
+DROP TABLE IF EXISTS XACML.ATTRIBUTE;
+DROP TABLE IF EXISTS XACML.OBADVICE;
+DROP TABLE IF EXISTS XACML.CONSTRAINTTYPE;
+DROP TABLE IF EXISTS XACML.CATEGORY;
+DROP TABLE IF EXISTS XACML.DATATYPE;
+DROP TABLE IF EXISTS XACML.ACTIONPOLICYDICT;
+DROP TABLE IF EXISTS XACML.SERVICEGROUP;
+DROP TABLE IF EXISTS XACML.SECURITYZONE;
+DROP TABLE IF EXISTS XACML.POLICYENTITY;
+DROP TABLE IF EXISTS XACML.CONFIGURATIONDATAENTITY;
+DROP TABLE IF EXISTS XACML.POLICYDBDAOENTITY;
+
+DROP TABLE IF EXISTS XACML.POLICYSCORE;
+DROP TABLE IF EXISTS XACML.ACTIONLIST;
+DROP TABLE IF EXISTS XACML.PROTOCOLLIST;
+DROP TABLE IF EXISTS XACML.TERM;
+DROP TABLE IF EXISTS XACML.PREFIXLIST;
+DROP TABLE IF EXISTS XACML.SCOPE;
+DROP TABLE IF EXISTS XACML.ENFORCINGTYPE;
+DROP TABLE IF EXISTS XACML.PORTLIST;
+DROP TABLE IF EXISTS XACML.GROUPSERVICELIST;
+DROP TABLE IF EXISTS XACML.VSCLACTION;
+DROP TABLE IF EXISTS XACML.VNFTYPE;
+DROP TABLE IF EXISTS XACML.ADDRESSGROUP;
+
+-- DROP SEQUENCE IF EXISTS XACML.SEQCONFIG;
+-- DROP SEQUENCE IF EXISTS XACML.SEQPOLICY;
+
+DROP TABLE IF EXISTS LOG.SEQUENCE;
+DROP TABLE IF EXISTS LOG.SYSTEMLOGDB;
+
+DROP VIEW IF EXISTS xacml.match_functions;
+DROP VIEW IF EXISTS xacml.xacml.function_flattener;
+DROP VIEW IF EXISTS xacml.xacml.higherorder_bag_functions;
diff --git a/packages/base/src/files/install/mysql/data/151000_upgrade_script.sql b/packages/base/src/files/install/mysql/data/151000_upgrade_script.sql new file mode 100644 index 00000000..065d705f --- /dev/null +++ b/packages/base/src/files/install/mysql/data/151000_upgrade_script.sql @@ -0,0 +1,1563 @@ +/*-
+ * ============LICENSE_START=======================================================
+ * Base Package
+ * ================================================================================
+ * 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=========================================================
+ */
+
+use xacml;
+
+DROP TABLE IF EXISTS XACML.SYSTEMLOGDB;
+DROP TABLE IF EXISTS XACML.SEQUENCE;
+DROP TABLE IF EXISTS XACML.RULEALGORITHMS;
+DROP TABLE IF EXISTS XACML.ROLES;
+DROP TABLE IF EXISTS XACML.POLICYALGORITHMS;
+DROP TABLE IF EXISTS XACML.POLICY_MANANGEMENT;
+DROP TABLE IF EXISTS XACML.PIPRESOLVERPARAMS;
+DROP TABLE IF EXISTS XACML.PIPRESOLVER;
+DROP TABLE IF EXISTS XACML.PIPCONFIGPARAMS;
+DROP TABLE IF EXISTS XACML.PIPCONFIGURATION;
+DROP TABLE IF EXISTS XACML.PIPTYPE;
+DROP TABLE IF EXISTS XACML.OBADVICEEXPRESSIONS;
+DROP TABLE IF EXISTS XACML.GLOBALROLESETTINGS;
+DROP TABLE IF EXISTS XACML.FUNCTIONARGUMENTS;
+DROP TABLE IF EXISTS XACML.FUNCTIONDEFINITION;
+DROP TABLE IF EXISTS XACML.ECOMPNAME;
+DROP TABLE IF EXISTS XACML.DECISIONSETTINGS;
+DROP TABLE IF EXISTS XACML.ATTRIBUTEASSIGNMENT;
+DROP TABLE IF EXISTS XACML.CONSTRAINTVALUES;
+DROP TABLE IF EXISTS XACML.ATTRIBUTE;
+DROP TABLE IF EXISTS XACML.OBADVICE;
+DROP TABLE IF EXISTS XACML.CONSTRAINTTYPE;
+DROP TABLE IF EXISTS XACML.CATEGORY;
+DROP TABLE IF EXISTS XACML.DATATYPE;
+DROP TABLE IF EXISTS XACML.ACTIONPOLICYDICT;
+DROP TABLE IF EXISTS XACML.SERVICEGROUP;
+DROP TABLE IF EXISTS XACML.SECURITYZONE;
+DROP TABLE IF EXISTS XACML.VSCLACTION;
+DROP TABLE IF EXISTS XACML.VNFTYPE;
+DROP TABLE IF EXISTS XACML.POLICYENTITY;
+DROP TABLE IF EXISTS XACML.CONFIGURATIONDATAENTITY;
+DROP TABLE IF EXISTS XACML.PolicyDBDaoEntity;
+
+DROP TABLE IF EXISTS XACML.POLICYSCORE;
+DROP TABLE IF EXISTS XACML.ACTIONLIST;
+DROP TABLE IF EXISTS XACML.PROTOCOLLIST;
+DROP TABLE IF EXISTS XACML.TERM;
+DROP TABLE IF EXISTS XACML.PREFIXLIST;
+DROP TABLE IF EXISTS XACML.SCOPE;
+DROP TABLE IF EXISTS XACML.GROUPSERVICELIST;
+DROP TABLE IF EXISTS XACML.ENFORCINGTYPE;
+DROP TABLE IF EXISTS XACML.PORTLIST;
+DROP TABLE IF EXISTS XACML.ADDRESSGROUP;
+
+-- DROP SEQUENCE IF EXISTS XACML.SEQCONFIG;
+-- DROP SEQUENCE IF EXISTS XACML.SEQPOLICY;
+DROP TABLE IF EXISTS LOG.SEQUENCE;
+DROP TABLE IF EXISTS LOG.SYSTEMLOGDB;
+
+DROP VIEW IF EXISTS xacml.match_functions;
+DROP VIEW IF EXISTS xacml.function_flattener;
+DROP VIEW IF EXISTS xacml.higherorder_bag_functions;
+
+DROP TABLE IF EXISTS XACML.GroupServiceList;
+
+CREATE TABLE XACML.GroupServiceList
+(
+id INTEGER NOT NULL,
+name varchar(32),
+serviceList varchar(255),
+PRIMARY KEY (id)
+)
+;
+CREATE INDEX IDX_GROUPSERVICELIST ON XACML.GROUPSERVICELIst(ID);
+
+DROP TABLE IF EXISTS XACML.PolicyAlgorithms;
+
+CREATE TABLE XACML.PolicyAlgorithms
+(
+id INTEGER NOT NULL,
+ is_standard CHAR NOT NULL,
+ short_name VARCHAR(64) NOT NULL,
+ xacml_id VARCHAR(255) NOT NULL,
+ PRIMARY KEY (id)
+)
+;
+
+DROP TABLE IF EXISTS XACML.AttributeAssignment;
+
+CREATE TABLE XACML.AttributeAssignment
+(
+id INTEGER NOT NULL,
+ attribute_id INTEGER,
+ expression VARCHAR(5000) NOT NULL,
+ OBADVICE_id INTEGER,
+ PRIMARY KEY (id)
+)
+;
+
+DROP TABLE IF EXISTS XACML.roles;
+CREATE TABLE XACML.roles
+(
+id INTEGER NOT NULL,
+ attuid VARCHAR(45) NOT NULL,
+ role VARCHAR(45) NOT NULL,
+ scope VARCHAR(45),
+ PRIMARY KEY (id)
+)
+;
+
+DROP TABLE IF EXISTS XACML.POLICYSCORE;
+CREATE TABLE XACML.POLICYSCORE
+(
+POLICY_NAME VARCHAR(200) NOT NULL,
+ POLICY_SCORE VARCHAR(100),
+ PRIMARY KEY (POLICY_NAME)
+)
+;
+
+DROP TABLE IF EXISTS XACML.GlobalRoleSettings;
+CREATE TABLE XACML.GlobalRoleSettings
+(
+role VARCHAR(45) NOT NULL,
+ lockdown BOOLEAN,
+ PRIMARY KEY (role)
+)
+;
+
+DROP TABLE IF EXISTS XACML.PIPResolverParams;
+CREATE TABLE XACML.PIPResolverParams
+(
+id INTEGER NOT NULL,
+ PARAM_DEFAULT VARCHAR(2048),
+ PARAM_NAME VARCHAR(1024) NOT NULL,
+ PARAM_VALUE VARCHAR(2048) NOT NULL,
+ REQUIRED CHAR NOT NULL,
+ ID_RESOLVER INTEGER,
+ PRIMARY KEY (id)
+)
+;
+
+DROP TABLE IF EXISTS XACML.Attribute;
+CREATE TABLE XACML.Attribute
+(
+id INTEGER NOT NULL,
+ ATTRIBUTE_VALUE VARCHAR(255),
+ created_by VARCHAR(255) NOT NULL,
+ created_date TIMESTAMP,
+ description VARCHAR(2048),
+ is_designator CHAR NOT NULL,
+ modified_by VARCHAR(255) NOT NULL,
+ modified_date TIMESTAMP NOT NULL,
+ PRIORITY VARCHAR(45),
+ selector_path VARCHAR(2048),
+ xacml_id VARCHAR(100) NOT NULL UNIQUE,
+ category INTEGER,
+ constraint_type INTEGER,
+ datatype INTEGER,
+ PRIMARY KEY (id)
+)
+;
+
+DROP TABLE IF EXISTS XACML.FunctionArguments;
+CREATE TABLE XACML.FunctionArguments
+(
+id INTEGER NOT NULL,
+ arg_index INTEGER NOT NULL,
+ is_bag INTEGER NOT NULL,
+ datatype_id INTEGER,
+ function_id INTEGER,
+ PRIMARY KEY (id)
+)
+;
+
+DROP TABLE IF EXISTS XACML.actionlist;
+CREATE TABLE XACML.actionlist
+(
+id INTEGER NOT NULL,
+ actionname VARCHAR(45) NOT NULL,
+ description VARCHAR(64),
+ PRIMARY KEY (id)
+)
+;
+
+DROP TABLE IF EXISTS XACML.Obadvice;
+CREATE TABLE XACML.Obadvice
+(
+id INTEGER NOT NULL,
+ created_by VARCHAR(255) NOT NULL,
+ created_date TIMESTAMP NOT NULL,
+ description VARCHAR(2048),
+ fulfill_on VARCHAR(32),
+ modified_by VARCHAR(255) NOT NULL,
+ modified_date TIMESTAMP NOT NULL,
+ type VARCHAR(100) NOT NULL,
+ xacml_id VARCHAR(255) NOT NULL,
+ PRIMARY KEY (id)
+)
+;
+
+DROP TABLE IF EXISTS XACML.ObadviceExpressions;
+CREATE TABLE XACML.ObadviceExpressions
+(
+id INTEGER NOT NULL,
+ type VARCHAR(100) NOT NULL,
+ obadvice_id INTEGER,
+ attribute_id INTEGER,
+ PRIMARY KEY (id)
+)
+;
+
+DROP TABLE IF EXISTS XACML.RuleAlgorithms;
+CREATE TABLE XACML.RuleAlgorithms
+(
+id INTEGER NOT NULL,
+ is_standard CHAR NOT NULL,
+ short_name VARCHAR(64) NOT NULL,
+ xacml_id VARCHAR(255) NOT NULL UNIQUE,
+ PRIMARY KEY (id)
+)
+;
+
+DROP TABLE IF EXISTS XACML.ConstraintValues;
+CREATE TABLE XACML.ConstraintValues
+(
+id INTEGER NOT NULL,
+ property VARCHAR(1000),
+ value VARCHAR(1000),
+ attribute_id INTEGER,
+ PRIMARY KEY (id)
+)
+;
+
+DROP TABLE IF EXISTS XACML.DecisionSettings;
+CREATE TABLE XACML.DecisionSettings
+(
+id INTEGER NOT NULL,
+ created_by VARCHAR(255) NOT NULL,
+ created_date TIMESTAMP,
+ description VARCHAR(2048),
+ modified_by VARCHAR(255) NOT NULL,
+ modified_date TIMESTAMP NOT NULL,
+ PRIORITY VARCHAR(45),
+ xacml_id VARCHAR(45) NOT NULL UNIQUE,
+ datatype INTEGER,
+ PRIMARY KEY (id)
+)
+;
+
+DROP TABLE IF EXISTS XACML.policy_manangement;
+CREATE TABLE XACML.policy_manangement
+(
+id INTEGER NOT NULL,
+ CONFIG_NAME VARCHAR(45) NOT NULL,
+ CREATE_DATE_TIME TIMESTAMP NOT NULL,
+ CREATED_BY VARCHAR(45) NOT NULL,
+ ECOMP_NAME VARCHAR(45) NOT NULL,
+ POLICY_NAME VARCHAR(45) NOT NULL,
+ scope VARCHAR(45) NOT NULL,
+ UPDATE_DATE_TIME TIMESTAMP NOT NULL,
+ UPDATED_BY VARCHAR(45) NOT NULL,
+ XML text NOT NULL,
+ PRIMARY KEY (id)
+)
+;
+
+DROP TABLE IF EXISTS XACML.PIPConfiguration;
+CREATE TABLE XACML.PIPConfiguration
+(
+id INTEGER NOT NULL,
+ CLASSNAME VARCHAR(2048) NOT NULL,
+ CREATED_BY VARCHAR(255) NOT NULL,
+ CREATED_DATE TIMESTAMP NOT NULL,
+ DESCRIPTION VARCHAR(2048),
+ ISSUER VARCHAR(1024),
+ MODIFIED_BY VARCHAR(255) NOT NULL,
+ MODIFIED_DATE TIMESTAMP NOT NULL,
+ NAME VARCHAR(255) NOT NULL,
+ READ_ONLY CHAR NOT NULL,
+ REQUIRES_RESOLVER CHAR NOT NULL,
+ TYPE INTEGER,
+ PRIMARY KEY (id)
+)
+;
+
+DROP TABLE IF EXISTS XACML.protocollist;
+CREATE TABLE XACML.protocollist
+(
+id INTEGER NOT NULL,
+ description VARCHAR(64),
+ protocolname VARCHAR(45) NOT NULL,
+ PRIMARY KEY (id)
+)
+;
+
+
+DROP TABLE IF EXISTS XACML.FunctionDefinition;
+CREATE TABLE XACML.FunctionDefinition
+(
+id INTEGER NOT NULL,
+ arg_lb INTEGER NOT NULL,
+ arg_ub INTEGER NOT NULL,
+ ho_arg_lb INTEGER,
+ ho_arg_ub INTEGER,
+ ho_primitive CHAR,
+ is_bag_return INTEGER NOT NULL,
+ is_higher_order INTEGER NOT NULL,
+ short_name VARCHAR(64) NOT NULL,
+ xacml_id VARCHAR(255) NOT NULL,
+ return_datatype INTEGER,
+ PRIMARY KEY (id)
+)
+;
+
+DROP TABLE IF EXISTS XACML.PIPResolver;
+CREATE TABLE XACML.PIPResolver
+(
+id INTEGER NOT NULL,
+ CLASSNAME VARCHAR(2048) NOT NULL,
+ CREATED_BY VARCHAR(255) NOT NULL,
+ CREATED_DATE TIMESTAMP NOT NULL,
+ DESCRIPTION VARCHAR(2048),
+ ISSUER VARCHAR(1024),
+ MODIFIED_BY VARCHAR(255) NOT NULL,
+ MODIFIED_DATE TIMESTAMP NOT NULL,
+ NAME VARCHAR(255) NOT NULL,
+ READ_ONLY CHAR NOT NULL,
+ PIP_ID INTEGER,
+ PRIMARY KEY (id)
+)
+;
+
+DROP TABLE IF EXISTS XACML.TERM;
+CREATE TABLE XACML.TERM
+(
+id INTEGER NOT NULL,
+ description VARCHAR(100),
+ action VARCHAR(100),
+ destIPList VARCHAR(100),
+ destPortList VARCHAR(100),
+ portList VARCHAR(100),
+ protocolList VARCHAR(100),
+ srcIPList VARCHAR(100),
+ srcPortList VARCHAR(100),
+ termName VARCHAR(45) NOT NULL,
+ PRIMARY KEY (id)
+)
+;
+
+DROP TABLE IF EXISTS XACML.PREFIXLIST;
+CREATE TABLE XACML.PREFIXLIST
+(
+id INTEGER NOT NULL,
+ pl_name VARCHAR(45) NOT NULL,
+ pl_value VARCHAR(64) NOT NULL,
+ description VARCHAR(255),
+ PRIMARY KEY (id)
+)
+;
+
+DROP TABLE IF EXISTS XACML.Datatype;
+CREATE TABLE XACML.Datatype
+(
+id INTEGER NOT NULL,
+ is_standard CHAR NOT NULL,
+ short_name VARCHAR(64) NOT NULL,
+ xacml_id VARCHAR(255) NOT NULL UNIQUE,
+ PRIMARY KEY (id)
+)
+;
+
+DROP TABLE IF EXISTS XACML.PIPType;
+CREATE TABLE XACML.PIPType
+(
+id INTEGER NOT NULL,
+ type VARCHAR(45) NOT NULL,
+ PRIMARY KEY (id)
+)
+;
+
+DROP TABLE IF EXISTS XACML.ActionPolicyDict;
+CREATE TABLE XACML.ActionPolicyDict
+(
+id INTEGER NOT NULL,
+ ATTRIBUTE_NAME VARCHAR(45) NOT NULL,
+ Body VARCHAR(4096),
+ created_by VARCHAR(255) NOT NULL,
+ created_date TIMESTAMP,
+ description VARCHAR(2048),
+ Headers VARCHAR(1024),
+ Method VARCHAR(45) NOT NULL,
+ modified_by VARCHAR(255) NOT NULL,
+ modified_date TIMESTAMP NOT NULL,
+ Type VARCHAR(45) NOT NULL,
+ URL VARCHAR(45) NOT NULL,
+ PRIMARY KEY (id)
+)
+;
+
+DROP TABLE IF EXISTS XACML.Category;
+CREATE TABLE XACML.Category
+(
+id INTEGER NOT NULL,
+ grouping VARCHAR(64) NOT NULL,
+ is_standard CHAR NOT NULL,
+ short_name VARCHAR(64) NOT NULL,
+ xacml_id VARCHAR(255) NOT NULL UNIQUE,
+ PRIMARY KEY (id)
+)
+;
+
+DROP TABLE IF EXISTS XACML.Scope;
+CREATE TABLE XACML.Scope
+(
+scopeId BIGINT NOT NULL,
+ parentScope BIGINT,
+ scopeName VARCHAR(255) NOT NULL,
+ PRIMARY KEY (scopeId)
+)
+;
+CREATE INDEX parentScope ON Scope (parentScope);
+
+DROP TABLE IF EXISTS XACML.EcompName;
+CREATE TABLE XACML.EcompName
+(
+id INTEGER NOT NULL,
+ created_by VARCHAR(255) NOT NULL,
+ created_date TIMESTAMP,
+ description VARCHAR(2048),
+ ecomp_Name VARCHAR(100) NOT NULL UNIQUE,
+ modified_by VARCHAR(255) NOT NULL,
+ modified_date TIMESTAMP NOT NULL,
+ PRIMARY KEY (id)
+)
+;
+
+DROP TABLE IF EXISTS XACML.ConstraintType;
+CREATE TABLE XACML.ConstraintType
+(
+id INTEGER NOT NULL,
+ constraint_type VARCHAR(64) NOT NULL,
+ description VARCHAR(255) NOT NULL,
+ PRIMARY KEY (id)
+)
+;
+
+DROP TABLE IF EXISTS XACML.EnforcingType;
+CREATE TABLE XACML.EnforcingType
+(
+id INTEGER NOT NULL,
+ connectionQuery VARCHAR(255) NOT NULL,
+ enforcingType VARCHAR(255) NOT NULL UNIQUE,
+ script VARCHAR(255) NOT NULL,
+ valueQuery VARCHAR(255) NOT NULL,
+ PRIMARY KEY (id)
+)
+;
+
+DROP TABLE IF EXISTS XACML.PIPConfigParams;
+CREATE TABLE XACML.PIPConfigParams
+(
+id INTEGER NOT NULL,
+ PARAM_DEFAULT VARCHAR(2048),
+ PARAM_NAME VARCHAR(1024) NOT NULL,
+ PARAM_VALUE VARCHAR(2048) NOT NULL,
+ REQUIRED CHAR NOT NULL,
+ PIP_ID INTEGER,
+ PRIMARY KEY (id)
+)
+;
+
+DROP TABLE IF EXISTS XACML.portlist;
+CREATE TABLE XACML.portlist
+(
+id INTEGER NOT NULL,
+ description VARCHAR(64),
+ portname VARCHAR(45) NOT NULL,
+ PRIMARY KEY (id)
+)
+;
+
+DROP TABLE IF EXISTS XACML.SEQUENCE;
+CREATE TABLE XACML.SEQUENCE
+(
+SEQ_NAME VARCHAR(50) NOT NULL,
+ SEQ_COUNT NUMERIC(38),
+ PRIMARY KEY (SEQ_NAME)
+)
+;
+-- INSERT INTO SEQUENCE(SEQ_NAME, SEQ_COUNT) values ('SEQ_GEN', 0);
+-- CREATE SEQUENCE seq START WITH 1;
+
+DROP TABLE IF EXISTS XACML.SYSTEMLOGDB;
+CREATE TABLE XACML.SYSTEMLOGDB
+(
+ id INTEGER NOT NULL AUTO_INCREMENT,
+ system VARCHAR(255) NOT NULL,
+ description VARCHAR(2048),
+ remote VARCHAR(255) NOT NULL,
+ type VARCHAR(10) NOT NULL,
+ date TIMESTAMP NOT NULL,
+ logtype VARCHAR(255) NOT NULL,
+ PRIMARY KEY (id)
+)
+
+;
+
+DROP TABLE IF EXISTS LOG.SEQUENCE;
+CREATE TABLE LOG.SEQUENCE
+(
+SEQ_NAME VARCHAR(50) NOT NULL,
+ SEQ_COUNT NUMERIC(38),
+ PRIMARY KEY (SEQ_NAME)
+)
+;
+
+DROP TABLE IF EXISTS LOG.SYSTEMLOGDB;
+CREATE TABLE LOG.SYSTEMLOGDB
+(
+ id INTEGER NOT NULL AUTO_INCREMENT,
+ system VARCHAR(255) NOT NULL,
+ description VARCHAR(2048),
+ remote VARCHAR(255) NOT NULL,
+ type VARCHAR(10) NOT NULL,
+ date TIMESTAMP NOT NULL,
+ logtype VARCHAR(255) NOT NULL,
+ PRIMARY KEY (id)
+)
+;
+
+drop table if exists SUPPORT.DB_VERSION;
+create table SUPPORT.DB_VERSION
+(
+ the_key varchar(20) primary key not null,
+ version varchar(20)
+)
+;
+
+DROP TABLE IF EXISTS XACML.SERVICEGROUP;
+CREATE TABLE XACML.SERVICEGROUP
+(
+id integer NOT NULL,
+name varchar(32),
+type varchar(16),
+transportprotocol varchar(255),
+appprotocol varchar(255),
+ports varchar(255),
+`desc` varchar(255),
+primary key(id)
+)
+;
+
+DROP TABLE IF EXISTS XACML.SECURITYZONE;
+CREATE TABLE XACML.SECURITYZONE
+(
+id integer NOT NULL,
+name varchar(32),
+value varchar(64),
+primary key(id)
+)
+;
+
+CREATE TABLE XACML.VSCLACTION
+(
+ID INTEGER NOT NULL,
+VSCL_ACTION VARCHAR(45) NOT NULL,
+DESCRIPTION VARCHAR(45) NULL,
+CREATED_DATE TIMESTAMP NOT NULL,
+CREATED_BY VARCHAR(45) NOT NULL,
+MODIFIED_DATE TIMESTAMP NOT NULL,
+MODIFIED_BY VARCHAR(45) NOT NULL,
+PRIMARY KEY(ID)
+);
+
+CREATE TABLE XACML.VNFTYPE
+(
+ID INTEGER NOT NULL,
+VNF_TYPE VARCHAR(45) NOT NULL,
+DESCRIPTION VARCHAR(45) NULL,
+CREATED_DATE TIMESTAMP NOT NULL,
+CREATED_BY VARCHAR(45) NOT NULL,
+MODIFIED_DATE TIMESTAMP NOT NULL,
+MODIFIED_BY VARCHAR(45) NOT NULL,
+PRIMARY KEY(ID)
+)
+;
+
+DROP TABLE IF EXISTS XACML.POLICYENTITY;
+CREATE TABLE XACML.PolicyEntity
+(
+policyId BIGINT NOT NULL,
+ created_by VARCHAR(255) NOT NULL,
+ created_date TIMESTAMP,
+ deleted BOOLEAN NOT NULL,
+ description VARCHAR(2048) NOT NULL,
+ modified_by VARCHAR(255) NOT NULL,
+ modified_date TIMESTAMP NOT NULL,
+ policyData TEXT,
+ policyName VARCHAR(255) NOT NULL,
+ scope VARCHAR(255) NOT NULL,
+ version INTEGER,
+ configurationDataId BIGINT,
+ PRIMARY KEY (policyId))
+;
+CREATE INDEX scope ON XACML.PolicyEntity (scope);
+CREATE INDEX policyName ON XACML.PolicyEntity (policyName);
+
+DROP TABLE IF EXISTS XACML.ConfigurationDataEntity;
+CREATE TABLE XACML.ConfigurationDataEntity
+(
+configurationDataId BIGINT NOT NULL,
+ configBody TEXT,
+ configType VARCHAR(255) NOT NULL,
+ configurationName VARCHAR(255) NOT NULL,
+ created_by VARCHAR(255) NOT NULL,
+ created_date TIMESTAMP,
+ deleted BOOLEAN NOT NULL,
+ description VARCHAR(2048) NOT NULL,
+ modified_by VARCHAR(255) NOT NULL,
+ modified_date TIMESTAMP NOT NULL,
+ version INTEGER,
+ PRIMARY KEY (configurationDataId))
+;
+
+DROP TABLE IF EXISTS XACML.PolicyDBDaoEntity;
+CREATE TABLE XACML.PolicyDBDaoEntity
+(
+ policyDBDaoUrl VARCHAR(500) NOT NULL UNIQUE,
+ created_date TIMESTAMP,
+ description VARCHAR(2048) NOT NULL,
+ modified_date TIMESTAMP NOT NULL,
+ PRIMARY KEY (policyDBDaoUrl))
+;
+
+DROP TABLE IF EXISTS XACML.ADDRESSGROUP;
+CREATE TABLE ADDRESSGROUP
+(
+ id INTEGER NOT NULL,
+ name varchar(32),
+ description VARCHAR(64),
+ prefixlist varchar(255)
+);
+
+create index idx_addressgroup on ADDRESSGROUP(ID);
+
+
+
+create or replace view xacml.match_functions
+as select d.id as id, d.short_name as shortname, d.xacml_id as xacmlid,
+d.return_datatype as return_datatype, d.is_bag_return as is_bag_return,
+d.arg_lb as arg_lb, d.arg_ub as arg_ub, a1.is_bag as arg1_isbag,
+a1.datatype_id as arg1_datatype, a2.is_bag as arg2_isbag,
+a2.datatype_id as arg2_datatype
+from (xacml.functiondefinition d
+left join xacml.functionarguments a1 on (a1.function_id = d.id and a1.arg_index = 1)
+left join xacml.functionarguments a2 on (a2.function_id = d.id and a2.arg_index = 2))
+where (d.arg_lb = 2 and d.arg_ub = 2 and d.return_datatype = 18 and a1.is_bag = 0)
+order by d.short_name;
+
+create or replace view xacml.function_flattener
+as select d.id as id, d.short_name as shortname,
+d.return_datatype as return_datatype, d.is_bag_return as is_bag_return,
+d.is_higher_order as is_higher_order, d.arg_lb as arg_lb, d.arg_ub as arg_ub,
+a1.is_bag as arg1_isbag, a1.datatype_id as arg1_datatype, a2.is_bag as arg2_isbag,
+a2.datatype_id as arg2_datatype, a3.is_bag as arg3_isbag,
+a3.datatype_id as arg3_datatype
+from (xacml.functiondefinition d left join xacml.functionarguments a1
+on (a1.function_id = d.id and a1.arg_index = 1)
+left join xacml.functionarguments a2 on (a2.function_id = d.id and a2.arg_index = 2)
+left join xacml.functionarguments a3 on (a3.function_id = d.id and a3.arg_index = 3))
+order by d.id;
+
+create or replace view xacml.higherorder_bag_functions
+as select * from xacml.function_flattener
+where is_higher_order = 1 and is_bag_return = 1 and return_datatype=18
+and arg_lb=2 and arg_ub=2 and arg1_isbag = 1 and (arg2_isbag = 1 or arg2_isbag is null);
+
+GRANT SELECT, INSERT, UPDATE, DELETE ON XACML.SYSTEMLOGDB TO policy_user;
+GRANT SELECT, INSERT, UPDATE, DELETE ON XACML.SEQUENCE TO policy_user;
+GRANT SELECT, INSERT, UPDATE, DELETE ON XACML.RULEALGORITHMS TO policy_user;
+GRANT SELECT, INSERT, UPDATE, DELETE ON XACML.ROLES TO policy_user;
+GRANT SELECT, INSERT, UPDATE, DELETE ON XACML.POLICYALGORITHMS TO policy_user;
+GRANT SELECT, INSERT, UPDATE, DELETE ON XACML.POLICY_MANANGEMENT TO policy_user;
+GRANT SELECT, INSERT, UPDATE, DELETE ON XACML.PIPRESOLVERPARAMS TO policy_user;
+GRANT SELECT, INSERT, UPDATE, DELETE ON XACML.PIPRESOLVER TO policy_user;
+GRANT SELECT, INSERT, UPDATE, DELETE ON XACML.PIPCONFIGPARAMS TO policy_user;
+GRANT SELECT, INSERT, UPDATE, DELETE ON XACML.PIPCONFIGURATION TO policy_user;
+GRANT SELECT, INSERT, UPDATE, DELETE ON XACML.PIPTYPE TO policy_user;
+GRANT SELECT, INSERT, UPDATE, DELETE ON XACML.OBADVICEEXPRESSIONS TO policy_user;
+GRANT SELECT, INSERT, UPDATE, DELETE ON XACML.GLOBALROLESETTINGS TO policy_user;
+GRANT SELECT, INSERT, UPDATE, DELETE ON XACML.FUNCTIONARGUMENTS TO policy_user;
+GRANT SELECT, INSERT, UPDATE, DELETE ON XACML.FUNCTIONDEFINITION TO policy_user;
+GRANT SELECT, INSERT, UPDATE, DELETE ON XACML.ECOMPNAME TO policy_user;
+GRANT SELECT, INSERT, UPDATE, DELETE ON XACML.DECISIONSETTINGS TO policy_user;
+GRANT SELECT, INSERT, UPDATE, DELETE ON XACML.ATTRIBUTEASSIGNMENT TO policy_user;
+GRANT SELECT, INSERT, UPDATE, DELETE ON XACML.CONSTRAINTVALUES TO policy_user;
+GRANT SELECT, INSERT, UPDATE, DELETE ON XACML.ATTRIBUTE TO policy_user;
+GRANT SELECT, INSERT, UPDATE, DELETE ON XACML.OBADVICE TO policy_user;
+GRANT SELECT, INSERT, UPDATE, DELETE ON XACML.CONSTRAINTTYPE TO policy_user;
+GRANT SELECT, INSERT, UPDATE, DELETE ON XACML.CATEGORY TO policy_user;
+GRANT SELECT, INSERT, UPDATE, DELETE ON XACML.DATATYPE TO policy_user;
+GRANT SELECT, INSERT, UPDATE, DELETE ON XACML.ACTIONPOLICYDICT TO policy_user;
+GRANT SELECT, INSERT, UPDATE, DELETE ON XACML.POLICYENTITY TO policy_user;
+GRANT SELECT, INSERT, UPDATE, DELETE ON XACML.CONFIGURATIONDATAENTITY TO policy_user;
+GRANT SELECT, INSERT, UPDATE, DELETE ON XACML.PolicyDBDaoEntity TO policy_user;
+
+GRANT SELECT, INSERT, UPDATE, DELETE ON XACML.POLICYSCORE TO policy_user;
+GRANT SELECT, INSERT, UPDATE, DELETE ON XACML.ACTIONLIST TO policy_user;
+GRANT SELECT, INSERT, UPDATE, DELETE ON XACML.PROTOCOLLIST TO policy_user;
+GRANT SELECT, INSERT, UPDATE, DELETE ON XACML.TERM TO policy_user;
+GRANT SELECT, INSERT, UPDATE, DELETE ON XACML.PREFIXLIST TO policy_user;
+GRANT SELECT, INSERT, UPDATE, DELETE ON XACML.SCOPE TO policy_user;
+GRANT SELECT, INSERT, UPDATE, DELETE ON XACML.ENFORCINGTYPE TO policy_user;
+GRANT SELECT, INSERT, UPDATE, DELETE ON XACML.PORTLIST TO policy_user;
+GRANT SELECT, INSERT, UPDATE, DELETE ON XACML.GROUPSERVICELIST TO policy_user;
+GRANT SELECT, INSERT, UPDATE, DELETE ON XACML.VSCLACTION TO policy_user;
+GRANT SELECT, INSERT, UPDATE, DELETE ON XACML.VNFTYPE TO policy_user;
+GRANT SELECT, INSERT, UPDATE, DELETE ON XACML.ADDRESSGROUP TO policy_user;
+
+GRANT SELECT, INSERT, UPDATE, DELETE ON LOG.SEQUENCE TO policy_user;
+GRANT SELECT, INSERT, UPDATE, DELETE ON LOG.SYSTEMLOGDB TO policy_user;
+
+grant insert, update, delete, select on support.db_version to policy_user;
+grant select on xacml.match_functions to policy_user;
+grant select on xacml.function_flattener to policy_user;
+grant select on xacml.higherorder_bag_functions to policy_user;
+
+
+
+INSERT INTO XACML.ATTRIBUTE (ID,CREATED_BY,CREATED_DATE,DESCRIPTION,IS_DESIGNATOR,MODIFIED_BY,MODIFIED_DATE,SELECTOR_PATH,XACML_ID,CATEGORY,CONSTRAINT_TYPE,DATATYPE,PRIORITY,ATTRIBUTE_VALUE) VALUES (1401,'super-admin',str_to_date('2015-05-11 19:56:54.930000','%Y-%m-%d %H:%i:%s.%f'),null,'1','super-admin',str_to_date('2015-05-11 19:56:54.930000','%Y-%m-%d %H:%i:%s.%f'),null,'true',5,null,18,null,null);
+INSERT INTO XACML.ATTRIBUTE (ID,CREATED_BY,CREATED_DATE,DESCRIPTION,IS_DESIGNATOR,MODIFIED_BY,MODIFIED_DATE,SELECTOR_PATH,XACML_ID,CATEGORY,CONSTRAINT_TYPE,DATATYPE,PRIORITY,ATTRIBUTE_VALUE) VALUES (1455,'super-admin',str_to_date('2015-05-13 14:10:44.134000','%Y-%m-%d %H:%i:%s.%f'),null,'1','super-admin',str_to_date('2015-05-13 14:10:44.134000','%Y-%m-%d %H:%i:%s.%f'),null,'Test-Kat',5,null,26,'High',null);
+INSERT INTO XACML.ATTRIBUTE (ID,CREATED_BY,CREATED_DATE,DESCRIPTION,IS_DESIGNATOR,MODIFIED_BY,MODIFIED_DATE,SELECTOR_PATH,XACML_ID,CATEGORY,CONSTRAINT_TYPE,DATATYPE,PRIORITY,ATTRIBUTE_VALUE) VALUES (1551,'super-admin',str_to_date('2015-05-22 11:40:23.118000','%Y-%m-%d %H:%i:%s.%f'),null,'1','super-admin',str_to_date('2015-05-22 11:40:23.118000','%Y-%m-%d %H:%i:%s.%f'),null,'test',5,null,26,null,null);
+INSERT INTO XACML.ATTRIBUTE (ID,CREATED_BY,CREATED_DATE,DESCRIPTION,IS_DESIGNATOR,MODIFIED_BY,MODIFIED_DATE,SELECTOR_PATH,XACML_ID,CATEGORY,CONSTRAINT_TYPE,DATATYPE,PRIORITY,ATTRIBUTE_VALUE) VALUES (1926,'super-admin',str_to_date('2015-06-09 11:42:16.580000','%Y-%m-%d %H:%i:%s.%f'),'Hour when maintenance window starts (0 to 24)','1','super-admin',str_to_date('2015-06-11 23:29:46.407000','%Y-%m-%d %H:%i:%s.%f'),null,'Window_Thursday_Start:',5,null,12,null,null);
+INSERT INTO XACML.ATTRIBUTE (ID,CREATED_BY,CREATED_DATE,DESCRIPTION,IS_DESIGNATOR,MODIFIED_BY,MODIFIED_DATE,SELECTOR_PATH,XACML_ID,CATEGORY,CONSTRAINT_TYPE,DATATYPE,PRIORITY,ATTRIBUTE_VALUE) VALUES (1927,'super-admin',str_to_date('2015-06-09 11:42:33.966000','%Y-%m-%d %H:%i:%s.%f'),'Hour when maintenance window starts (0 to 24)','1','super-admin',str_to_date('2015-06-11 23:29:24.841000','%Y-%m-%d %H:%i:%s.%f'),null,'Window_Friday_Start:',5,null,12,null,null);
+INSERT INTO XACML.ATTRIBUTE (ID,CREATED_BY,CREATED_DATE,DESCRIPTION,IS_DESIGNATOR,MODIFIED_BY,MODIFIED_DATE,SELECTOR_PATH,XACML_ID,CATEGORY,CONSTRAINT_TYPE,DATATYPE,PRIORITY,ATTRIBUTE_VALUE) VALUES (1928,'super-admin',str_to_date('2015-06-09 11:42:49.867000','%Y-%m-%d %H:%i:%s.%f'),'Hour when maintenance window starts (0 to 24)','1','super-admin',str_to_date('2015-06-11 23:29:32.730000','%Y-%m-%d %H:%i:%s.%f'),null,'Window_Saturday_Start:',5,null,12,null,null);
+INSERT INTO XACML.ATTRIBUTE (ID,CREATED_BY,CREATED_DATE,DESCRIPTION,IS_DESIGNATOR,MODIFIED_BY,MODIFIED_DATE,SELECTOR_PATH,XACML_ID,CATEGORY,CONSTRAINT_TYPE,DATATYPE,PRIORITY,ATTRIBUTE_VALUE) VALUES (1929,'super-admin',str_to_date('2015-06-09 11:43:11.486000','%Y-%m-%d %H:%i:%s.%f'),'Hour when maintenance window starts (0 to 24)','1','super-admin',str_to_date('2015-06-11 23:34:08.866000','%Y-%m-%d %H:%i:%s.%f'),null,'Window_Sunday_Start:',5,null,12,null,null);
+INSERT INTO XACML.ATTRIBUTE (ID,CREATED_BY,CREATED_DATE,DESCRIPTION,IS_DESIGNATOR,MODIFIED_BY,MODIFIED_DATE,SELECTOR_PATH,XACML_ID,CATEGORY,CONSTRAINT_TYPE,DATATYPE,PRIORITY,ATTRIBUTE_VALUE) VALUES (1954,'super-admin',str_to_date('2015-06-11 23:30:12.656000','%Y-%m-%d %H:%i:%s.%f'),'Hour when maintenance window ends (0 to 24)','1','super-admin',str_to_date('2015-06-11 23:30:39.869000','%Y-%m-%d %H:%i:%s.%f'),null,'Window _Monday_End:',5,null,12,null,null);
+INSERT INTO XACML.ATTRIBUTE (ID,CREATED_BY,CREATED_DATE,DESCRIPTION,IS_DESIGNATOR,MODIFIED_BY,MODIFIED_DATE,SELECTOR_PATH,XACML_ID,CATEGORY,CONSTRAINT_TYPE,DATATYPE,PRIORITY,ATTRIBUTE_VALUE) VALUES (1955,'super-admin',str_to_date('2015-06-11 23:30:46.701000','%Y-%m-%d %H:%i:%s.%f'),'Hour when maintenance window ends (0 to 24)','1','super-admin',str_to_date('2015-06-11 23:32:01.698000','%Y-%m-%d %H:%i:%s.%f'),null,'Window_Friday_End:',5,null,12,null,null);
+INSERT INTO XACML.ATTRIBUTE (ID,CREATED_BY,CREATED_DATE,DESCRIPTION,IS_DESIGNATOR,MODIFIED_BY,MODIFIED_DATE,SELECTOR_PATH,XACML_ID,CATEGORY,CONSTRAINT_TYPE,DATATYPE,PRIORITY,ATTRIBUTE_VALUE) VALUES (1956,'super-admin',str_to_date('2015-06-11 23:31:10.449000','%Y-%m-%d %H:%i:%s.%f'),'Hour when maintenance window ends (0 to 24)','1','super-admin',str_to_date('2015-06-11 23:31:42.361000','%Y-%m-%d %H:%i:%s.%f'),null,'Window_Saturday_End:',5,null,12,null,null);
+INSERT INTO XACML.ATTRIBUTE (ID,CREATED_BY,CREATED_DATE,DESCRIPTION,IS_DESIGNATOR,MODIFIED_BY,MODIFIED_DATE,SELECTOR_PATH,XACML_ID,CATEGORY,CONSTRAINT_TYPE,DATATYPE,PRIORITY,ATTRIBUTE_VALUE) VALUES (1957,'super-admin',str_to_date('2015-06-11 23:32:25.542000','%Y-%m-%d %H:%i:%s.%f'),'Hour when maintenance window ends (0 to 24)','1','super-admin',str_to_date('2015-06-11 23:32:45.215000','%Y-%m-%d %H:%i:%s.%f'),null,'Window_Sunday_End:',5,null,12,null,null);
+INSERT INTO XACML.ATTRIBUTE (ID,CREATED_BY,CREATED_DATE,DESCRIPTION,IS_DESIGNATOR,MODIFIED_BY,MODIFIED_DATE,SELECTOR_PATH,XACML_ID,CATEGORY,CONSTRAINT_TYPE,DATATYPE,PRIORITY,ATTRIBUTE_VALUE) VALUES (1958,'super-admin',str_to_date('2015-06-11 23:32:55.89000','%Y-%m-%d %H:%i:%s.%f'),'Hour when maintenance window ends (0 to 24)','1','super-admin',str_to_date('2015-06-11 23:33:11.766000','%Y-%m-%d %H:%i:%s.%f'),null,'Window_Thursday_End:',5,null,12,null,null);
+INSERT INTO XACML.ATTRIBUTE (ID,CREATED_BY,CREATED_DATE,DESCRIPTION,IS_DESIGNATOR,MODIFIED_BY,MODIFIED_DATE,SELECTOR_PATH,XACML_ID,CATEGORY,CONSTRAINT_TYPE,DATATYPE,PRIORITY,ATTRIBUTE_VALUE) VALUES (1959,'super-admin',str_to_date('2015-06-11 23:33:28.664000','%Y-%m-%d %H:%i:%s.%f'),'Hour when maintenance window ends (0 to 24)','1','super-admin',str_to_date('2015-06-11 23:33:47.905000','%Y-%m-%d %H:%i:%s.%f'),null,'Window_Tuesday_End:',5,null,12,null,null);
+INSERT INTO XACML.ATTRIBUTE (ID,CREATED_BY,CREATED_DATE,DESCRIPTION,IS_DESIGNATOR,MODIFIED_BY,MODIFIED_DATE,SELECTOR_PATH,XACML_ID,CATEGORY,CONSTRAINT_TYPE,DATATYPE,PRIORITY,ATTRIBUTE_VALUE) VALUES (1960,'super-admin',str_to_date('2015-06-11 23:34:18.912000','%Y-%m-%d %H:%i:%s.%f'),'Hour when maintenance window ends (0 to 24)','1','super-admin',str_to_date('2015-06-11 23:35:12.283000','%Y-%m-%d %H:%i:%s.%f'),null,'Window_Wednesday_End:',5,null,12,null,null);
+INSERT INTO XACML.ATTRIBUTE (ID,CREATED_BY,CREATED_DATE,DESCRIPTION,IS_DESIGNATOR,MODIFIED_BY,MODIFIED_DATE,SELECTOR_PATH,XACML_ID,CATEGORY,CONSTRAINT_TYPE,DATATYPE,PRIORITY,ATTRIBUTE_VALUE) VALUES (2904,'super-admin',str_to_date('2015-08-24 18:06:29.370000','%Y-%m-%d %H:%i:%s.%f'),'Test','1','super-admin',str_to_date('2015-08-24 18:06:29.370000','%Y-%m-%d %H:%i:%s.%f'),null,'KK1:(0)',5,null,26,null,null);
+
+
+
+
+INSERT INTO XACML.CATEGORY (ID,GROUPING,IS_STANDARD,SHORT_NAME,XACML_ID) VALUES (4,'subject','S','intermediary-subject','urn:oasis:names:tc:xacml:1.0:subject-category:intermediary-subject');
+INSERT INTO XACML.CATEGORY (ID,GROUPING,IS_STANDARD,SHORT_NAME,XACML_ID) VALUES (5,'resource','S','resource','urn:oasis:names:tc:xacml:3.0:attribute-category:resource');
+INSERT INTO XACML.CATEGORY (ID,GROUPING,IS_STANDARD,SHORT_NAME,XACML_ID) VALUES (6,'subject','S','codebase','urn:oasis:names:tc:xacml:1.0:subject-category:codebase');
+INSERT INTO XACML.CATEGORY (ID,GROUPING,IS_STANDARD,SHORT_NAME,XACML_ID) VALUES (7,'action','S','action','urn:oasis:names:tc:xacml:3.0:attribute-category:action');
+INSERT INTO XACML.CATEGORY (ID,GROUPING,IS_STANDARD,SHORT_NAME,XACML_ID) VALUES (8,'subject','S','access-subject','urn:oasis:names:tc:xacml:1.0:subject-category:access-subject');
+INSERT INTO XACML.CATEGORY (ID,GROUPING,IS_STANDARD,SHORT_NAME,XACML_ID) VALUES (9,'environment','S','environment','urn:oasis:names:tc:xacml:3.0:attribute-category:environment');
+INSERT INTO XACML.CATEGORY (ID,GROUPING,IS_STANDARD,SHORT_NAME,XACML_ID) VALUES (10,'subject','S','requesting-machine','urn:oasis:names:tc:xacml:1.0:subject-category:requesting-machine');
+INSERT INTO XACML.CATEGORY (ID,GROUPING,IS_STANDARD,SHORT_NAME,XACML_ID) VALUES (11,'subject','S','recipient-subject','urn:oasis:names:tc:xacml:1.0:subject-category:recipient-subject');
+
+
+INSERT INTO XACML.CONSTRAINTTYPE (ID,CONSTRAINT_TYPE,DESCRIPTION) VALUES (1,'Range','Set a range of min and/or max integer/double values the attribute can be set to during policy creation.');
+INSERT INTO XACML.CONSTRAINTTYPE (ID,CONSTRAINT_TYPE,DESCRIPTION) VALUES (2,'Regular Expression','Define a regular expression the attribute must match against during policy creation.');
+INSERT INTO XACML.CONSTRAINTTYPE (ID,CONSTRAINT_TYPE,DESCRIPTION) VALUES (3,'Enumeration','Enumerate a set of values that the attribute may be set to during policy creation.');
+
+
+
+
+
+INSERT INTO XACML.DATATYPE (ID,IS_STANDARD,SHORT_NAME,XACML_ID) VALUES (12,'S','integer','http://www.w3.org/2001/XMLSchema#integer');
+INSERT INTO XACML.DATATYPE (ID,IS_STANDARD,SHORT_NAME,XACML_ID) VALUES (13,'S','base64Binary','http://www.w3.org/2001/XMLSchema#base64Binary');
+INSERT INTO XACML.DATATYPE (ID,IS_STANDARD,SHORT_NAME,XACML_ID) VALUES (14,'S','x500Name','urn:oasis:names:tc:xacml:1.0:data-type:x500Name');
+INSERT INTO XACML.DATATYPE (ID,IS_STANDARD,SHORT_NAME,XACML_ID) VALUES (15,'S','dayTimeDuration','http://www.w3.org/2001/XMLSchema#dayTimeDuration');
+INSERT INTO XACML.DATATYPE (ID,IS_STANDARD,SHORT_NAME,XACML_ID) VALUES (16,'S','time','http://www.w3.org/2001/XMLSchema#time');
+INSERT INTO XACML.DATATYPE (ID,IS_STANDARD,SHORT_NAME,XACML_ID) VALUES (17,'S','dnsName','urn:oasis:names:tc:xacml:2.0:data-type:dnsName');
+INSERT INTO XACML.DATATYPE (ID,IS_STANDARD,SHORT_NAME,XACML_ID) VALUES (18,'S','boolean','http://www.w3.org/2001/XMLSchema#boolean');
+INSERT INTO XACML.DATATYPE (ID,IS_STANDARD,SHORT_NAME,XACML_ID) VALUES (19,'S','dateTime','http://www.w3.org/2001/XMLSchema#dateTime');
+INSERT INTO XACML.DATATYPE (ID,IS_STANDARD,SHORT_NAME,XACML_ID) VALUES (20,'S','rfc822Name','urn:oasis:names:tc:xacml:1.0:data-type:rfc822Name');
+INSERT INTO XACML.DATATYPE (ID,IS_STANDARD,SHORT_NAME,XACML_ID) VALUES (21,'S','date','http://www.w3.org/2001/XMLSchema#date');
+INSERT INTO XACML.DATATYPE (ID,IS_STANDARD,SHORT_NAME,XACML_ID) VALUES (22,'S','ipAddress','urn:oasis:names:tc:xacml:2.0:data-type:ipAddress');
+INSERT INTO XACML.DATATYPE (ID,IS_STANDARD,SHORT_NAME,XACML_ID) VALUES (23,'S','yearMonthDuration','http://www.w3.org/2001/XMLSchema#yearMonthDuration');
+INSERT INTO XACML.DATATYPE (ID,IS_STANDARD,SHORT_NAME,XACML_ID) VALUES (24,'S','hexBinary','http://www.w3.org/2001/XMLSchema#hexBinary');
+INSERT INTO XACML.DATATYPE (ID,IS_STANDARD,SHORT_NAME,XACML_ID) VALUES (25,'S','double','http://www.w3.org/2001/XMLSchema#double');
+INSERT INTO XACML.DATATYPE (ID,IS_STANDARD,SHORT_NAME,XACML_ID) VALUES (26,'S','string','http://www.w3.org/2001/XMLSchema#string');
+INSERT INTO XACML.DATATYPE (ID,IS_STANDARD,SHORT_NAME,XACML_ID) VALUES (27,'S','anyURI','http://www.w3.org/2001/XMLSchema#anyURI');
+INSERT INTO XACML.DATATYPE (ID,IS_STANDARD,SHORT_NAME,XACML_ID) VALUES (28,'S','xpathExpression','urn:oasis:names:tc:xacml:3.0:data-type:xpathExpression');
+INSERT INTO XACML.DATATYPE (ID,IS_STANDARD,SHORT_NAME,XACML_ID) VALUES (29,'S','user','');
+
+
+
+
+INSERT INTO XACML.ECOMPNAME (ID,CREATED_BY,CREATED_DATE,DESCRIPTION,ECOMP_NAME,MODIFIED_BY,MODIFIED_DATE) VALUES (1456,'super-admin',str_to_date('2015-05-13 14:21:34.778000','%Y-%m-%d %H:%i:%s.%f'),'orchestrator','MSO','super-admin',str_to_date('2015-05-13 14:21:34.778000','%Y-%m-%d %H:%i:%s.%f'));
+
+
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (1,1,0,12,1);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (2,2,0,12,1);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (3,1,0,12,2);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (4,2,0,12,2);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (5,1,0,25,3);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (6,1,1,12,4);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (7,1,1,25,5);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (8,1,0,26,6);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (9,2,0,26,6);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (10,1,0,26,7);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (11,2,0,26,7);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (12,1,0,26,8);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (13,2,0,26,8);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (14,1,0,26,9);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (15,2,0,26,9);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (16,1,0,26,10);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (17,1,0,26,11);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (18,1,0,18,12);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (19,1,0,26,13);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (20,1,0,12,14);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (21,1,0,26,15);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (22,1,0,25,16);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (23,1,0,26,17);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (24,1,0,16,18);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (25,1,0,26,19);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (26,1,0,21,20);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (27,1,0,26,21);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (28,1,0,19,22);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (29,1,0,26,23);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (30,1,0,27,24);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (31,1,0,26,25);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (32,1,0,15,26);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (33,1,0,26,27);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (34,1,0,23,28);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (35,1,0,26,29);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (36,1,0,14,30);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (37,1,0,26,31);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (38,1,0,20,32);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (39,1,0,26,33);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (40,1,0,22,34);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (41,1,0,26,35);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (42,1,0,17,36);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (43,2,0,27,37);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (44,1,0,26,37);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (45,1,0,26,38);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (46,2,0,27,38);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (47,1,0,26,39);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (48,2,0,26,39);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (49,1,0,26,40);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (50,2,0,27,40);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (51,1,0,26,41);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (52,2,0,12,41);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (53,3,0,12,41);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (54,1,0,27,42);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (55,2,0,12,42);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (56,3,0,12,42);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (57,1,0,18,43);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (58,2,0,18,43);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (59,1,0,12,44);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (60,2,0,12,44);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (61,1,0,25,45);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (62,2,0,25,45);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (63,1,0,21,46);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (64,2,0,21,46);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (65,1,0,16,47);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (66,2,0,16,47);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (67,1,0,19,48);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (68,2,0,19,48);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (69,1,0,15,49);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (70,2,0,15,49);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (71,1,0,23,50);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (72,2,0,23,50);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (73,1,0,27,51);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (74,2,0,27,51);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (75,1,0,14,52);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (76,2,0,14,52);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (77,1,0,20,53);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (78,2,0,20,53);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (79,1,0,24,54);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (80,2,0,24,54);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (81,1,0,13,55);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (82,2,0,13,55);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (83,1,0,12,56);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (84,2,0,12,56);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (85,1,0,25,57);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (86,2,0,25,57);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (89,1,0,25,58);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (90,2,0,25,58);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (91,1,0,12,59);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (92,2,0,12,59);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (93,1,0,25,60);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (94,2,0,25,60);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (95,1,0,12,61);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (96,2,0,12,61);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (97,1,0,25,62);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (98,2,0,25,62);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (99,1,0,12,63);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (100,2,0,12,63);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (101,1,0,12,64);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (102,1,0,25,65);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (103,1,0,25,66);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (104,1,0,25,67);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (125,1,0,26,68);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (126,1,0,26,69);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (128,1,0,12,70);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (129,1,0,12,71);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (130,2,0,12,71);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (131,1,0,12,72);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (132,2,0,12,72);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (133,1,0,12,73);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (134,2,0,12,73);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (135,1,0,25,74);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (136,2,0,25,74);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (137,1,0,25,75);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (138,2,0,25,75);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (139,1,0,25,76);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (140,2,0,25,76);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (141,1,0,25,77);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (142,2,0,25,77);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (143,1,0,19,78);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (144,2,0,15,78);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (145,1,0,19,79);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (146,2,0,23,79);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (147,1,0,19,80);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (148,2,0,15,80);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (149,1,0,19,81);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (150,2,0,23,81);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (151,1,0,21,82);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (152,2,0,23,82);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (153,1,0,21,83);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (154,2,0,23,83);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (155,1,0,26,84);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (156,2,0,26,84);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (157,1,0,26,85);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (158,2,0,26,85);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (159,1,0,26,86);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (160,2,0,26,86);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (161,1,0,26,87);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (162,2,0,26,87);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (163,1,0,16,88);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (164,2,0,16,88);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (165,1,0,16,89);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (166,2,0,16,89);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (167,1,0,16,90);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (168,2,0,16,90);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (169,1,0,16,91);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (170,2,0,16,91);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (171,1,0,16,92);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (172,2,0,16,92);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (173,1,0,19,93);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (174,2,0,19,93);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (175,1,0,19,94);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (176,2,0,19,94);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (177,1,0,19,95);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (178,2,0,19,95);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (179,1,0,19,96);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (180,2,0,19,96);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (181,1,0,21,97);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (182,2,0,21,97);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (183,1,0,21,98);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (184,2,0,21,98);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (185,2,0,21,99);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (186,1,0,21,99);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (187,2,0,21,100);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (188,1,0,21,100);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (189,1,1,26,101);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (190,1,1,26,102);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (191,1,0,26,103);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (192,2,1,26,103);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (193,1,0,26,104);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (194,1,1,12,105);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (195,1,0,12,106);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (196,2,1,12,106);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (197,1,0,12,107);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (198,1,1,25,108);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (199,1,0,25,109);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (200,2,1,25,109);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (201,1,0,25,110);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (202,1,1,18,111);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (203,1,1,18,112);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (204,1,0,18,113);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (205,2,1,18,113);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (206,1,0,18,114);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (207,1,1,16,115);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (208,1,1,16,116);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (209,1,0,16,117);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (210,2,1,16,117);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (211,1,0,16,118);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (212,1,1,21,119);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (213,1,1,21,120);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (214,1,0,21,121);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (215,2,1,21,121);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (216,1,0,21,122);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (217,1,1,19,123);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (218,1,1,19,124);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (219,1,0,19,125);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (220,2,1,19,125);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (221,1,0,19,126);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (222,1,1,27,127);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (223,1,1,27,128);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (224,1,0,27,129);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (225,2,1,27,129);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (226,1,0,27,130);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (227,1,1,24,131);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (228,1,1,24,132);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (229,1,0,24,133);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (230,2,1,24,133);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (231,1,0,24,134);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (232,1,1,13,135);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (233,1,1,13,136);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (234,1,0,13,137);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (235,2,1,13,137);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (236,1,0,13,138);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (237,1,1,15,139);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (238,1,1,15,140);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (239,1,0,15,141);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (240,2,1,15,141);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (241,1,0,15,142);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (242,1,1,23,143);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (243,1,1,23,144);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (244,2,1,23,145);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (245,1,0,23,145);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (246,1,0,23,146);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (247,1,1,14,147);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (248,1,1,14,148);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (249,1,0,14,149);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (250,2,1,14,149);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (251,1,0,14,150);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (252,1,1,20,151);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (253,1,1,20,152);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (254,1,0,20,153);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (255,2,1,20,153);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (256,1,0,20,154);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (257,1,1,22,155);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (258,1,1,22,156);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (259,1,0,22,157);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (260,2,1,22,157);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (261,1,0,22,158);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (262,1,1,17,159);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (263,1,1,17,160);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (264,1,0,17,161);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (265,2,1,17,161);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (266,1,0,17,162);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (267,1,0,26,163);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (268,2,0,26,163);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (269,1,0,26,164);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (270,2,0,27,164);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (271,1,0,26,165);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (272,2,0,22,165);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (273,1,0,26,166);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (274,2,0,17,166);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (275,1,0,26,167);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (276,2,0,20,167);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (277,1,0,26,168);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (278,2,0,14,168);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (279,1,1,26,169);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (280,2,1,26,169);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (281,1,1,26,170);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (282,2,1,26,170);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (283,1,1,26,171);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (284,1,1,26,172);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (285,2,1,26,172);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (286,1,1,26,173);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (287,2,1,26,173);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (288,2,1,12,174);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (289,1,1,12,174);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (290,1,1,12,175);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (292,2,1,12,176);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (293,1,1,12,176);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (294,2,1,12,177);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (295,1,1,12,177);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (296,1,1,25,178);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (297,2,1,25,178);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (298,1,1,25,179);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (299,1,1,25,180);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (300,2,1,25,180);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (301,1,1,25,181);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (302,2,1,25,181);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (303,1,1,18,182);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (304,2,1,18,182);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (305,1,1,18,183);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (306,2,1,18,183);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (307,1,1,18,184);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (308,1,1,18,185);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (309,2,1,18,185);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (310,1,1,18,186);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (311,2,1,18,186);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (312,2,1,16,187);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (313,1,1,16,187);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (314,1,1,16,188);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (315,2,1,16,188);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (316,1,1,16,189);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (317,1,1,16,190);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (318,2,1,16,190);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (319,1,1,16,191);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (320,2,1,16,191);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (321,1,1,21,192);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (322,2,1,21,192);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (323,1,1,21,193);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (324,2,1,21,193);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (325,1,1,21,194);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (326,1,1,21,195);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (327,2,1,21,195);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (328,1,1,21,196);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (329,2,1,21,196);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (330,1,1,19,197);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (331,2,1,19,197);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (332,1,1,19,198);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (333,2,1,19,198);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (334,1,1,19,199);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (335,1,1,19,200);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (336,2,1,19,200);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (337,1,1,19,201);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (338,2,1,19,201);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (339,1,1,27,202);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (340,2,1,27,202);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (341,1,1,27,203);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (342,2,1,27,203);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (343,1,1,27,204);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (344,1,1,27,205);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (345,2,1,27,205);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (346,1,1,27,206);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (347,2,1,27,206);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (348,1,1,24,207);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (349,2,1,24,207);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (350,1,1,24,208);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (351,2,1,24,208);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (352,1,1,24,209);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (353,1,1,24,210);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (354,2,1,24,210);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (355,1,1,24,211);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (356,2,1,24,211);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (357,1,1,13,212);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (358,2,1,13,212);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (359,1,1,13,213);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (360,2,1,13,213);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (361,1,1,13,214);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (362,1,1,13,215);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (363,2,1,13,215);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (364,1,1,13,216);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (365,2,1,13,216);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (366,1,1,15,217);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (367,2,1,15,217);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (368,1,1,15,218);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (369,2,1,15,218);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (370,1,1,15,219);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (371,1,1,15,220);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (372,2,1,15,220);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (373,1,1,15,221);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (374,2,1,15,221);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (375,1,1,23,222);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (376,2,1,23,222);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (377,1,1,23,223);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (378,2,1,23,223);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (380,1,1,23,224);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (381,1,1,23,225);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (382,2,1,23,225);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (383,2,1,23,226);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (384,1,1,23,226);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (385,1,1,14,227);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (386,2,1,14,227);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (387,1,1,14,228);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (388,2,1,14,228);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (389,1,1,14,229);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (390,1,1,14,230);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (391,2,1,14,230);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (392,1,1,14,231);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (393,2,1,14,231);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (394,1,1,20,232);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (395,2,1,20,232);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (396,1,1,20,233);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (397,2,1,20,233);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (398,1,1,20,234);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (399,1,1,20,235);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (400,2,1,20,235);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (401,1,1,20,236);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (402,2,1,20,236);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (403,1,0,14,237);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (404,2,0,14,237);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (405,1,0,26,238);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (406,2,0,20,238);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (407,1,1,12,239);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (408,2,1,12,239);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (409,1,1,25,240);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (410,2,1,25,240);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (411,1,0,18,241);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (412,1,0,18,242);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (413,1,0,12,243);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (414,2,0,18,243);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (415,1,0,18,244);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (416,1,0,18,245);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (417,2,0,null,245);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (418,3,1,null,245);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (419,1,0,18,246);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (420,2,0,null,246);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (421,3,1,null,246);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (422,1,0,18,247);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (423,2,1,null,247);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (424,3,1,null,247);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (433,1,0,18,248);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (434,2,1,null,248);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (435,3,1,null,248);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (436,1,0,18,249);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (437,2,1,null,249);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (438,3,1,null,249);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (439,1,0,18,250);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (440,2,1,null,250);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (441,3,1,null,250);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (442,1,0,null,251);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (447,2,1,null,251);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (448,1,0,28,252);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (449,1,0,28,253);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (450,2,0,28,253);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (451,1,0,28,254);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (452,2,0,28,254);
+INSERT INTO XACML.FUNCTIONARGUMENTS (ID,ARG_INDEX,IS_BAG,DATATYPE_ID,FUNCTION_ID) VALUES (453,3,0,16,92);
+
+
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (1,2,2,null,null,null,0,0,'integer-greater-than-or-equal','urn:oasis:names:tc:xacml:1.0:function:integer-greater-than-or-equal',18);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (2,2,2,null,null,null,0,0,'integer-subtract','urn:oasis:names:tc:xacml:1.0:function:integer-subtract',12);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (3,1,1,null,null,null,0,0,'double-to-integer','urn:oasis:names:tc:xacml:1.0:function:double-to-integer',12);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (4,1,1,null,null,null,0,0,'integer-one-and-only','urn:oasis:names:tc:xacml:1.0:function:integer-one-and-only',12);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (5,1,1,null,null,null,0,0,'double-one-and-only','urn:oasis:names:tc:xacml:1.0:function:double-one-and-only',25);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (6,2,2,null,null,null,0,0,'string-equal','urn:oasis:names:tc:xacml:1.0:function:string-equal',18);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (7,2,2,null,null,null,0,0,'string-equal-ignore-case','urn:oasis:names:tc:xacml:3.0:function:string-equal-ignore-case',18);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (8,2,2,null,null,null,0,0,'string-starts-with','urn:oasis:names:tc:xacml:3.0:function:string-starts-with',18);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (9,2,2,null,null,null,0,0,'string-ends-with','urn:oasis:names:tc:xacml:3.0:function: string-ends-with',18);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (10,2,-1,null,null,null,0,0,'string-concatenate','urn:oasis:names:tc:xacml:2.0:function:string-concatenate',26);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (11,1,1,null,null,null,0,0,'boolean-from-string','urn:oasis:names:tc:xacml:3.0:function:boolean-from-string',18);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (12,1,1,null,null,null,0,0,'string-from-boolean','urn:oasis:names:tc:xacml:3.0:function:string-from-boolean',26);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (13,1,1,null,null,null,0,0,'integer-from-string','urn:oasis:names:tc:xacml:3.0:function:integer-from-string',12);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (14,1,1,null,null,null,0,0,'string-from-integer','urn:oasis:names:tc:xacml:3.0:function:string-from-integer',26);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (15,1,1,null,null,null,0,0,'double-from-string','urn:oasis:names:tc:xacml:3.0:function:double-from-string',25);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (16,1,1,null,null,null,0,0,'string-from-double','urn:oasis:names:tc:xacml:3.0:function:string-from-double',26);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (17,1,1,null,null,null,0,0,'time-from-string','urn:oasis:names:tc:xacml:3.0:function:time-from-string',16);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (18,1,1,null,null,null,0,0,'string-from-time','urn:oasis:names:tc:xacml:3.0:function:string-from-time',26);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (19,1,1,null,null,null,0,0,'date-from-string','urn:oasis:names:tc:xacml:3.0:function:date-from-string',21);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (20,1,1,null,null,null,0,0,'string-from-date','urn:oasis:names:tc:xacml:3.0:function:string-from-date',26);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (21,1,1,null,null,null,0,0,'dateTime-from-string','urn:oasis:names:tc:xacml:3.0:function:dateTime-from-string',19);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (22,1,1,null,null,null,0,0,'string-from-dateTime','urn:oasis:names:tc:xacml:3.0:function:string-from-dateTime',26);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (23,1,1,null,null,null,0,0,'anyURI-from-string','urn:oasis:names:tc:xacml:3.0:function:anyURI-from-string',27);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (24,1,1,null,null,null,0,0,'string-from-anyURI','urn:oasis:names:tc:xacml:3.0:function:string-from-anyURI',26);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (25,1,1,null,null,null,0,0,'dayTimeDuration-from-string','urn:oasis:names:tc:xacml:3.0:function:dayTimeDuration-from-string',15);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (26,1,1,null,null,null,0,0,'string-from-dayTimeDuration','urn:oasis:names:tc:xacml:3.0:function:string-from-dayTimeDuration',26);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (27,1,1,null,null,null,0,0,'yearMonthDuration-from-string','urn:oasis:names:tc:xacml:3.0:function:yearMonthDuration-from-string',23);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (28,1,1,null,null,null,0,0,'string-from-yearMonthDuration','urn:oasis:names:tc:xacml:3.0:function:string-from-yearMonthDuration',26);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (29,1,1,null,null,null,0,0,'x500Name-from-string','urn:oasis:names:tc:xacml:3.0:function:x500Name-from-string',14);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (30,1,1,null,null,null,0,0,'string-from-x500Name','urn:oasis:names:tc:xacml:3.0:function:string-from-x500Name',26);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (31,1,1,null,null,null,0,0,'rfc822Name-from-string','urn:oasis:names:tc:xacml:3.0:function:rfc822Name-from-string',20);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (32,1,1,null,null,null,0,0,'string-from-rfc822Name','urn:oasis:names:tc:xacml:3.0:function:string-from-rfc822Name',26);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (33,1,1,null,null,null,0,0,'ipAddress-from-string','urn:oasis:names:tc:xacml:3.0:function:ipAddress-from-string',22);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (34,1,1,null,null,null,0,0,'string-from-ipAddress','urn:oasis:names:tc:xacml:3.0:function:string-from-ipAddress',26);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (35,1,1,null,null,null,0,0,'dnsName-from-string','urn:oasis:names:tc:xacml:3.0:function:dnsName-from-string',17);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (36,1,1,null,null,null,0,0,'string-from-dnsName','urn:oasis:names:tc:xacml:3.0:function:string-from-dnsName',26);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (37,2,2,null,null,null,0,0,'anyURI-starts-with','urn:oasis:names:tc:xacml:3.0:function:anyURI-starts-with',18);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (38,2,2,null,null,null,0,0,'anyURI-ends-with','urn:oasis:names:tc:xacml:3.0:function:anyURI-ends-with',18);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (39,2,2,null,null,null,0,0,'string-contains','urn:oasis:names:tc:xacml:3.0:function:string-contains',18);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (40,2,2,null,null,null,0,0,'anyURI-contains','urn:oasis:names:tc:xacml:3.0:function:anyURI-contains',18);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (41,3,3,null,null,null,0,0,'string-substring','urn:oasis:names:tc:xacml:3.0:function:string-substring',26);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (42,3,3,null,null,null,0,0,'anyURI-substring','urn:oasis:names:tc:xacml:3.0:function:anyURI-substring',26);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (43,2,2,null,null,null,0,0,'boolean-equal','urn:oasis:names:tc:xacml:1.0:function:boolean-equal',18);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (44,2,2,null,null,null,0,0,'integer-equal','urn:oasis:names:tc:xacml:1.0:function:integer-equal',18);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (45,2,2,null,null,null,0,0,'double-equal','urn:oasis:names:tc:xacml:1.0:function:double-equal',18);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (46,2,2,null,null,null,0,0,'date-equal','urn:oasis:names:tc:xacml:1.0:function:date-equal',18);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (47,2,2,null,null,null,0,0,'time-equal','urn:oasis:names:tc:xacml:1.0:function:time-equal',18);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (48,2,2,null,null,null,0,0,'dateTime-equal','urn:oasis:names:tc:xacml:1.0:function:dateTime-equal',18);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (49,2,2,null,null,null,0,0,'dayTimeDuration-equal','urn:oasis:names:tc:xacml:3.0:function:dayTimeDuration-equal',18);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (50,2,2,null,null,null,0,0,'yearMonthDuration-equal','urn:oasis:names:tc:xacml:3.0:function:yearMonthDuration-equal',18);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (51,2,2,null,null,null,0,0,'anyURI-equal','urn:oasis:names:tc:xacml:1.0:function:anyURI-equal',18);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (52,2,2,null,null,null,0,0,'x500Name-equal','urn:oasis:names:tc:xacml:1.0:function:x500Name-equal',18);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (53,2,2,null,null,null,0,0,'rfc822Name-equal','urn:oasis:names:tc:xacml:1.0:function:rfc822Name-equal',18);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (54,2,2,null,null,null,0,0,'hexBinary-equal','urn:oasis:names:tc:xacml:1.0:function:hexBinary-equal',18);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (55,2,2,null,null,null,0,0,'base64Binary-equal','urn:oasis:names:tc:xacml:1.0:function:base64Binary-equal',18);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (56,2,2,null,null,null,0,0,'integer-add','urn:oasis:names:tc:xacml:1.0:function:integer-add',12);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (57,2,2,null,null,null,0,0,'double-add','urn:oasis:names:tc:xacml:1.0:function:double-add',25);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (58,2,2,null,null,null,0,0,'double-subtract','urn:oasis:names:tc:xacml:1.0:function:double-subtract',25);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (59,2,2,null,null,null,0,0,'integer-multiply','urn:oasis:names:tc:xacml:1.0:function:integer-multiply',12);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (60,2,2,null,null,null,0,0,'double-multiply','urn:oasis:names:tc:xacml:1.0:function:double-multiply',25);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (61,2,2,null,null,null,0,0,'integer-divide','urn:oasis:names:tc:xacml:1.0:function:integer-divide',12);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (62,2,2,null,null,null,0,0,'double-divide','urn:oasis:names:tc:xacml:1.0:function:double-divide',25);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (63,2,2,null,null,null,0,0,'integer-mod','urn:oasis:names:tc:xacml:1.0:function:integer-mod',12);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (64,1,1,null,null,null,0,0,'integer-abs','urn:oasis:names:tc:xacml:1.0:function:integer-abs',12);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (65,1,1,null,null,null,0,0,'double-abs','urn:oasis:names:tc:xacml:1.0:function:double-abs',25);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (66,1,1,null,null,null,0,0,'round','urn:oasis:names:tc:xacml:1.0:function:round',25);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (67,1,1,null,null,null,0,0,'floor','urn:oasis:names:tc:xacml:1.0:function:floor',25);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (68,1,1,null,null,null,0,0,'string-normalize-space','urn:oasis:names:tc:xacml:1.0:function:string-normalize-space',26);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (69,1,1,null,null,null,0,0,'string-normalize-to-lower-case','urn:oasis:names:tc:xacml:1.0:function:string-normalize-to-lower-case',26);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (70,1,1,null,null,null,0,0,'integer-to-double','urn:oasis:names:tc:xacml:1.0:function:integer-to-double',25);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (71,2,2,null,null,null,0,0,'integer-greater-than','urn:oasis:names:tc:xacml:1.0:function:integer-greater-than',18);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (72,2,2,null,null,null,0,0,'integer-less-than','urn:oasis:names:tc:xacml:1.0:function:integer-less-than',18);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (73,2,2,null,null,null,0,0,'integer-less-than-or-equal','urn:oasis:names:tc:xacml:1.0:function:integer-less-than-or-equal',18);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (74,2,2,null,null,null,0,0,'double-greater-than','urn:oasis:names:tc:xacml:1.0:function:double-greater-than',18);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (75,2,2,null,null,null,0,0,'double-greater-than-or-equal','urn:oasis:names:tc:xacml:1.0:function:double-greater-than-or-equal',18);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (76,2,2,null,null,null,0,0,'double-less-than','urn:oasis:names:tc:xacml:1.0:function:double-less-than',18);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (77,2,2,null,null,null,0,0,'double-less-than-or-equal','urn:oasis:names:tc:xacml:1.0:function:double-less-than-or-equal',18);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (78,2,2,null,null,null,0,0,'dateTime-add-dayTimeDuration','urn:oasis:names:tc:xacml:3.0:function:dateTime-add-dayTimeDuration',19);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (79,2,2,null,null,null,0,0,'dateTime-add-yearMonthDuration','urn:oasis:names:tc:xacml:3.0:function:dateTime-add-yearMonthDuration',19);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (80,2,2,null,null,null,0,0,'dateTime-subtract-dayTimeDuration','urn:oasis:names:tc:xacml:3.0:function:dateTime-subtract-dayTimeDuration',19);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (81,2,2,null,null,null,0,0,'dateTime-subtract-yearMonthDuration','urn:oasis:names:tc:xacml:3.0:function:dateTime-subtract-yearMonthDuration',19);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (82,2,2,null,null,null,0,0,'date-add-yearMonthDuration','urn:oasis:names:tc:xacml:3.0:function:date-add-yearMonthDuration',21);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (83,2,2,null,null,null,0,0,'date-subtract-yearMonthDuration','urn:oasis:names:tc:xacml:3.0:function:date-subtract-yearMonthDuration',21);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (84,2,2,null,null,null,0,0,'string-greater-than','urn:oasis:names:tc:xacml:1.0:function:string-greater-than',18);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (85,2,2,null,null,null,0,0,'string-greater-than-or-equal','urn:oasis:names:tc:xacml:1.0:function:string-greater-than-or-equal',18);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (86,2,2,null,null,null,0,0,'string-less-than','urn:oasis:names:tc:xacml:1.0:function:string-less-than',18);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (87,2,2,null,null,null,0,0,'string-less-than-or-equal','urn:oasis:names:tc:xacml:1.0:function:string-less-than-or-equal',18);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (88,2,2,null,null,null,0,0,'time-greater-than','urn:oasis:names:tc:xacml:1.0:function:time-greater-than',18);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (89,2,2,null,null,null,0,0,'time-greater-than-or-equal','urn:oasis:names:tc:xacml:1.0:function:time-greater-than-or-equal',18);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (90,2,2,null,null,null,0,0,'time-less-than','urn:oasis:names:tc:xacml:1.0:function:time-less-than',18);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (91,2,2,null,null,null,0,0,'time-less-than-or-equal','urn:oasis:names:tc:xacml:1.0:function:time-less-than-or-equal',18);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (92,3,3,null,null,null,0,0,'time-in-range','urn:oasis:names:tc:xacml:2.0:function:time-in-range',18);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (93,2,2,null,null,null,0,0,'dateTime-greater-than','urn:oasis:names:tc:xacml:1.0:function:dateTime-greater-than',18);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (94,2,2,null,null,null,0,0,'dateTime-greater-than-or-equal','urn:oasis:names:tc:xacml:1.0:function:dateTime-greater-than-or-equal',18);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (95,2,2,null,null,null,0,0,'dateTime-less-than','urn:oasis:names:tc:xacml:1.0:function:dateTime-less-than',18);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (96,2,2,null,null,null,0,0,'dateTime-less-than-or-equal','urn:oasis:names:tc:xacml:1.0:function:dateTime-less-than-or-equal',18);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (97,2,2,null,null,null,0,0,'date-greater-than','urn:oasis:names:tc:xacml:1.0:function:date-greater-than',18);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (98,2,2,null,null,null,0,0,'date-greater-than-or-equal','urn:oasis:names:tc:xacml:1.0:function:date-greater-than-or-equal',18);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (99,2,2,null,null,null,0,0,'date-less-than','urn:oasis:names:tc:xacml:1.0:function:date-less-than',18);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (100,2,2,null,null,null,0,0,'date-less-than-or-equal','urn:oasis:names:tc:xacml:1.0:function:date-less-than-or-equal',18);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (101,1,1,null,null,null,0,0,'string-one-and-only','urn:oasis:names:tc:xacml:1.0:function:string-one-and-only',26);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (102,1,1,null,null,null,0,0,'string-bag-size','urn:oasis:names:tc:xacml:1.0:function:string-bag-size',12);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (103,2,2,null,null,null,0,0,'string-is-in','urn:oasis:names:tc:xacml:1.0:function:string-is-in',18);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (104,1,-1,null,null,null,1,0,'string-bag','urn:oasis:names:tc:xacml:1.0:function:string-bag',26);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (105,1,1,null,null,null,0,0,'integer-bag-size','urn:oasis:names:tc:xacml:1.0:function:integer-bag-size',12);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (106,2,2,null,null,null,0,0,'integer-is-in','urn:oasis:names:tc:xacml:1.0:function:integer-is-in',18);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (107,1,-1,null,null,null,1,0,'integer-bag','urn:oasis:names:tc:xacml:1.0:function:integer-bag',12);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (108,1,1,null,null,null,0,0,'double-bag-size','urn:oasis:names:tc:xacml:1.0:function:double-bag-size',12);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (109,2,2,null,null,null,0,0,'double-is-in','urn:oasis:names:tc:xacml:1.0:function:double-is-in',18);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (110,1,-1,null,null,null,1,0,'double-bag','urn:oasis:names:tc:xacml:1.0:function:double-bag',25);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (111,1,1,null,null,null,0,0,'boolean-one-and-only','urn:oasis:names:tc:xacml:1.0:function:boolean-one-and-only',18);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (112,1,1,null,null,null,0,0,'boolean-bag-size','urn:oasis:names:tc:xacml:1.0:function:boolean-bag-size',12);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (113,2,2,null,null,null,0,0,'boolean-is-in','urn:oasis:names:tc:xacml:1.0:function:boolean-is-in',18);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (114,1,-1,null,null,null,1,0,'boolean-bag','urn:oasis:names:tc:xacml:1.0:function:boolean-bag',18);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (115,1,1,null,null,null,0,0,'time-one-and-only','urn:oasis:names:tc:xacml:1.0:function:time-one-and-only',16);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (116,1,1,null,null,null,0,0,'time-bag-size','urn:oasis:names:tc:xacml:1.0:function:time-bag-size',12);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (117,2,2,null,null,null,0,0,'time-is-in','urn:oasis:names:tc:xacml:1.0:function:time-is-in',18);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (118,1,-1,null,null,null,1,0,'time-bag','urn:oasis:names:tc:xacml:1.0:function:time-bag',16);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (119,1,1,null,null,null,0,0,'date-one-and-only','urn:oasis:names:tc:xacml:1.0:function:date-one-and-only',21);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (120,1,1,null,null,null,0,0,'date-bag-size','urn:oasis:names:tc:xacml:1.0:function:date-bag-size',12);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (121,2,2,null,null,null,0,0,'date-is-in','urn:oasis:names:tc:xacml:1.0:function:date-is-in',18);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (122,1,-1,null,null,null,1,0,'date-bag','urn:oasis:names:tc:xacml:1.0:function:date-bag',21);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (123,1,1,null,null,null,0,0,'dateTime-one-and-only','urn:oasis:names:tc:xacml:1.0:function:dateTime-one-and-only',19);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (124,1,1,null,null,null,0,0,'dateTime-bag-size','urn:oasis:names:tc:xacml:1.0:function:dateTime-bag-size',12);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (125,2,2,null,null,null,0,0,'dateTime-is-in','urn:oasis:names:tc:xacml:1.0:function:dateTime-is-in',18);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (126,1,-1,null,null,null,1,0,'dateTime-bag','urn:oasis:names:tc:xacml:1.0:function:dateTime-bag',19);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (127,1,1,null,null,null,0,0,'anyURI-one-and-only','urn:oasis:names:tc:xacml:1.0:function:anyURI-one-and-only',27);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (128,1,1,null,null,null,0,0,'anyURI-bag-size','urn:oasis:names:tc:xacml:1.0:function:anyURI-bag-size',12);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (129,2,2,null,null,null,0,0,'anyURI-is-in','urn:oasis:names:tc:xacml:1.0:function:anyURI-is-in',18);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (130,1,-1,null,null,null,1,0,'anyURI-bag','urn:oasis:names:tc:xacml:1.0:function:anyURI-bag',27);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (131,1,1,null,null,null,0,0,'hexBinary-one-and-only','urn:oasis:names:tc:xacml:1.0:function:hexBinary-one-and-only',24);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (132,1,1,null,null,null,0,0,'hexBinary-bag-size','urn:oasis:names:tc:xacml:1.0:function:hexBinary-bag-size',12);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (133,2,2,null,null,null,0,0,'hexBinary-is-in','urn:oasis:names:tc:xacml:1.0:function:hexBinary-is-in',18);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (134,1,-1,null,null,null,1,0,'hexBinary-bag','urn:oasis:names:tc:xacml:1.0:function:hexBinary-bag',24);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (135,1,1,null,null,null,0,0,'base64Binary-one-and-only','urn:oasis:names:tc:xacml:1.0:function:base64Binary-one-and-only',13);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (136,1,1,null,null,null,0,0,'base64Binary-bag-size','urn:oasis:names:tc:xacml:1.0:function:base64Binary-bag-size',12);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (137,2,2,null,null,null,0,0,'base64Binary-is-in','urn:oasis:names:tc:xacml:1.0:function:base64Binary-is-in',18);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (138,1,-1,null,null,null,1,0,'base64Binary-bag','urn:oasis:names:tc:xacml:1.0:function:base64Binary-bag',13);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (139,1,1,null,null,null,0,0,'dayTimeDuration-one-and-only','urn:oasis:names:tc:xacml:3.0:function:dayTimeDuration-one-and-only',15);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (140,1,1,null,null,null,0,0,'dayTimeDuration-bag-size','urn:oasis:names:tc:xacml:3.0:function:dayTimeDuration-bag-size',12);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (141,2,2,null,null,null,0,0,'dayTimeDuration-is-in','urn:oasis:names:tc:xacml:3.0:function:dayTimeDuration-is-in',18);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (142,1,-1,null,null,null,1,0,'dayTimeDuration-bag','urn:oasis:names:tc:xacml:3.0:function:dayTimeDuration-bag',15);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (143,1,1,null,null,null,0,0,'yearMonthDuration-one-and-only','urn:oasis:names:tc:xacml:3.0:function:yearMonthDuration-one-and-only',23);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (144,1,1,null,null,null,0,0,'yearMonthDuration-bag-size','urn:oasis:names:tc:xacml:3.0:function:yearMonthDuration-bag-size',12);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (145,2,2,null,null,null,0,0,'yearMonthDuration-is-in','urn:oasis:names:tc:xacml:3.0:function:yearMonthDuration-is-in',18);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (146,1,-1,null,null,null,1,0,'yearMonthDuration-bag','urn:oasis:names:tc:xacml:3.0:function:yearMonthDuration-bag',23);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (147,1,1,null,null,null,0,0,'x500Name-one-and-only','urn:oasis:names:tc:xacml:1.0:function:x500Name-one-and-only',14);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (148,1,1,null,null,null,0,0,'x500Name-bag-size','urn:oasis:names:tc:xacml:1.0:function:x500Name-bag-size',12);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (149,2,2,null,null,null,0,0,'x500Name-is-in','urn:oasis:names:tc:xacml:1.0:function:x500Name-is-in',18);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (150,1,-1,null,null,null,1,0,'x500Name-bag','urn:oasis:names:tc:xacml:1.0:function:x500Name-bag',14);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (151,1,1,null,null,null,0,0,'rfc822Name-one-and-only','urn:oasis:names:tc:xacml:1.0:function:rfc822Name-one-and-only',20);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (152,1,1,null,null,null,0,0,'rfc822Name-bag-size','urn:oasis:names:tc:xacml:1.0:function:rfc822Name-bag-size',12);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (153,2,2,null,null,null,0,0,'rfc822Name-is-in','urn:oasis:names:tc:xacml:1.0:function:rfc822Name-is-in',18);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (154,1,-1,null,null,null,1,0,'rfc822Name-bag','urn:oasis:names:tc:xacml:1.0:function:rfc822Name-bag',20);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (155,1,1,null,null,null,0,0,'ipAddress-one-and-only','urn:oasis:names:tc:xacml:2.0:function:ipAddress-one-and-only',22);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (156,1,1,null,null,null,0,0,'ipAddress-bag-size','urn:oasis:names:tc:xacml:2.0:function:ipAddress-bag-size',12);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (157,2,2,null,null,null,0,0,'ipAddress-is-in','urn:oasis:names:tc:xacml:2.0:function:ipAddress-is-in',18);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (158,1,-1,null,null,null,1,0,'ipAddress-bag','urn:oasis:names:tc:xacml:2.0:function:ipAddress-bag',22);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (159,1,1,null,null,null,0,0,'dnsName-one-and-only','urn:oasis:names:tc:xacml:2.0:function:dnsName-one-and-only',17);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (160,1,1,null,null,null,0,0,'dnsName-bag-size','urn:oasis:names:tc:xacml:2.0:function:dnsName-bag-size',12);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (161,2,2,null,null,null,0,0,'dnsName-is-in','urn:oasis:names:tc:xacml:2.0:function:dnsName-is-in',18);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (162,1,-1,null,null,null,1,0,'dnsName-bag','urn:oasis:names:tc:xacml:2.0:function:dnsName-bag',17);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (163,2,2,null,null,null,0,0,'string-regexp-match','urn:oasis:names:tc:xacml:1.0:function:string-regexp-match',18);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (164,2,2,null,null,null,0,0,'anyURI-regexp-match','urn:oasis:names:tc:xacml:2.0:function:anyURI-regexp-match',18);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (165,2,2,null,null,null,0,0,'ipAddress-regexp-match','urn:oasis:names:tc:xacml:2.0:function:ipAddress-regexp-match',18);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (166,2,2,null,null,null,0,0,'dnsName-regexp-match','urn:oasis:names:tc:xacml:2.0:function:dnsName-regexp-match',18);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (167,2,2,null,null,null,0,0,'rfc822Name-regexp-match','urn:oasis:names:tc:xacml:2.0:function:rfc822Name-regexp-match',18);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (168,2,2,null,null,null,0,0,'x500Name-regexp-match','urn:oasis:names:tc:xacml:2.0:function:x500Name-regexp-match',18);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (169,2,2,null,null,null,1,0,'string-intersection','urn:oasis:names:tc:xacml:1.0:function:string-intersection',26);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (170,2,2,null,null,null,0,0,'string-at-least-one-member-of','urn:oasis:names:tc:xacml:1.0:function:string-at-least-one-member-of',18);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (171,2,-1,null,null,null,1,0,'string-union','urn:oasis:names:tc:xacml:1.0:function:string-union',26);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (172,2,2,null,null,null,0,0,'string-subset','urn:oasis:names:tc:xacml:1.0:function:string-subset',18);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (173,2,2,null,null,null,0,0,'string-set-equals','urn:oasis:names:tc:xacml:1.0:function:string-set-equals',18);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (174,2,2,null,null,null,0,0,'integer-at-least-one-member-of','urn:oasis:names:tc:xacml:1.0:function:integer-at-least-one-member-of',18);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (175,2,-1,null,null,null,1,0,'integer-union','urn:oasis:names:tc:xacml:1.0:function:integer-union',12);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (176,2,2,null,null,null,0,0,'integer-subset','urn:oasis:names:tc:xacml:1.0:function:integer-subset',18);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (177,2,2,null,null,null,0,0,'integer-set-equals','urn:oasis:names:tc:xacml:1.0:function:integer-set-equals',18);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (178,2,2,null,null,null,0,0,'double-at-least-one-member-of','urn:oasis:names:tc:xacml:1.0:function:double-at-least-one-member-of',18);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (179,2,-1,null,null,null,1,0,'double-union','urn:oasis:names:tc:xacml:1.0:function:double-union',25);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (180,2,2,null,null,null,0,0,'double-subset','urn:oasis:names:tc:xacml:1.0:function:double-subset',18);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (181,2,2,null,null,null,0,0,'double-set-equals','urn:oasis:names:tc:xacml:1.0:function:double-set-equals',18);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (182,2,2,null,null,null,1,0,'boolean-intersection','urn:oasis:names:tc:xacml:1.0:function:boolean-intersection',18);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (183,2,2,null,null,null,0,0,'boolean-at-least-one-member-of','urn:oasis:names:tc:xacml:1.0:function:boolean-at-least-one-member-of',18);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (184,2,-1,null,null,null,1,0,'boolean-union','urn:oasis:names:tc:xacml:1.0:function:boolean-union',18);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (185,2,2,null,null,null,0,0,'boolean-subset','urn:oasis:names:tc:xacml:1.0:function:boolean-subset',18);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (186,2,2,null,null,null,0,0,'boolean-set-equals','urn:oasis:names:tc:xacml:1.0:function:boolean-set-equals',18);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (187,2,2,null,null,null,1,0,'time-intersection','urn:oasis:names:tc:xacml:1.0:function:time-intersection',16);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (188,2,2,null,null,null,0,0,'time-at-least-one-member-of','urn:oasis:names:tc:xacml:1.0:function:time-at-least-one-member-of',18);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (189,2,-1,null,null,null,1,0,'time-union','urn:oasis:names:tc:xacml:1.0:function:time-union',16);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (190,2,2,null,null,null,0,0,'time-subset','urn:oasis:names:tc:xacml:1.0:function:time-subset',18);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (191,2,2,null,null,null,0,0,'time-set-equals','urn:oasis:names:tc:xacml:1.0:function:time-set-equals',18);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (192,2,2,null,null,null,1,0,'date-intersection','urn:oasis:names:tc:xacml:1.0:function:date-intersection',21);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (193,2,2,null,null,null,0,0,'date-at-least-one-member-of','urn:oasis:names:tc:xacml:1.0:function:date-at-least-one-member-of',18);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (194,2,-1,null,null,null,1,0,'date-union','urn:oasis:names:tc:xacml:1.0:function:date-union',21);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (195,2,2,null,null,null,0,0,'date-subset','urn:oasis:names:tc:xacml:1.0:function:date-subset',18);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (196,2,2,null,null,null,0,0,'date-set-equals','urn:oasis:names:tc:xacml:1.0:function:date-set-equals',18);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (197,2,2,null,null,null,1,0,'dateTime-intersection','urn:oasis:names:tc:xacml:1.0:function:dateTime-intersection',19);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (198,2,2,null,null,null,0,0,'dateTime-at-least-one-member-of','urn:oasis:names:tc:xacml:1.0:function:dateTime-at-least-one-member-of',18);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (199,2,-1,null,null,null,1,0,'dateTime-union','urn:oasis:names:tc:xacml:1.0:function:dateTime-union',19);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (200,2,2,null,null,null,0,0,'dateTime-subset','urn:oasis:names:tc:xacml:1.0:function:dateTime-subset',18);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (201,2,2,null,null,null,0,0,'dateTime-set-equals','urn:oasis:names:tc:xacml:1.0:function:dateTime-set-equals',18);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (202,2,2,null,null,null,1,0,'anyURI-intersection','urn:oasis:names:tc:xacml:1.0:function:anyURI-intersection',27);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (203,2,2,null,null,null,0,0,'anyURI-at-least-one-member-of','urn:oasis:names:tc:xacml:1.0:function:anyURI-at-least-one-member-of',18);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (204,2,-1,null,null,null,1,0,'anyURI-union','urn:oasis:names:tc:xacml:1.0:function:anyURI-union',27);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (205,2,2,null,null,null,0,0,'anyURI-subset','urn:oasis:names:tc:xacml:1.0:function:anyURI-subset',18);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (206,2,2,null,null,null,0,0,'anyURI-set-equals','urn:oasis:names:tc:xacml:1.0:function:anyURI-set-equals',18);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (207,2,2,null,null,null,1,0,'hexBinary-intersection','urn:oasis:names:tc:xacml:1.0:function:hexBinary-intersection',24);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (208,2,2,null,null,null,0,0,'hexBinary-at-least-one-member-of','urn:oasis:names:tc:xacml:1.0:function:hexBinary-at-least-one-member-of',18);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (209,2,-1,null,null,null,1,0,'hexBinary-union','urn:oasis:names:tc:xacml:1.0:function:hexBinary-union',24);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (210,2,2,null,null,null,0,0,'hexBinary-subset','urn:oasis:names:tc:xacml:1.0:function:hexBinary-subset',18);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (211,2,2,null,null,null,0,0,'hexBinary-set-equals','urn:oasis:names:tc:xacml:1.0:function:hexBinary-set-equals',18);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (212,2,2,null,null,null,1,0,'base64Binary-intersection','urn:oasis:names:tc:xacml:1.0:function:base64Binary-intersection',13);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (213,2,2,null,null,null,0,0,'base64Binary-at-least-one-member-of','urn:oasis:names:tc:xacml:1.0:function:base64Binary-at-least-one-member-of',18);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (214,2,-1,null,null,null,1,0,'base64Binary-union','urn:oasis:names:tc:xacml:1.0:function:base64Binary-union',13);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (215,2,2,null,null,null,0,0,'base64Binary-subset','urn:oasis:names:tc:xacml:1.0:function:base64Binary-subset',18);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (216,2,2,null,null,null,0,0,'base64Binary-set-equals','urn:oasis:names:tc:xacml:1.0:function:base64Binary-set-equals',18);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (217,2,2,null,null,null,1,0,'dayTimeDuration-intersection','urn:oasis:names:tc:xacml:3.0:function:dayTimeDuration-intersection',15);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (218,2,2,null,null,null,0,0,'dayTimeDuration-at-least-one-member-of','urn:oasis:names:tc:xacml:3.0:function:dayTimeDuration-at-least-one-member-of',18);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (219,2,-1,null,null,null,1,0,'dayTimeDuration-union','urn:oasis:names:tc:xacml:3.0:function:dayTimeDuration-union',15);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (220,2,2,null,null,null,0,0,'dayTimeDuration-subset','urn:oasis:names:tc:xacml:3.0:function:dayTimeDuration-subset',18);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (221,2,2,null,null,null,0,0,'dayTimeDuration-set-equals','urn:oasis:names:tc:xacml:3.0:function:dayTimeDuration-set-equals',18);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (222,2,2,null,null,null,1,0,'yearMonthDuration-intersection','urn:oasis:names:tc:xacml:3.0:function:yearMonthDuration-intersection',23);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (223,2,2,null,null,null,0,0,'yearMonthDuration-at-least-one-member-of','urn:oasis:names:tc:xacml:3.0:function:yearMonthDuration-at-least-one-member-of',18);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (224,2,-1,null,null,null,1,0,'yearMonthDuration-union','urn:oasis:names:tc:xacml:3.0:function:yearMonthDuration-union',23);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (225,2,2,null,null,null,0,0,'yearMonthDuration-subset','urn:oasis:names:tc:xacml:3.0:function:yearMonthDuration-subset',18);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (226,2,2,null,null,null,0,0,'yearMonthDuration-set-equals','urn:oasis:names:tc:xacml:3.0:function:yearMonthDuration-set-equals',18);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (227,2,2,null,null,null,1,0,'x500Name-intersection','urn:oasis:names:tc:xacml:1.0:function:x500Name-intersection',14);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (228,2,2,null,null,null,0,0,'x500Name-at-least-one-member-of','urn:oasis:names:tc:xacml:1.0:function:x500Name-at-least-one-member-of',18);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (229,2,-1,null,null,null,1,0,'x500Name-union','urn:oasis:names:tc:xacml:1.0:function:x500Name-union',14);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (230,2,2,null,null,null,0,0,'x500Name-subset','urn:oasis:names:tc:xacml:1.0:function:x500Name-subset',18);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (231,2,2,null,null,null,0,0,'x500Name-set-equals','urn:oasis:names:tc:xacml:1.0:function:x500Name-set-equals',18);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (232,2,2,null,null,null,1,0,'rfc822Name-intersection','urn:oasis:names:tc:xacml:1.0:function:rfc822Name-intersection',20);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (233,2,2,null,null,null,0,0,'rfc822Name-at-least-one-member-of','urn:oasis:names:tc:xacml:1.0:function:rfc822Name-at-least-one-member-of',18);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (234,2,-1,null,null,null,1,0,'rfc822Name-union','urn:oasis:names:tc:xacml:1.0:function:rfc822Name-union',20);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (235,2,2,null,null,null,0,0,'rfc822Name-subset','urn:oasis:names:tc:xacml:1.0:function:rfc822Name-subset',18);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (236,2,2,null,null,null,0,0,'rfc822Name-set-equals','urn:oasis:names:tc:xacml:1.0:function:rfc822Name-set-equals',18);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (237,2,2,null,null,null,0,0,'x500Name-match','urn:oasis:names:tc:xacml:1.0:function:x500Name-match',18);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (238,2,2,null,null,null,0,0,'rfc822Name-match','urn:oasis:names:tc:xacml:1.0:function:rfc822Name-match',18);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (239,2,2,null,null,null,1,0,'integer-intersection','urn:oasis:names:tc:xacml:1.0:function:integer-intersection',12);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (240,2,2,null,null,null,1,0,'double-intersection','urn:oasis:names:tc:xacml:1.0:function:double-intersection',25);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (241,0,-1,null,null,null,0,0,'or','urn:oasis:names:tc:xacml:1.0:function:or',18);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (242,0,-1,null,null,null,0,0,'and','urn:oasis:names:tc:xacml:1.0:function:and',18);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (243,2,-1,null,null,null,0,0,'n-of','urn:oasis:names:tc:xacml:1.0:function:n-of',18);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (244,1,1,null,null,null,0,0,'not','urn:oasis:names:tc:xacml:1.0:function:not',18);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (245,2,-1,1,-1,'1',0,1,'any-of','urn:oasis:names:tc:xacml:3.0:function:any-of',18);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (246,2,-1,1,-1,'1',0,1,'all-of','urn:oasis:names:tc:xacml:3.0:function:all-of',18);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (247,2,-1,1,-1,'0',0,1,'any-of-any','urn:oasis:names:tc:xacml:3.0:function:any-of-any',18);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (248,3,3,2,2,'1',0,1,'all-of-any','urn:oasis:names:tc:xacml:1.0:function:all-of-any',18);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (249,3,3,2,2,'1',0,1,'any-of-all','urn:oasis:names:tc:xacml:1.0:function:any-of-all',18);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (250,3,3,2,2,'1',0,1,'all-of-all','urn:oasis:names:tc:xacml:1.0:function:all-of-all',18);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (251,2,-1,1,-1,'1',1,1,'map','urn:oasis:names:tc:xacml:3.0:function:map',null);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (252,1,1,null,null,null,0,0,'xpath-node-count','urn:oasis:names:tc:xacml:3.0:function:xpath-node-count',12);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (253,2,2,null,null,null,0,0,'xpath-node-equal','urn:oasis:names:tc:xacml:3.0:function:xpath-node-equal',18);
+INSERT INTO XACML.FUNCTIONDEFINITION (ID,ARG_LB,ARG_UB,HO_ARG_LB,HO_ARG_UB,HO_PRIMITIVE,IS_BAG_RETURN,IS_HIGHER_ORDER,SHORT_NAME,XACML_ID,RETURN_DATATYPE) VALUES (254,2,2,null,null,null,0,0,'xpath-node-match','urn:oasis:names:tc:xacml:3.0:function:xpath-node-match',18);
+
+
+INSERT INTO XACML.GLOBALROLESETTINGS (ROLE,LOCKDOWN) VALUES ('super-admin',0);
+
+
+INSERT INTO XACML.PIPCONFIGPARAMS (ID,PARAM_DEFAULT,PARAM_NAME,PARAM_VALUE,REQUIRED,PIP_ID) VALUES (1711,null,'type','jdbc','0',1709);
+INSERT INTO XACML.PIPCONFIGPARAMS (ID,PARAM_DEFAULT,PARAM_NAME,PARAM_VALUE,REQUIRED,PIP_ID) VALUES (1712,null,'jdbc.url','jdbc:h2:file:/','0',1709);
+INSERT INTO XACML.PIPCONFIGPARAMS (ID,PARAM_DEFAULT,PARAM_NAME,PARAM_VALUE,REQUIRED,PIP_ID) VALUES (1713,null,'jdbc.driver','org.h2.Driver','0',1709);
+INSERT INTO XACML.PIPCONFIGPARAMS (ID,PARAM_DEFAULT,PARAM_NAME,PARAM_VALUE,REQUIRED,PIP_ID) VALUES (1714,null,'jdbc.conn.password','smil3yfc','0',1709);
+
+
+
+
+
+
+
+
+INSERT INTO XACML.PIPTYPE (ID,TYPE) VALUES (500,'SQL');
+INSERT INTO XACML.PIPTYPE (ID,TYPE) VALUES (501,'LDAP');
+INSERT INTO XACML.PIPTYPE (ID,TYPE) VALUES (502,'CSV');
+INSERT INTO XACML.PIPTYPE (ID,TYPE) VALUES (503,'Hyper-CSV');
+INSERT INTO XACML.PIPTYPE (ID,TYPE) VALUES (504,'Custom');
+
+
+INSERT INTO XACML.POLICYALGORITHMS (ID,IS_STANDARD,SHORT_NAME,XACML_ID) VALUES (29,'S','ordered-deny-overrides','urn:oasis:names:tc:xacml:3.0:policy-combining-algorithm:ordered-deny-overrides');
+INSERT INTO XACML.POLICYALGORITHMS (ID,IS_STANDARD,SHORT_NAME,XACML_ID) VALUES (30,'S','on-permit-apply-second','urn:oasis:names:tc:xacml:3.0:policy-combining-algorithm:on-permit-apply-second');
+INSERT INTO XACML.POLICYALGORITHMS (ID,IS_STANDARD,SHORT_NAME,XACML_ID) VALUES (31,'S','deny-overrides','urn:oasis:names:tc:xacml:3.0:policy-combining-algorithm:deny-overrides');
+INSERT INTO XACML.POLICYALGORITHMS (ID,IS_STANDARD,SHORT_NAME,XACML_ID) VALUES (32,'S','permit-unless-deny','urn:oasis:names:tc:xacml:3.0:policy-combining-algorithm:permit-unless-deny');
+INSERT INTO XACML.POLICYALGORITHMS (ID,IS_STANDARD,SHORT_NAME,XACML_ID) VALUES (33,'S','deny-unless-permit','urn:oasis:names:tc:xacml:3.0:policy-combining-algorithm:deny-unless-permit');
+INSERT INTO XACML.POLICYALGORITHMS (ID,IS_STANDARD,SHORT_NAME,XACML_ID) VALUES (34,'S','permit-overrides','urn:oasis:names:tc:xacml:3.0:policy-combining-algorithm:permit-overrides');
+INSERT INTO XACML.POLICYALGORITHMS (ID,IS_STANDARD,SHORT_NAME,XACML_ID) VALUES (35,'S','only-one-applicable','urn:oasis:names:tc:xacml:1.0:policy-combining-algorithm:only-one-applicable');
+INSERT INTO XACML.POLICYALGORITHMS (ID,IS_STANDARD,SHORT_NAME,XACML_ID) VALUES (36,'S','first-applicable','urn:oasis:names:tc:xacml:1.0:policy-combining-algorithm:first-applicable');
+INSERT INTO XACML.POLICYALGORITHMS (ID,IS_STANDARD,SHORT_NAME,XACML_ID) VALUES (37,'S','ordered-permit-overrides','urn:oasis:names:tc:xacml:3.0:policy-combining-algorithm:ordered-permit-overrides');
+
+
+
+
+
+
+INSERT INTO XACML.RULEALGORITHMS (ID,IS_STANDARD,SHORT_NAME,XACML_ID) VALUES (38,'S','permit-unless-deny','urn:oasis:names:tc:xacml:3.0:rule-combining-algorithm:permit-unless-deny');
+INSERT INTO XACML.RULEALGORITHMS (ID,IS_STANDARD,SHORT_NAME,XACML_ID) VALUES (39,'S','permit-overrides','urn:oasis:names:tc:xacml:3.0:rule-combining-algorithm:permit-overrides');
+INSERT INTO XACML.RULEALGORITHMS (ID,IS_STANDARD,SHORT_NAME,XACML_ID) VALUES (40,'S','deny-overrides','urn:oasis:names:tc:xacml:3.0:rule-combining-algorithm:deny-overrides');
+INSERT INTO XACML.RULEALGORITHMS (ID,IS_STANDARD,SHORT_NAME,XACML_ID) VALUES (41,'S','ordered-permit-overrides','urn:oasis:names:tc:xacml:3.0:rule-combining-algorithm:ordered-permit-overrides');
+INSERT INTO XACML.RULEALGORITHMS (ID,IS_STANDARD,SHORT_NAME,XACML_ID) VALUES (42,'S','deny-unless-permit','urn:oasis:names:tc:xacml:3.0:rule-combining-algorithm:deny-unless-permit');
+INSERT INTO XACML.RULEALGORITHMS (ID,IS_STANDARD,SHORT_NAME,XACML_ID) VALUES (43,'S','ordered-deny-overrides','urn:oasis:names:tc:xacml:3.0:rule-combining-algorithm:ordered-deny-overrides');
+INSERT INTO XACML.RULEALGORITHMS (ID,IS_STANDARD,SHORT_NAME,XACML_ID) VALUES (44,'S','only-one-applicable','urn:oasis:names:tc:xacml:1.0:rule-combining-algorithm:only-one-applicable');
+INSERT INTO XACML.RULEALGORITHMS (ID,IS_STANDARD,SHORT_NAME,XACML_ID) VALUES (45,'S','first-applicable','urn:oasis:names:tc:xacml:1.0:rule-combining-algorithm:first-applicable');
+
+
+INSERT INTO XACML.SEQUENCE (SEQ_NAME,SEQ_COUNT) VALUES ('SEQ_GEN',3050);
+
+
+
+ALTER TABLE XACML.AttributeAssignment ADD CONSTRAINT FK_AttributeAssignment_OBADVICE_id
+FOREIGN KEY (OBADVICE_id) REFERENCES XACML.Obadvice (id);
+ALTER TABLE XACML.PIPResolverParams ADD CONSTRAINT FK_PIPResolverParams_ID_RESOLVER
+FOREIGN KEY (ID_RESOLVER) REFERENCES XACML.PIPResolver (id);
+ALTER TABLE XACML.Attribute ADD CONSTRAINT FK_Attribute_category
+FOREIGN KEY (category) REFERENCES XACML.Category (id);
+ALTER TABLE XACML.Attribute ADD CONSTRAINT FK_Attribute_constraint_type
+FOREIGN KEY (constraint_type) REFERENCES XACML.ConstraintType (id);
+ALTER TABLE XACML.Attribute ADD CONSTRAINT FK_Attribute_datatype
+FOREIGN KEY (datatype) REFERENCES XACML.Datatype (id);
+ALTER TABLE XACML.FunctionArguments ADD CONSTRAINT FK_FunctionArguments_function_id
+FOREIGN KEY (function_id) REFERENCES XACML.FunctionDefinition (id);
+ALTER TABLE XACML.FunctionArguments ADD CONSTRAINT FK_FunctionArguments_datatype_id
+FOREIGN KEY (datatype_id) REFERENCES XACML.Datatype (id);
+ALTER TABLE XACML.ObadviceExpressions ADD CONSTRAINT FK_ObadviceExpressions_obadvice_id
+FOREIGN KEY (obadvice_id) REFERENCES XACML.Obadvice (id);
+ALTER TABLE XACML.ObadviceExpressions ADD CONSTRAINT FK_ObadviceExpressions_attribute_id
+FOREIGN KEY (attribute_id) REFERENCES XACML.Attribute (id);
+ALTER TABLE XACML.ConstraintValues ADD CONSTRAINT FK_ConstraintValues_attribute_id
+FOREIGN KEY (attribute_id) REFERENCES XACML.Attribute (id);
+ALTER TABLE XACML.DecisionSettings ADD CONSTRAINT FK_DecisionSettings_datatype
+FOREIGN KEY (datatype) REFERENCES XACML.Datatype (id);
+ALTER TABLE XACML.PIPConfiguration ADD CONSTRAINT FK_PIPConfiguration_TYPE
+FOREIGN KEY (TYPE) REFERENCES XACML.PIPType (id);
+
+ALTER TABLE FunctionDefinition ADD CONSTRAINT FK_FunctionDefinition_return_datatype
+FOREIGN KEY (return_datatype) REFERENCES XACML.Datatype (id);
+ALTER TABLE PIPResolver ADD CONSTRAINT FK_PIPResolver_PIP_ID
+FOREIGN KEY (PIP_ID) REFERENCES XACML.PIPConfiguration (id);
+ALTER TABLE PIPConfigParams ADD CONSTRAINT FK_PIPConfigParams_PIP_ID
+FOREIGN KEY (PIP_ID) REFERENCES XACML.PIPConfiguration (id);
+
+ALTER TABLE XACML.PolicyEntity ADD CONSTRAINT UNQ_PolicyEntity_0 UNIQUE (policyName, scope, deleted);
+ALTER TABLE XACML.PolicyEntity ADD CONSTRAINT FK_PolicyEntity_configurationDataId FOREIGN KEY (configurationDataId)
+ REFERENCES XACML.ConfigurationDataEntity (configurationDataId);
diff --git a/packages/base/src/files/install/mysql/data/151001_downgrade_script.sql b/packages/base/src/files/install/mysql/data/151001_downgrade_script.sql new file mode 100644 index 00000000..06cf389a --- /dev/null +++ b/packages/base/src/files/install/mysql/data/151001_downgrade_script.sql @@ -0,0 +1,248 @@ +/*-
+ * ============LICENSE_START======================================================= + * Base Package + * ================================================================================ + * 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=========================================================
+ */
+
+SET FOREIGN_KEY_CHECKS=0;
+DROP TABLE IF EXISTS XACML.ENFORCINGTYPE;
+DROP TABLE IF EXISTS XACML.ACTIONPOLICYDICT;
+DROP TABLE IF EXISTS XACML.TERM;
+DROP TABLE IF EXISTS XACML.PROTOCOLLIST;
+DROP TABLE IF EXISTS XACML.PORTLIST;
+DROP TABLE IF EXISTS XACML.PREFIXLIST;
+DROP TABLE IF EXISTS XACML.ADDRESSGROUP;
+DROP TABLE IF EXISTS XACML.POLICYSCORE;
+DROP TABLE IF EXISTS XACML.VSCLACTION;
+DROP TABLE IF EXISTS XACML.VNFTYPE;
+DROP TABLE IF EXISTS XACML.ATTRIBUTE;
+DROP TABLE IF EXISTS XACML.DECISIONSETTINGS;
+DROP TABLE IF EXISTS XACML.POLICY_MANAGEMENT;
+DROP TABLE IF EXISTS XACML.SCOPES;
+
+DROP TABLE IF EXISTS XACML.SERVICEGROUP;
+CREATE TABLE XACML.SERVICEGROUP
+(
+id integer NOT NULL,
+name varchar(32),
+type varchar(16),
+transportprotocol varchar(255),
+appprotocol varchar(255),
+ports varchar(255),
+`desc` varchar(255),
+primary key(id)
+)
+;
+
+GRANT INSERT, UPDATE, DELETE, SELECT ON XACML.SERVICEGROUP TO POLICY_USER;
+
+
+DROP TABLE IF EXISTS XACML.EnforcingType;
+CREATE TABLE XACML.EnforcingType
+(
+id INTEGER NOT NULL,
+ connectionQuery VARCHAR(255) NOT NULL,
+ enforcingType VARCHAR(255) NOT NULL UNIQUE,
+ script VARCHAR(255) NOT NULL,
+ valueQuery VARCHAR(255) NOT NULL,
+ PRIMARY KEY (id)
+)
+;
+
+DROP TABLE IF EXISTS XACML.ActionPolicyDict;
+CREATE TABLE XACML.ActionPolicyDict
+(
+id INTEGER NOT NULL,
+ ATTRIBUTE_NAME VARCHAR(45) NOT NULL,
+ Body VARCHAR(4096),
+ created_by VARCHAR(255) NOT NULL,
+ created_date TIMESTAMP,
+ description VARCHAR(2048),
+ Headers VARCHAR(1024),
+ Method VARCHAR(45) NOT NULL,
+ modified_by VARCHAR(255) NOT NULL,
+ modified_date TIMESTAMP NOT NULL,
+ Type VARCHAR(45) NOT NULL,
+ URL VARCHAR(45) NOT NULL,
+ PRIMARY KEY (id)
+)
+;
+
+DROP TABLE IF EXISTS XACML.TERM;
+CREATE TABLE XACML.TERM
+(
+id INTEGER NOT NULL,
+ description VARCHAR(100),
+ action VARCHAR(100),
+ destIPList VARCHAR(100),
+ destPortList VARCHAR(100),
+ portList VARCHAR(100),
+ protocolList VARCHAR(100),
+ srcIPList VARCHAR(100),
+ srcPortList VARCHAR(100),
+ termName VARCHAR(45) NOT NULL,
+ PRIMARY KEY (id)
+)
+;
+
+DROP TABLE IF EXISTS XACML.PROTOCOLLIST;
+CREATE TABLE XACML.PROTOCOLLIST
+(
+id INTEGER NOT NULL,
+ description VARCHAR(64),
+ protocolname VARCHAR(45) NOT NULL,
+ PRIMARY KEY (id)
+)
+;
+
+DROP TABLE IF EXISTS XACML.PORTLIST;
+CREATE TABLE XACML.PORTLIST
+(
+id INTEGER NOT NULL,
+ description VARCHAR(64),
+ portname VARCHAR(45) NOT NULL,
+ PRIMARY KEY (id)
+)
+;
+
+DROP TABLE IF EXISTS XACML.PREFIXLIST;
+CREATE TABLE XACML.PREFIXLIST
+(
+id INTEGER NOT NULL,
+ pl_name VARCHAR(45) NOT NULL,
+ pl_value VARCHAR(64) NOT NULL,
+ description VARCHAR(255),
+ PRIMARY KEY (id)
+)
+;
+
+DROP TABLE IF EXISTS XACML.ADDRESSGROUP;
+CREATE TABLE ADDRESSGROUP
+(
+ id INTEGER NOT NULL,
+ name varchar(32),
+ description VARCHAR(64),
+ prefixlist varchar(255)
+);
+
+CREATE INDEX idx_addressgroup on XACML.ADDRESSGROUP(ID);
+
+DROP TABLE IF EXISTS XACML.POLICYSCORE;
+CREATE TABLE XACML.POLICYSCORE
+(
+POLICY_NAME VARCHAR(200) NOT NULL,
+ POLICY_SCORE VARCHAR(100),
+ PRIMARY KEY (POLICY_NAME)
+)
+;
+
+CREATE TABLE XACML.VSCLACTION
+(
+ID INTEGER NOT NULL,
+VSCL_ACTION VARCHAR(45) NOT NULL,
+DESCRIPTION VARCHAR(45) NULL,
+CREATED_DATE TIMESTAMP NOT NULL,
+CREATED_BY VARCHAR(45) NOT NULL,
+MODIFIED_DATE TIMESTAMP NOT NULL,
+MODIFIED_BY VARCHAR(45) NOT NULL,
+PRIMARY KEY(ID)
+);
+
+CREATE TABLE XACML.VNFTYPE
+(
+ID INTEGER NOT NULL,
+VNF_TYPE VARCHAR(45) NOT NULL,
+DESCRIPTION VARCHAR(45) NULL,
+CREATED_DATE TIMESTAMP NOT NULL,
+CREATED_BY VARCHAR(45) NOT NULL,
+MODIFIED_DATE TIMESTAMP NOT NULL,
+MODIFIED_BY VARCHAR(45) NOT NULL,
+PRIMARY KEY(ID)
+)
+;
+
+DROP TABLE IF EXISTS XACML.ATTRIBUTE;
+CREATE TABLE XACML.ATTRIBUTE
+(
+id INTEGER NOT NULL,
+ ATTRIBUTE_VALUE VARCHAR(255),
+ created_by VARCHAR(255) NOT NULL,
+ created_date TIMESTAMP,
+ description VARCHAR(2048),
+ is_designator CHAR NOT NULL,
+ modified_by VARCHAR(255) NOT NULL,
+ modified_date TIMESTAMP NOT NULL,
+ PRIORITY VARCHAR(45),
+ selector_path VARCHAR(2048),
+ xacml_id VARCHAR(100) NOT NULL UNIQUE,
+ category INTEGER,
+ constraint_type INTEGER,
+ datatype INTEGER,
+ PRIMARY KEY (id)
+)
+;
+
+DROP TABLE IF EXISTS XACML.DECISIONSETTINGS;
+CREATE TABLE XACML.DECISIONSETTINGS
+(
+id INTEGER NOT NULL,
+ created_by VARCHAR(255) NOT NULL,
+ created_date TIMESTAMP,
+ description VARCHAR(2048),
+ modified_by VARCHAR(255) NOT NULL,
+ modified_date TIMESTAMP NOT NULL,
+ PRIORITY VARCHAR(45),
+ xacml_id VARCHAR(45) NOT NULL UNIQUE,
+ datatype INTEGER,
+ PRIMARY KEY (id)
+)
+;
+
+DROP TABLE IF EXISTS XACML.POLICY_MANANGEMENT;
+CREATE TABLE XACML.POLICY_MANANGEMENT
+(
+id INTEGER NOT NULL,
+ CONFIG_NAME VARCHAR(45) NOT NULL,
+ CREATE_DATE_TIME TIMESTAMP NOT NULL,
+ CREATED_BY VARCHAR(45) NOT NULL,
+ ECOMP_NAME VARCHAR(45) NOT NULL,
+ POLICY_NAME VARCHAR(45) NOT NULL,
+ scope VARCHAR(45) NOT NULL,
+ UPDATE_DATE_TIME TIMESTAMP NOT NULL,
+ UPDATED_BY VARCHAR(45) NOT NULL,
+ XML text NOT NULL,
+ PRIMARY KEY (id)
+)
+;
+
+GRANT INSERT, UPDATE, DELETE, SELECT XACML.ENFORCINGTYPE;
+GRANT INSERT, UPDATE, DELETE, SELECT XACML.ACTIONPOLICYDICT;
+GRANT INSERT, UPDATE, DELETE, SELECT XACML.TERM;
+GRANT INSERT, UPDATE, DELETE, SELECT XACML.PROTOCOLLIST;
+GRANT INSERT, UPDATE, DELETE, SELECT XACML.PORTLIST;
+GRANT INSERT, UPDATE, DELETE, SELECT XACML.PREFIXLIST;
+GRANT INSERT, UPDATE, DELETE, SELECT XACML.ADDRESSGROUP;
+GRANT INSERT, UPDATE, DELETE, SELECT XACML.POLICYSCORE;
+GRANT INSERT, UPDATE, DELETE, SELECT XACML.VSCLACTION;
+GRANT INSERT, UPDATE, DELETE, SELECT XACML.VNFTYPE;
+GRANT INSERT, UPDATE, DELETE, SELECT XACML.ATTRIBUTE;
+GRANT INSERT, UPDATE, DELETE, SELECT XACML.DECISIONSETTINGS;
+GRANT INSERT, UPDATE, DELETE, SELECT XACML.POLICY_MANAGEMENT;
+GRANT INSERT, UPDATE, DELETE, SELECT XACML.SCOPES;
+
+
+set foreign_key_checks=1;
diff --git a/packages/base/src/files/install/mysql/data/151001_upgrade_script.sql b/packages/base/src/files/install/mysql/data/151001_upgrade_script.sql new file mode 100644 index 00000000..9708fd42 --- /dev/null +++ b/packages/base/src/files/install/mysql/data/151001_upgrade_script.sql @@ -0,0 +1,246 @@ +/*-
+ * ============LICENSE_START======================================================= + * Base Package + * ================================================================================ + * 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=========================================================
+ */
+
+set foreign_key_checks=0;
+DROP TABLE IF EXISTS XACML.SERVICEGROUP;
+CREATE TABLE XACML.SERVICEGROUP
+(
+id integer NOT NULL,
+name varchar(32),
+type varchar(16),
+transportprotocol varchar(255),
+appprotocol varchar(255),
+ports varchar(255),
+description varchar(255),
+primary key(id)
+)
+;
+
+GRANT INSERT, UPDATE, DELETE, SELECT ON XACML.SERVICEGROUP TO POLICY_USER;
+
+DROP TABLE IF EXISTS XACML.ENFORCINGTYPE;
+CREATE TABLE XACML.ENFORCINGTYPE
+(
+ID INTEGER NOT NULL,
+ENFORCINGTYPE VARCHAR(255) NOT NULL,
+SCRIPT VARCHAR(5000) NOT NULL,
+CONNECTIONQUERY VARCHAR(1000) NOT NULL,
+VALUEQUERY VARCHAR(1000) NOT NULL,
+PRIMARY KEY(ID)
+);
+
+GRANT INSERT, UPDATE, DELETE, SELECT ON XACML.ENFORCINGTYPE TO POLICY_USER;
+
+DROP TABLE IF EXISTS XACML.ACTIONPOLICYDICT;
+CREATE TABLE XACML.ACTIONPOLICYDICT
+(
+ID INTEGER NOT NULL,
+TYPE VARCHAR(45) NOT NULL,
+URL VARCHAR(45) NOT NULL,
+METHOD VARCHAR(45) NOT NULL,
+HEADERS VARCHAR(1024) NOT NULL,
+BODY VARCHAR(4096) NOT NULL,
+CREATED_DATE TIMESTAMP NOT NULL,
+CREATED_BY VARCHAR(45) NOT NULL,
+MODIFIED_DATE TIMESTAMP NOT NULL,
+MODIFIED_BY VARCHAR(45) NOT NULL,
+ATTRIBUTE_NAME VARCHAR(45) NOT NULL,
+DESCRIPTION VARCHAR(1024),
+PRIMARY KEY(ID)
+);
+
+GRANT INSERT, UPDATE, DELETE, SELECT ON XACML.ACTIONPOLICYDICT TO POLICY_USER;
+
+DROP TABLE IF EXISTS XACML.TERM;
+CREATE TABLE XACML.TERM
+(
+ID INTEGER NOT NULL,
+TERMNAME VARCHAR(45) NOT NULL,
+SRCIPLIST VARCHAR(100),
+DESTIPLIST VARCHAR(100),
+PROTOCOLLIST VARCHAR(100),
+PORTLIST VARCHAR(100),
+SRCPORTLIST VARCHAR(100),
+DESTPORTLIST VARCHAR(100),
+ACTION VARCHAR(100),
+DESCRIPTION VARCHAR(100),
+PRIMARY KEY(ID)
+);
+
+GRANT INSERT, UPDATE, DELETE, SELECT ON XACML.TERM TO POLICY_USER;
+
+DROP TABLE IF EXISTS XACML.PROTOCOLLIST;
+CREATE TABLE XACML.PROTOCOLLIST
+(
+ID INTEGER NOT NULL,
+PROTOCOLNAME VARCHAR(45) NOT NULL,
+DESCRIPTION VARCHAR(64),
+PRIMARY KEY(ID)
+);
+
+GRANT INSERT, UPDATE, DELETE, SELECT ON XACML.PROTOCOLLIST TO POLICY_USER;
+
+DROP TABLE IF EXISTS XACML.PORTLIST;
+CREATE TABLE XACML.PORTLIST
+(
+ID INTEGER NOT NULL,
+PORTNAME VARCHAR(45) NOT NULL,
+DESCRIPTION VARCHAR(64),
+PRIMARY KEY(ID)
+);
+
+GRANT INSERT, UPDATE, DELETE, SELECT ON XACML.PORTLIST TO POLICY_USER;
+
+DROP TABLE IF EXISTS XACML.PREFIXLIST;
+CREATE TABLE XACML.PREFIXLIST
+(
+ID INTEGER NOT NULL,
+PL_NAME VARCHAR(45) NOT NULL,
+PL_VALUE VARCHAR(64),
+DESCRIPTION VARCHAR(255) NULL,
+PRIMARY KEY(ID)
+);
+
+GRANT INSERT, UPDATE, DELETE, SELECT ON XACML.PREFIXLIST TO POLICY_USER;
+
+DROP TABLE IF EXISTS XACML.ADDRESSGROUP;
+CREATE TABLE XACML.ADDRESSGROUP
+(
+ ID INTEGER NOT NULL,
+ NAME VARCHAR(32),
+ DESCRIPTION VARCHAR(64),
+ PREFIXLIST VARCHAR(255),
+ PRIMARY KEY(ID)
+);
+
+GRANT INSERT, UPDATE, DELETE, SELECT ON XACML.ADDRESSGROUP TO POLICY_USER;
+
+DROP TABLE IF EXISTS XACML.POLICYSCORE;
+CREATE TABLE XACML.POLICYSCORE
+(
+POLICY_NAME VARCHAR(100) NOT NULL,
+POLICY_SCORE VARCHAR(100),
+PRIMARY KEY(POLICY_NAME)
+);
+
+GRANT INSERT, UPDATE, DELETE, SELECT ON XACML.POLICYSCORE TO POLICY_USER;
+
+DROP TABLE IF EXISTS XACML.VSCLACTION;
+CREATE TABLE XACML.VSCLACTION
+(
+ID INTEGER NOT NULL,
+VSCL_ACTION VARCHAR(45) NOT NULL,
+DESCRIPTION VARCHAR(45) NULL,
+CREATED_DATE TIMESTAMP NOT NULL,
+CREATED_BY VARCHAR(45) NOT NULL,
+MODIFIED_DATE TIMESTAMP NOT NULL,
+MODIFIED_BY VARCHAR(45) NOT NULL,
+PRIMARY KEY(ID)
+);
+
+GRANT INSERT, UPDATE, DELETE, SELECT ON XACML.VSCLACTION TO POLICY_USER;
+
+DROP TABLE IF EXISTS XACML.VNFTYPE;
+CREATE TABLE XACML.VNFTYPE
+(
+ID INTEGER NOT NULL,
+VNF_TYPE VARCHAR(45) NOT NULL,
+DESCRIPTION VARCHAR(45) NULL,
+CREATED_DATE TIMESTAMP NOT NULL,
+CREATED_BY VARCHAR(45) NOT NULL,
+MODIFIED_DATE TIMESTAMP NOT NULL,
+MODIFIED_BY VARCHAR(45) NOT NULL,
+PRIMARY KEY(ID)
+);
+
+GRANT INSERT, UPDATE, DELETE, SELECT ON XACML.VNFTYPE TO POLICY_USER;
+
+SET FOREIGN_KEY_CHECKS=0;
+
+DROP TABLE IF EXISTS XACML.ATTRIBUTE;
+CREATE TABLE XACML.ATTRIBUTE
+(
+ID INTEGER NOT NULL,
+CREATED_BY VARCHAR(255) NOT NULL,
+CREATED_DATE TIMESTAMP,
+DESCRIPTION VARCHAR(2048),
+IS_DESIGNATOR CHAR(1) NOT NULL,
+MODIFIED_BY VARCHAR(255) NOT NULL,
+MODIFIED_DATE TIMESTAMP NOT NULL,
+SELECTOR_PATH VARCHAR(2048),
+XACML_ID VARCHAR(500) NOT NULL,
+CATEGORY INTEGER,
+CONSTRAINT_TYPE INTEGER,
+DATATYPE INTEGER,
+PRIORITY VARCHAR(45),
+ATTRIBUTE_VALUE VARCHAR(45),
+PRIMARY KEY(ID)
+);
+
+GRANT INSERT, UPDATE, DELETE, SELECT ON XACML.ATTRIBUTE TO POLICY_USER;
+
+DROP TABLE IF EXISTS XACML.DECISIONSETTINGS;
+CREATE TABLE XACML.DECISIONSETTINGS
+(
+ ID INTEGER NOT NULL,
+ XACML_ID VARCHAR(45) NOT NULL,
+ DESCRIPTION VARCHAR(45),
+ DATATYPE VARCHAR(45) NOT NULL,
+ CREATED_BY VARCHAR(45) NOT NULL,
+ MODIFIED_DATE TIMESTAMP NOT NULL,
+ MODIFIED_BY VARCHAR(45) NOT NULL,
+ PRIORITY VARCHAR(45),
+ CREATED_DATE TIMESTAMP NOT NULL,
+ PRIMARY KEY(ID)
+);
+
+GRANT INSERT, UPDATE, DELETE, SELECT ON XACML.DECISIONSETTINGS TO POLICY_USER;
+
+DROP TABLE IF EXISTS XACML.POLICY_MANAGEMENT;
+CREATE TABLE XACML.POLICY_MANAGEMENT
+(
+ ID INTEGER NOT NULL,
+ CONFIG_NAME VARCHAR(45) NOT NULL,
+ CREATE_DATE_TIME TIMESTAMP,
+ CREATED_BY VARCHAR(45) NOT NULL,
+ ECOMP_NAME VARCHAR(45) NOT NULL,
+ POLICY_NAME VARCHAR(45) NOT NULL,
+ SCOPE VARCHAR(45) NOT NULL,
+ UPDATE_DATE_TIME TIMESTAMP NOT NULL,
+ UPDATED_BY VARCHAR(45) NOT NULL,
+ XML TEXT NOT NULL,
+ PRIMARY KEY(ID)
+);
+
+GRANT INSERT, UPDATE, DELETE, SELECT ON XACML.POLICY_MANAGEMENT TO POLICY_USER;
+
+DROP TABLE IF EXISTS XACML.SCOPES;
+CREATE TABLE XACML.SCOPES
+(
+ ID INTEGER NOT NULL,
+ SCOPE VARCHAR(45) NOT NULL,
+ PARENT_SCOPE INTEGER,
+ PRIMARY KEY(ID)
+);
+
+GRANT INSERT, UPDATE, DELETE, SELECT ON XACML.SCOPES TO POLICY_USER;
+
+
+set foreign_key_checks=1;
diff --git a/packages/base/src/files/install/mysql/data/151002_downgrade_script.sql b/packages/base/src/files/install/mysql/data/151002_downgrade_script.sql new file mode 100644 index 00000000..66cdf302 --- /dev/null +++ b/packages/base/src/files/install/mysql/data/151002_downgrade_script.sql @@ -0,0 +1,21 @@ +/*-
+ * ============LICENSE_START======================================================= + * Base Package + * ================================================================================ + * 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=========================================================
+ */
+
+REVOKE INSERT, UPDATE, DELETE, SELECT ON XACML.SECURITYZONE from policy_user;
diff --git a/packages/base/src/files/install/mysql/data/151002_upgrade_script.sql b/packages/base/src/files/install/mysql/data/151002_upgrade_script.sql new file mode 100644 index 00000000..3b4d27e4 --- /dev/null +++ b/packages/base/src/files/install/mysql/data/151002_upgrade_script.sql @@ -0,0 +1,21 @@ +/*-
+ * ============LICENSE_START======================================================= + * Base Package + * ================================================================================ + * 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=========================================================
+ */
+
+GRANT INSERT, UPDATE, DELETE, SELECT ON XACML.SECURITYZONE TO policy_user;
diff --git a/packages/base/src/files/install/mysql/data/151200_downgrade_script.sql b/packages/base/src/files/install/mysql/data/151200_downgrade_script.sql new file mode 100644 index 00000000..a3147223 --- /dev/null +++ b/packages/base/src/files/install/mysql/data/151200_downgrade_script.sql @@ -0,0 +1,43 @@ +/*-
+ * ============LICENSE_START======================================================= + * Base Package + * ================================================================================ + * 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=========================================================
+ */
+
+set foreign_key_checks=0;
+
+DROP TABLE IF EXISTS xacml.PolicyEntity;
+DROP TABLE IF EXISTS xacml.ConfigurationDataEntity;
+DROP TABLE IF EXISTS xacml.PolicyDBDaoEntity;
+DROP TABLE IF EXISTS xacml.GroupEntity;
+DROP TABLE IF EXISTS xacml.PdpEntity;
+DROP TABLE IF EXISTS xacml.ActionBodyEntity;
+DROP TABLE IF EXISTS xacml.DatabaseLockEntity;
+DROP TABLE IF EXISTS xacml.PolicyGroupEntity;
+
+ALTER TABLE XACML.TERM DROP COLUMN FROMZONE;
+ALTER TABLE XACML.TERM DROP COLUMN TOZONE;
+
+ALTER TABLE XACML.ACTIONPOLICYDICT DROP INDEX ACTIONPOLICYDICT_UNIQUE;
+
+DROP TABLE IF EXISTS XACML.ZONE;
+
+DROP TABLE IF EXISTS XACML.POLICYVERSION;
+
+ALTER TABLE XACML.VSCLACTION DROP INDEX VSCLACTION_VSCL_ACTION_UNIQUE;
+
+set foreign_key_checks=1;
diff --git a/packages/base/src/files/install/mysql/data/151200_upgrade_script.sql b/packages/base/src/files/install/mysql/data/151200_upgrade_script.sql new file mode 100644 index 00000000..ecb23da0 --- /dev/null +++ b/packages/base/src/files/install/mysql/data/151200_upgrade_script.sql @@ -0,0 +1,226 @@ +/*-
+ * ============LICENSE_START======================================================= + * Base Package + * ================================================================================ + * 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=========================================================
+ */
+
+set foreign_key_checks=0;
+
+DROP TABLE IF EXISTS xacml.PolicyEntity;
+CREATE TABLE xacml.PolicyEntity
+(
+policyId BIGINT NOT NULL AUTO_INCREMENT,
+created_by VARCHAR(255) NOT NULL,
+created_date TIMESTAMP,
+deleted BOOLEAN NOT NULL,
+description VARCHAR(2048) NOT NULL,
+modified_by VARCHAR(255) NOT NULL,
+modified_date TIMESTAMP NOT NULL,
+policyData TEXT,
+policyName VARCHAR(255) NOT NULL,
+policyVersion INTEGER,
+scope VARCHAR(255) NOT NULL,
+version INTEGER,
+actionBodyId BIGINT,
+configurationDataId BIGINT,
+PRIMARY KEY (policyId)
+);
+
+CREATE INDEX scope ON xacml.PolicyEntity (scope);
+CREATE INDEX policyName ON xacml.PolicyEntity (policyName);
+
+GRANT INSERT, UPDATE, DELETE, SELECT on xacml.PolicyEntity to policy_user;
+
+DROP TABLE IF EXISTS xacml.ConfigurationDataEntity;
+CREATE TABLE xacml.ConfigurationDataEntity
+(
+ configurationDataId BIGINT NOT NULL AUTO_INCREMENT,
+ configBody TEXT,
+ configType VARCHAR(255) NOT NULL,
+ configurationName VARCHAR(255) NOT NULL,
+ created_by VARCHAR(255) NOT NULL,
+ created_date TIMESTAMP,
+ deleted BOOLEAN NOT NULL,
+ description VARCHAR(2048) NOT NULL,
+ modified_by VARCHAR(255) NOT NULL,
+ modified_date TIMESTAMP NOT NULL,
+ version INTEGER,
+ PRIMARY KEY (configurationDataId)
+);
+
+GRANT INSERT, UPDATE, DELETE, SELECT on xacml.ConfigurationDataEntity to policy_user;
+
+DROP TABLE IF EXISTS xacml.PolicyDBDaoEntity;
+CREATE TABLE xacml.PolicyDBDaoEntity
+(
+ policyDBDaoUrl VARCHAR(500) NOT NULL,
+ created_date TIMESTAMP,
+ description VARCHAR(2048) NOT NULL,
+ modified_date TIMESTAMP NOT NULL,
+ password VARCHAR(100),
+ username VARCHAR(100),
+ PRIMARY KEY (policyDBDaoUrl)
+);
+
+GRANT INSERT, UPDATE, DELETE, SELECT on xacml.PolicyDBDaoEntity to policy_user;
+
+DROP TABLE IF EXISTS xacml.GroupEntity;
+CREATE TABLE xacml.GroupEntity
+(
+groupKey BIGINT NOT NULL AUTO_INCREMENT,
+ created_by VARCHAR(255) NOT NULL,
+ created_date TIMESTAMP,
+ defaultGroup BOOLEAN NOT NULL,
+ deleted BOOLEAN NOT NULL,
+ description VARCHAR(2048) NOT NULL,
+ groupId VARCHAR(100) NOT NULL,
+ groupName VARCHAR(255) NOT NULL,
+ modified_by VARCHAR(255) NOT NULL,
+ modified_date TIMESTAMP NOT NULL,
+ version INTEGER,
+ PRIMARY KEY (groupKey)
+);
+
+GRANT INSERT, UPDATE, DELETE, SELECT on xacml.GroupEntity to policy_user;
+
+DROP TABLE IF EXISTS xacml.PdpEntity;
+CREATE TABLE xacml.PdpEntity
+(
+pdpKey BIGINT NOT NULL AUTO_INCREMENT,
+ created_by VARCHAR(255) NOT NULL,
+ created_date TIMESTAMP,
+ deleted BOOLEAN NOT NULL,
+ description VARCHAR(2048) NOT NULL,
+ jmxPort INTEGER NOT NULL,
+ modified_by VARCHAR(255) NOT NULL,
+ modified_date TIMESTAMP NOT NULL,
+ pdpId VARCHAR(255) NOT NULL,
+ pdpName VARCHAR(255) NOT NULL,
+ groupKey BIGINT,
+ PRIMARY KEY (pdpKey)
+);
+
+GRANT INSERT, UPDATE, DELETE, SELECT on xacml.PdpEntity to policy_user;
+
+DROP TABLE IF EXISTS xacml.ActionBodyEntity;
+CREATE TABLE xacml.ActionBodyEntity
+(
+actionBodyId BIGINT NOT NULL AUTO_INCREMENT,
+ actionBody TEXT,
+ actionBodyName VARCHAR(255) NOT NULL,
+ created_by VARCHAR(255) NOT NULL,
+ created_date TIMESTAMP,
+ deleted BOOLEAN NOT NULL,
+ modified_by VARCHAR(255) NOT NULL,
+ modified_date TIMESTAMP NOT NULL,
+ version INTEGER,
+ PRIMARY KEY (actionBodyId)
+);
+
+GRANT INSERT, UPDATE, DELETE, SELECT on xacml.ActionBodyEntity to policy_user;
+
+DROP TABLE IF EXISTS xacml.DatabaseLockEntity;
+CREATE TABLE xacml.DatabaseLockEntity
+(
+ lock_key INTEGER NOT NULL,
+ PRIMARY KEY (lock_key)
+);
+
+GRANT INSERT, UPDATE, DELETE, SELECT on xacml.DatabaseLockEntity to policy_user;
+
+DROP TABLE IF EXISTS xacml.PolicyGroupEntity;
+CREATE TABLE xacml.PolicyGroupEntity
+(
+groupKey BIGINT NOT NULL AUTO_INCREMENT,
+ policyId BIGINT NOT NULL,
+ PRIMARY KEY (groupKey,policyId)
+);
+
+GRANT INSERT, UPDATE, DELETE, SELECT on xacml.PolicyGroupEntity to policy_user;
+
+ALTER TABLE xacml.PolicyEntity ADD CONSTRAINT UNQ_PolicyEntity_0 UNIQUE (policyName, scope);
+ALTER TABLE xacml.PolicyEntity ADD CONSTRAINT FK_PolicyEntity_configurationDataId FOREIGN KEY (configurationDataId)
+REFERENCES xacml.ConfigurationDataEntity (configurationDataId);
+ALTER TABLE xacml.PolicyEntity ADD CONSTRAINT FK_PolicyEntity_actionBodyId FOREIGN KEY (actionBodyId)
+REFERENCES xacml.ActionBodyEntity (actionBodyId);
+ALTER TABLE xacml.PdpEntity ADD CONSTRAINT FK_PdpEntity_groupKey FOREIGN KEY (groupKey)
+REFERENCES xacml.GroupEntity (groupKey);
+
+ALTER TABLE xacml.PolicyGroupEntity ADD CONSTRAINT FK_PolicyGroupEntity_policyId FOREIGN KEY (policyId)
+REFERENCES xacml.PolicyEntity (policyId);
+
+ALTER TABLE xacml.PolicyGroupEntity ADD CONSTRAINT FK_PolicyGroupEntity_groupKey FOREIGN KEY (groupKey)
+REFERENCES xacml.GroupEntity (groupKey);
+
+-- CREATE SEQUENCE xacml.seqActBody START WITH 1;
+-- CREATE SEQUENCE xacml.seqGroup INCREMENT BY 50 START WITH 50;
+-- CREATE SEQUENCE xacml.seqConfig START WITH 1;
+-- CREATE SEQUENCE xacml.seqPolicy START WITH 1;
+-- CREATE SEQUENCE xacml.seqPdp INCREMENT BY 50 START WITH 50;
+
+DROP TABLE IF EXISTS XACML.TERM;
+CREATE TABLE XACML.TERM
+(
+ ID int NOT NULL,
+ termName VARCHAR(45) NOT NULL,
+ fromzone VARCHAR(100),
+ tozone VARCHAR(100),
+ srcIPList VARCHAR(100),
+ destIPList VARCHAR(100) ,
+ protocolList VARCHAR(100) ,
+ portList VARCHAR(100) ,
+ srcPortList VARCHAR(100) ,
+ destPortList VARCHAR(100) ,
+ action VARCHAR(100),
+ DESCRIPTION VARCHAR(100),
+ PRIMARY KEY(ID)
+);
+
+GRANT INSERT, UPDATE, DELETE, SELECT ON XACML.TERM TO policy_user;
+
+ALTER TABLE XACML.ACTIONPOLICYDICT add constraint ACTIONPOLICYDICT_UNIQUE UNIQUE(ATTRIBUTE_NAME);
+
+DROP TABLE IF EXISTS XACML.ZONE;
+CREATE TABLE XACML.ZONE
+(
+ ID INTEGER NOT NULL,
+ zonename VARCHAR(45) NOT NULL,
+ zonevalue VARCHAR(64)
+);
+
+GRANT INSERT, UPDATE, DELETE, SELECT ON XACML.ZONE TO policy_user;
+
+DROP TABLE IF EXISTS XACML.POLICYVERSION;
+
+CREATE TABLE XACML.POLICYVERSION
+(
+ID INTEGER NOT NULL,
+POLICY_NAME VARCHAR(255) NOT NULL,
+ACTIVE_VERSION INTEGER NULL,
+HIGHEST_VERSION INTEGER NULL,
+CREATED_DATE TIMESTAMP NOT NULL,
+CREATED_BY VARCHAR(45) NOT NULL,
+MODIFIED_DATE TIMESTAMP NOT NULL,
+MODIFIED_BY VARCHAR(45) NOT NULL,
+PRIMARY KEY(ID)
+);
+
+GRANT INSERT, UPDATE, DELETE, SELECT ON XACML.POLICYVERSION to policy_user;
+
+ALTER TABLE XACML.VSCLACTION ADD CONSTRAINT VSCLACTION_VSCL_ACTION_UNIQUE UNIQUE(VSCL_ACTION);
+
+set foreign_key_checks=1;
diff --git a/packages/base/src/files/install/mysql/data/160200_downgrade_script.sql b/packages/base/src/files/install/mysql/data/160200_downgrade_script.sql new file mode 100644 index 00000000..41baaa92 --- /dev/null +++ b/packages/base/src/files/install/mysql/data/160200_downgrade_script.sql @@ -0,0 +1,39 @@ +/*-
+ * ============LICENSE_START======================================================= + * Base Package + * ================================================================================ + * 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=========================================================
+ */
+
+drop table if exists xacml.DCAEuuid;
+drop table if exists xacml.MicroServiceLocation;
+drop table if exists xacml.DCAEUsers;
+drop table if exists xacml.microserviceconfigname;
+drop table if exists xacml.vmType;
+
+alter table xacml.term drop column created_by;
+alter table xacml.term drop column created_date;
+alter table xacml.term drop column modified_by;
+alter table xacml.term drop column modified_date;
+
+drop table if exists xacml.pepoptions;
+drop table if exists xacml.VarbindDictionary;
+drop table if exists xacml.GocEventAlarm;
+drop table if exists xacml.GocTraversal;
+drop table if exists xacml.BRMSParamTemplate;
+
+alter table xacml.roles drop column name;
+
diff --git a/packages/base/src/files/install/mysql/data/160200_upgrade_script.sql b/packages/base/src/files/install/mysql/data/160200_upgrade_script.sql new file mode 100644 index 00000000..46629a94 --- /dev/null +++ b/packages/base/src/files/install/mysql/data/160200_upgrade_script.sql @@ -0,0 +1,127 @@ +/*-
+ * ============LICENSE_START======================================================= + * Base Package + * ================================================================================ + * 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=========================================================
+ */
+
+drop table if exists xacml.DCAEuuid;
+CREATE TABLE xacml.DCAEuuid (
+ ID int NOT NULL,
+ name VARCHAR(45) NOT NULL,
+ description VARCHAR(64)
+ );
+
+drop table if exists xacml.MicroServiceLocation;
+CREATE TABLE xacml.MicroServiceLocation (
+ ID int NOT NULL,
+ name VARCHAR(45) NOT NULL,
+ description VARCHAR(64)
+ );
+
+drop table if exists xacml.DCAEUsers;
+CREATE TABLE xacml.DCAEUsers (
+ ID int NOT NULL,
+ name VARCHAR(45) NOT NULL,
+ description VARCHAR(64)
+ );
+
+drop table if exists xacml.microserviceconfigname;
+CREATE TABLE xacml.microserviceconfigname (
+ ID int NOT NULL,
+ name VARCHAR(45) NOT NULL,
+ description VARCHAR(64)
+ );
+
+drop table if exists xacml.vmType;
+CREATE TABLE xacml.vmType (
+ ID int NOT NULL,
+ name VARCHAR(45) NOT NULL,
+ description VARCHAR(64)
+ );
+
+alter table xacml.term add created_by varchar(100);
+alter table xacml.term add created_date date;
+alter table xacml.term add modified_by varchar(100);
+alter table xacml.term add modified_date date;
+
+drop table if exists xacml.pepoptions;
+CREATE TABLE xacml.PEPOPTIONS (
+ID INT NOT NULL,
+PEP_NAME VARCHAR(45) NOT NULL,
+DESCRIPTION VARCHAR(1024),
+Actions VARCHAR(1024) NOT NULL,
+CREATED_DATE TIMESTAMP NOT NULL,
+CREATED_BY VARCHAR(45) NOT NULL,
+MODIFIED_DATE TIMESTAMP NOT NULL,
+MODIFIED_BY VARCHAR(45) NOT NULL,
+PRIMARY KEY(ID)
+);
+
+drop table if exists xacml.VarbindDictionary;
+CREATE TABLE xacml.VarbindDictionary (
+Id INT NOT NULL,
+created_by VARCHAR(255) NOT NULL,
+created_date TIMESTAMP,
+modified_by VARCHAR(255) NOT NULL,
+modified_date TIMESTAMP NOT NULL,
+varbind_Description VARCHAR(2048),
+varbind_Name VARCHAR(45) NOT NULL UNIQUE,
+varbind_oid VARCHAR(45) NOT NULL,
+PRIMARY KEY (Id)
+);
+
+drop table if exists xacml.GocEventAlarm;
+CREATE TABLE xacml.GocEventAlarm(
+Id INT NOT NULL,
+Event VARCHAR(45) NOT NULL,
+description VARCHAR(1024),
+Alarm VARCHAR(1024) NOT NULL,
+CREATED_DATE TIMESTAMP NOT NULL,
+CREATED_BY VARCHAR(45) NOT NULL,
+MODIFIED_DATE TIMESTAMP NOT NULL,
+MODIFIED_BY VARCHAR(45) NOT NULL,
+PRIMARY KEY(ID)
+);
+
+drop table if exists xacml.GocTraversal;
+CREATE TABLE xacml.GocTraversal(
+ID INT NOT NULL,
+TRAVERSAL VARCHAR(45) NOT NULL,
+DESCRIPTION VARCHAR(45) NULL,
+CREATED_DATE TIMESTAMP NOT NULL,
+CREATED_BY VARCHAR(45) NOT NULL,
+MODIFIED_DATE TIMESTAMP NOT NULL,
+MODIFIED_BY VARCHAR(45) NOT NULL,
+PRIMARY KEY(ID)
+);
+
+drop table if exists xacml.BRMSParamTemplate;
+CREATE TABLE xacml.BRMSParamTemplate(
+ID INT NOT NULL,
+param_template_name VARCHAR(45) NOT NULL,
+DESCRIPTION VARCHAR(45),
+rule LONGTEXT NOT NULL,
+CREATED_DATE TIMESTAMP NOT NULL,
+CREATED_BY VARCHAR(45) NOT NULL,
+PRIMARY KEY(ID)
+);
+
+alter table xacml.roles add name varchar(45);
+
+
+
+
diff --git a/packages/base/src/files/install/mysql/data/160201_downgrade_script.sql b/packages/base/src/files/install/mysql/data/160201_downgrade_script.sql new file mode 100644 index 00000000..5f6381af --- /dev/null +++ b/packages/base/src/files/install/mysql/data/160201_downgrade_script.sql @@ -0,0 +1,43 @@ +/*-
+ * ============LICENSE_START======================================================= + * Base Package + * ================================================================================ + * 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=========================================================
+ */
+
+alter table xacml.attribute modify created_date timestamp;
+alter table xacml.obadvice modify created_date timestamp;
+alter table xacml.decisionsettings modify created_date timestamp;
+alter table xacml.actionpolicydict modify created_date timestamp;
+alter table xacml.ecompname modify created_date timestamp;
+alter table xacml.policyentity modify created_date timestamp;
+alter table xacml.configurationdataentity modify created_date timestamp;
+alter table xacml.policydbdaoentity modify created_date timestamp;
+
+alter table xacml.actionpolicydict modify created_date timestamp;
+alter table xacml.vsclaction modify created_date timestamp;
+alter table xacml.vnftype modify created_date timestamp;
+
+alter table xacml.groupentity modify created_date timestamp;
+alter table xacml.pdpentity modify created_date timestamp;
+alter table xacml.actionbodyentity modify created_date timestamp;
+
+alter table xacml.term modify created_date timestamp;
+alter table xacml.varbinddictionary modify created_date timestamp;
+alter table xacml.pepoptions modify created_date timestamp;
+alter table xacml.goceventalarm modify created_date timestamp;
+alter table xacml.goctraversal modify created_date timestamp;
+alter table xacml.brmsparamtemplate modify created_date timestamp;
diff --git a/packages/base/src/files/install/mysql/data/160201_upgrade_script.sql b/packages/base/src/files/install/mysql/data/160201_upgrade_script.sql new file mode 100644 index 00000000..70ddf791 --- /dev/null +++ b/packages/base/src/files/install/mysql/data/160201_upgrade_script.sql @@ -0,0 +1,44 @@ +/*-
+ * ============LICENSE_START======================================================= + * Base Package + * ================================================================================ + * 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=========================================================
+ */
+
+alter table xacml.attribute modify created_date timestamp default current_timestamp;
+alter table xacml.obadvice modify created_date timestamp default current_timestamp;
+alter table xacml.decisionsettings modify created_date timestamp default current_timestamp;
+alter table xacml.actionpolicydict modify created_date timestamp default current_timestamp;
+alter table xacml.ecompname modify created_date timestamp default current_timestamp;
+alter table xacml.policyentity modify created_date timestamp default current_timestamp;
+alter table xacml.configurationdataentity modify created_date timestamp default current_timestamp;
+alter table xacml.policydbdaoentity modify created_date timestamp default current_timestamp;
+
+alter table xacml.actionpolicydict modify created_date timestamp default current_timestamp;
+alter table xacml.vsclaction modify created_date timestamp default current_timestamp;
+alter table xacml.vnftype modify created_date timestamp default current_timestamp;
+
+alter table xacml.groupentity modify created_date timestamp default current_timestamp;
+alter table xacml.pdpentity modify created_date timestamp default current_timestamp;
+alter table xacml.actionbodyentity modify created_date timestamp default current_timestamp;
+
+alter table xacml.term modify created_date timestamp default current_timestamp;
+alter table xacml.term modify modified_date timestamp not null;
+alter table xacml.varbinddictionary modify created_date timestamp default current_timestamp;
+alter table xacml.pepoptions modify created_date timestamp default current_timestamp;
+alter table xacml.goceventalarm modify created_date timestamp default current_timestamp;
+alter table xacml.goctraversal modify created_date timestamp default current_timestamp;
+alter table xacml.brmsparamtemplate modify created_date timestamp default current_timestamp;
diff --git a/packages/base/src/files/install/mysql/data/160400_downgrade_script.sql b/packages/base/src/files/install/mysql/data/160400_downgrade_script.sql new file mode 100644 index 00000000..d5a990fc --- /dev/null +++ b/packages/base/src/files/install/mysql/data/160400_downgrade_script.sql @@ -0,0 +1,33 @@ +/*- + * ============LICENSE_START======================================================= + * Base Package + * ================================================================================ + * 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========================================================= + */ + +drop table if exists xacml.MicroServiceModels; +drop table if exists xacml.GocRCAlarm; +drop table if exists xacml.xacmlGocVnfType; +drop table if exists xacml.CLOSEDLOOPD2SERVICES; +drop table if exists xacml.CLOSEDLOOPSITE; +drop table if exists xacml.USERINFO; + +drop table if exists drools.sessioninfo; +drop table if exists drools.WORKITEMINFO; +drop table if exists drools.droolspdpentity; + + + diff --git a/packages/base/src/files/install/mysql/data/160400_upgrade_script.sql b/packages/base/src/files/install/mysql/data/160400_upgrade_script.sql new file mode 100644 index 00000000..745b4715 --- /dev/null +++ b/packages/base/src/files/install/mysql/data/160400_upgrade_script.sql @@ -0,0 +1,124 @@ +/*- + * ============LICENSE_START======================================================= + * Base Package + * ================================================================================ + * 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========================================================= + */ + +drop table if exists xacml.MicroServiceModels; +CREATE TABLE xacml.MicroServiceModels ( +ID INTEGER NOT NULL, +modelName VARCHAR(75) NOT NULL, +DESCRIPTION VARCHAR(45), +Dependency VARCHAR(255), +imported_by VARCHAR(45) NOT NULL, +attributes LONGTEXT, +ref_attributes LONGTEXT, +PRIMARY KEY(ID) +); + +drop table if exists xacml.GocRCAlarm; +CREATE TABLE xacml.GocRCAlarm( +ID int NOT NULL, +alarmName VARCHAR(45) NOT NULL, +DESCRIPTION VARCHAR(45) NULL, +CREATED_DATE TIMESTAMP NOT NULL default current_timestamp, +CREATED_BY VARCHAR(45) NOT NULL, +MODIFIED_DATE TIMESTAMP NOT NULL, +MODIFIED_BY VARCHAR(45) NOT NULL, +PRIMARY KEY(ID) +); + +drop table if exists xacml.xacmlGocVnfType; +CREATE TABLE xacml.xacmlGocVnfType( +ID int NOT NULL, +vnfName VARCHAR(45) NOT NULL, +DESCRIPTION VARCHAR(45) NULL, +CREATED_DATE TIMESTAMP NOT NULL default current_timestamp, +CREATED_BY VARCHAR(45) NOT NULL, +MODIFIED_DATE TIMESTAMP NOT NULL, +MODIFIED_BY VARCHAR(45) NOT NULL, +PRIMARY KEY(ID) +); + +drop table if exists xacml.CLOSEDLOOPD2SERVICES; +CREATE TABLE xacml.CLOSEDLOOPD2SERVICES( +ID INTEGER NOT NULL, +SERVICE_NAME VARCHAR(45) NOT NULL, +DESCRIPTION VARCHAR(45) NULL, +CREATED_DATE TIMESTAMP NOT NULL default current_timestamp, +CREATED_BY VARCHAR(45) NOT NULL, +MODIFIED_DATE TIMESTAMP NOT NULL, +MODIFIED_BY VARCHAR(45) NOT NULL, +PRIMARY KEY(ID) +); + +drop table if exists xacml.CLOSEDLOOPSITE; +CREATE TABLE xacml.CLOSEDLOOPSITE( +ID INTEGER NOT NULL, +SITE_NAME VARCHAR(45) NOT NULL, +DESCRIPTION VARCHAR(45) NULL, +CREATED_DATE TIMESTAMP NOT NULL default current_timestamp, +CREATED_BY VARCHAR(45) NOT NULL, +MODIFIED_DATE TIMESTAMP NOT NULL, +MODIFIED_BY VARCHAR(45) NOT NULL, +PRIMARY KEY(ID) +); + +drop table if exists xacml.USERINFO; +CREATE TABLE xacml.USERINFO( +ATTUID VARCHAR(45) NOT NULL, +NAME VARCHAR(45) NOT NULL, +PRIMARY KEY(ATTUID) +); + +-- use BLOB instead of LONGVARBINARY +drop table if exists drools.sessioninfo; +CREATE TABLE drools.SESSIONINFO +( +ID BIGINT NOT NULL, +LASTMODIFICATIONDATE TIMESTAMP, +RULESBYTEARRAY BLOB, +STARTDATE TIMESTAMP default current_timestamp, +OPTLOCK INTEGER, +PRIMARY KEY (ID) +); + +drop table if exists drools.WORKITEMINFO; +CREATE TABLE drools.WORKITEMINFO +( +WORKITEMID BIGINT NOT NULL, +CREATIONDATE TIMESTAMP default current_timestamp, +`NAME` VARCHAR(500), +PROCESSINSTANCEID BIGINT, +STATE BIGINT, +OPTLOCK INTEGER, +WORKITEMBYTEARRAY BLOB, +PRIMARY KEY (WORKITEMID) +); + +drop table if exists drools.droolspdpentity; +CREATE TABLE drools.DROOLSPDPENTITY +( + PDPID VARCHAR(100) NOT NULL, + DESIGNATED BOOLEAN NOT NULL DEFAULT FALSE, + PRIORITY INT NOT NULL DEFAULT 0, + UPDATEDDATE DATE NOT NULL, + GROUPID VARCHAR(100) NOT NULL, + SESSIONID BIGINT NOT NULL +); + + diff --git a/packages/base/src/files/m2/settings.xml b/packages/base/src/files/m2/settings.xml new file mode 100755 index 00000000..f7b3c9e5 --- /dev/null +++ b/packages/base/src/files/m2/settings.xml @@ -0,0 +1,83 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + ============LICENSE_START======================================================= + Base Package + ================================================================================ + 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========================================================= + --> + + +<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0 http://maven.apache.org/xsd/settings-1.0.0.xsd"> + + <profiles> + <profile> + <id>policy-profile</id> + <activation> + <activeByDefault>true</activeByDefault> + </activation> + + <repositories> + <repository> + <id>${{snapshotRepositoryID}}</id> + <url>${{snapshotRepositoryUrl}}</url> + <releases> + <enabled>false</enabled> + <updatePolicy>always</updatePolicy> + </releases> + <snapshots> + <enabled>true</enabled> + <updatePolicy>always</updatePolicy> + </snapshots> + </repository> + + <repository> + <id>${{releaseRepositoryID}}</id> + <url>${{releaseRepositoryUrl}}</url> + <releases> + <enabled>true</enabled> + <updatePolicy>always</updatePolicy> + </releases> + <snapshots> + <enabled>false</enabled> + <updatePolicy>always</updatePolicy> + </snapshots> + </repository> + </repositories> + + </profile> + </profiles> + + <activeProfiles> + <activeProfile>policy-profile</activeProfile> + </activeProfiles> + + <servers> + <server> + <id>${{snapshotRepositoryID}}</id> + <username>${{repositoryUsername}}</username> + <password>${{repositoryPassword}}</password> + </server> + <server> + <id>${{releaseRepositoryID}}</id> + <username>${{repositoryUsername}}</username> + <password>${{repositoryPassword}}</password> + </server> + </servers> + +</settings> + diff --git a/packages/base/src/files/m2/standalone-settings.xml b/packages/base/src/files/m2/standalone-settings.xml new file mode 100755 index 00000000..277113c2 --- /dev/null +++ b/packages/base/src/files/m2/standalone-settings.xml @@ -0,0 +1,57 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + ============LICENSE_START======================================================= + Base Package + ================================================================================ + 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========================================================= + --> + + +<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0 http://maven.apache.org/xsd/settings-1.0.0.xsd"> + + <profiles> + <profile> + <id>policy-profile</id> + <activation> + <activeByDefault>true</activeByDefault> + </activation> + + <repositories> + <repository> + <id>${{fileRepoID}}</id> + <url>${{fileRepoUrl}}</url> + <releases> + <enabled>true</enabled> + <updatePolicy>always</updatePolicy> + </releases> + <snapshots> + <enabled>true</enabled> + <updatePolicy>always</updatePolicy> + </snapshots> + </repository> + </repositories> + + </profile> + </profiles> + + <activeProfiles> + <activeProfile>policy-profile</activeProfile> + </activeProfiles> + +</settings> + diff --git a/packages/install/.gitignore b/packages/install/.gitignore new file mode 100644 index 00000000..b83d2226 --- /dev/null +++ b/packages/install/.gitignore @@ -0,0 +1 @@ +/target/ diff --git a/packages/install/pom.xml b/packages/install/pom.xml new file mode 100644 index 00000000..2ed29546 --- /dev/null +++ b/packages/install/pom.xml @@ -0,0 +1,94 @@ +<!-- + ============LICENSE_START======================================================= + Policy Packages + ================================================================================ + 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/xsd/maven-4.0.0.xsd"> + + <modelVersion>4.0.0</modelVersion> + + <parent> + <groupId>org.openecomp.policy.drools-pdp</groupId> + <artifactId>packages</artifactId> + <version>1.0.0-SNAPSHOT</version> + </parent> + + <artifactId>install-drools</artifactId> + <packaging>pom</packaging> + + <name>Installation Package</name> + <description>D2 ECOMP Policy Drools PDP Installation Package</description> + + <build> + <plugins> + <plugin> + <artifactId>maven-assembly-plugin</artifactId> + <executions> + <execution> + <goals> + <goal>single</goal> + </goals> + <phase>package</phase> + <configuration> + <descriptors> + <descriptor>src/assembly/zip.xml</descriptor> + </descriptors> + <appendAssemblyId>false</appendAssemblyId> + </configuration> + </execution> + </executions> + </plugin> + </plugins> + </build> + + <!-- List any dependencies here that should be included in the installer zip --> + <dependencies> + <dependency> + <groupId>org.openecomp.policy.drools-pdp</groupId> + <artifactId>base</artifactId> + <version>${project.version}</version> + <type>tar.gz</type> + </dependency> + <dependency> + <groupId>org.openecomp.policy.drools-pdp</groupId> + <artifactId>policy-core</artifactId> + <version>${project.version}</version> + <type>zip</type> + </dependency> + <dependency> + <groupId>org.openecomp.policy.drools-pdp</groupId> + <artifactId>policy-management</artifactId> + <version>${project.version}</version> + <type>zip</type> + </dependency> + <dependency> + <groupId>org.openecomp.policy.drools-pdp</groupId> + <artifactId>policy-persistence</artifactId> + <version>${project.version}</version> + <type>zip</type> + </dependency> + <dependency> + <groupId>org.openecomp.policy.drools-pdp</groupId> + <artifactId>policy-healthcheck</artifactId> + <version>${project.version}</version> + <type>zip</type> + </dependency> + </dependencies> + +</project> diff --git a/packages/install/src/assembly/zip.xml b/packages/install/src/assembly/zip.xml new file mode 100644 index 00000000..48b82d40 --- /dev/null +++ b/packages/install/src/assembly/zip.xml @@ -0,0 +1,39 @@ +<!-- + ============LICENSE_START======================================================= + Installation Package + ================================================================================ + 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========================================================= + --> + +<assembly> + <id>zipfile</id> + <formats> + <format>zip</format> + </formats> + <includeBaseDirectory>false</includeBaseDirectory> + <fileSets> + <fileSet> + <directory>src/files</directory> + <outputDirectory>.</outputDirectory> + <fileMode>755</fileMode> + </fileSet> + </fileSets> + <dependencySets> + <dependencySet> + <useTransitiveDependencies>false</useTransitiveDependencies> + </dependencySet> + </dependencySets> +</assembly> diff --git a/packages/install/src/files/base.conf b/packages/install/src/files/base.conf new file mode 100644 index 00000000..90128e91 --- /dev/null +++ b/packages/install/src/files/base.conf @@ -0,0 +1,68 @@ +POLICY_HOME=/opt/app/policy +JAVA_HOME=/opt/jdk1.8.0_77 +M2_HOME=/opt/app/policy/3rdparty/apache-maven-3.3.1 + +ENGINE_MANAGEMENT_PORT=9696 +ENGINE_MANAGEMENT_HOST=localhost +ENGINE_MANAGEMENT_USER=@1b3rt +ENGINE_MANAGEMENT_PASSWORD=31nst@1n + +ENGINE_HEALTHCHECK_HOST=0.0.0.0 +ENGINE_HEALTHCHECK_PORT=9697 + +JDBC_DRIVER=org.mariadb.jdbc.Driver +JDBC_URL=jdbc:mysql://localhost:3306/xacml +JDBC_DROOLS_URL=jdbc:mysql://localhost:3306/drools +JDBC_USER=policy_user +JDBC_PASSWORD= + +NAGIOS_CONFIG_NAME=policy +NAGIOS_NRDP_URL= +NAGIOS_NRDP_TOKEN=bbpguvsohehj +NAGIOS_NRDP_DISABLED=true + +# Integrity Monitor properties +site_name=site_1 +fp_monitor_interval=30 +failed_counter_threshold=3 +test_trans_interval=20 +write_fpc_interval=5 +max_fpc_update_interval=60 +test_via_jmx=false +node_type=pdp_drools +# Dependency groups are groups of resources upon which a node operational state is dependent upon. +# Each group is a comma-separated list of resource names and groups are separated by a semicolon. +dependency_groups=site_1.pap_1,site_1.pap_2;site_1.pdp_1,site_1.pdp_2 +resource_name=pdpd_1 + +# The (optional) period of time in seconds between executions of the integrity audit. +# Value < 0 : Audit does not run (default value if property is not present = -1) +# Value = 0 : Audit runs continuously +# Value > 0 : The period of time in seconds between execution of the audit on a particular node +integrity_audit_period_seconds=-1 + +host_port=0.0.0.0:9981 + +# To use a Nexus repository for rules artifacts, +# following properties must be uncommented and set: +#repositoryID=policy-nexus +#repositoryUrl=http://....(URL for the repository goes here) +#repositoryUsername=(nexus username goes here) +#repositoryPassword=(password goes here) + +# just for testing purposes, modify at installation +PDPD_CONFIGURATION_TOPIC=PDPD_CONFIGURATION +PDPD_CONFIGURATION_SERVERS= +PDPD_CONFIGURATION_API_KEY= +PDPD_CONFIGURATION_API_SECRET= +PDPD_CONFIGURATION_CONSUMER_GROUP= +PDPD_CONFIGURATION_CONSUMER_INSTANCE= +PDPD_CONFIGURATION_PARTITION_KEY= + +PAP_HOST= +PAP_USERNAME= +PAP_PASSWORD= + +PDP_HOST= +PDP_USERNAME= +PDP_PASSWORD= diff --git a/packages/install/src/files/policy-management.conf b/packages/install/src/files/policy-management.conf new file mode 100644 index 00000000..609aa868 --- /dev/null +++ b/packages/install/src/files/policy-management.conf @@ -0,0 +1,5 @@ +CONTROLLER_ARTIFACT_ID=policy-management +CONTROLLER_NAME=policy-management-controller +CONTROLLER_PORT=9696 +RULES_ARTIFACT=org.openecomp.policy:dummy-artifact:1.0.0-SNAPSHOT +UEB_TOPIC=policyengine-develop diff --git a/packages/pom.xml b/packages/pom.xml new file mode 100644 index 00000000..3cde69cd --- /dev/null +++ b/packages/pom.xml @@ -0,0 +1,43 @@ +<!-- + ============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/xsd/maven-4.0.0.xsd"> + + <modelVersion>4.0.0</modelVersion> + + <parent> + <groupId>org.openecomp.policy.drools-pdp</groupId> + <artifactId>drools-pdp</artifactId> + <version>1.0.0-SNAPSHOT</version> + </parent> + + <artifactId>packages</artifactId> + <packaging>pom</packaging> + + <name>Policy Packages</name> + <description>D2 ECOMP Policy Drools PDP Installation Packages</description> + + <modules> + <module>base</module> + <!-- <module>root</module> --> + <module>install</module> + </modules> +</project> 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> diff --git a/policy-endpoints/pom.xml b/policy-endpoints/pom.xml new file mode 100644 index 00000000..e62853c5 --- /dev/null +++ b/policy-endpoints/pom.xml @@ -0,0 +1,157 @@ +<!-- + ============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/xsd/maven-4.0.0.xsd"> + + <modelVersion>4.0.0</modelVersion> + + <parent> + <groupId>org.openecomp.policy.drools-pdp</groupId> + <artifactId>drools-pdp</artifactId> + <version>1.0.0-SNAPSHOT</version> + </parent> + + <artifactId>policy-endpoints</artifactId> + + <name>policy-endpoints</name> + <description>Policy UEB support</description> + + <properties> + <maven.compiler.source>1.8</maven.compiler.source> + <maven.compiler.target>1.8</maven.compiler.target> + <cambria.version>0.0.1</cambria.version> + <dmaap.version>0.2.12</dmaap.version> + <jetty.version>9.3.14.v20161028</jetty.version> + <jersey.version>2.22.1</jersey.version> + <jackson.version>2.8.4</jackson.version> + + </properties> + + <dependencies> + <dependency> + <groupId>com.att.nsa</groupId> + <artifactId>cambriaClient</artifactId> + <version>${cambria.version}</version> + <exclusions> + <exclusion> + <groupId>org.slf4j</groupId> + <artifactId>slf4j-log4j12</artifactId> + </exclusion> + <exclusion> + <groupId>com.att.nsa</groupId> + <artifactId>saClientLibrary</artifactId> + </exclusion> + </exclusions> + </dependency> + <dependency> + <groupId>com.att.nsa</groupId> + <artifactId>dmaapClient</artifactId> + <version>${dmaap.version}</version> + <exclusions> + <exclusion> + <groupId>org.slf4j</groupId> + <artifactId>slf4j-log4j12</artifactId> + </exclusion> + </exclusions> + </dependency> + <dependency> + <groupId>org.eclipse.jetty</groupId> + <artifactId>jetty-server</artifactId> + <version>${jetty.version}</version> + </dependency> + + <dependency> + <groupId>org.eclipse.jetty</groupId> + <artifactId>jetty-servlet</artifactId> + <version>${jetty.version}</version> + </dependency> + + <dependency> + <groupId>org.glassfish.jersey.core</groupId> + <artifactId>jersey-server</artifactId> + <version>${jersey.version}</version> + </dependency> + + <dependency> + <groupId>org.glassfish.jersey.containers</groupId> + <artifactId>jersey-container-servlet-core</artifactId> + <version>${jersey.version}</version> + </dependency> + + <dependency> + <groupId>org.glassfish.jersey.media</groupId> + <artifactId>jersey-media-json-jackson</artifactId> + <version>${jersey.version}</version> + </dependency> + + <dependency> + <groupId>org.glassfish.jersey.containers</groupId> + <artifactId>jersey-container-jetty-http</artifactId> + <version>${jersey.version}</version> + <exclusions> + <exclusion> + <groupId>org.eclipse.jetty</groupId> + <artifactId>jetty-util</artifactId> + </exclusion> + </exclusions> + </dependency> + + <dependency> + <groupId>org.glassfish.jersey.core</groupId> + <artifactId>jersey-client</artifactId> + <version>${jersey.version}</version> + </dependency> + + <dependency> + <groupId>com.fasterxml.jackson.core</groupId> + <artifactId>jackson-databind</artifactId> + <version>${jackson.version}</version> + </dependency> + + <dependency> + <groupId>com.fasterxml.jackson.datatype</groupId> + <artifactId>jackson-datatype-jsr310</artifactId> + <version>${jackson.version}</version> + </dependency> + + <dependency> + <groupId>org.apache.httpcomponents</groupId> + <artifactId>httpcore</artifactId> + <version>4.4.4</version> + </dependency> + <dependency> + <groupId>org.apache.httpcomponents</groupId> + <artifactId>httpclient</artifactId> + <version>4.5</version> + </dependency> + <dependency> + <groupId>org.apache.commons</groupId> + <artifactId>commons-collections4</artifactId> + <version>4.1</version> + </dependency> + <dependency> + <groupId>org.openecomp.policy.drools-pdp</groupId> + <artifactId>policy-core</artifactId> + <version>1.0.0-SNAPSHOT</version> + </dependency> + </dependencies> + +</project> diff --git a/policy-endpoints/src/main/java/org/openecomp/policy/drools/event/comm/Topic.java b/policy-endpoints/src/main/java/org/openecomp/policy/drools/event/comm/Topic.java new file mode 100644 index 00000000..d38bab5a --- /dev/null +++ b/policy-endpoints/src/main/java/org/openecomp/policy/drools/event/comm/Topic.java @@ -0,0 +1,76 @@ +/*- + * ============LICENSE_START======================================================= + * policy-endpoints + * ================================================================================ + * 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.event.comm; + +import java.util.List; + +/** + * Essential Topic Data + */ +public interface Topic { + + public static final String NETWORK_LOGGER = "networkLogger"; + + /** + * Underlying Communication infrastructure Types + */ + public enum CommInfrastructure { + /** + * UEB Communication Infrastructure + */ + UEB, + /** + * DMAAP Communication Infrastructure + */ + DMAAP, + /** + * REST Communication Infrastructure + */ + REST + } + + /** + * gets the topic name + * + * @return topic name + */ + public String getTopic(); + + /** + * gets the communication infrastructure type + * @return + */ + public CommInfrastructure getTopicCommInfrastructure(); + + /** + * return list of servers + * @return bus servers + */ + public List<String> getServers(); + + /** + * get the more recent events in this topic entity + * + * @return list of most recent events + */ + public String[] getRecentEvents(); + +} diff --git a/policy-endpoints/src/main/java/org/openecomp/policy/drools/event/comm/TopicEndpoint.java b/policy-endpoints/src/main/java/org/openecomp/policy/drools/event/comm/TopicEndpoint.java new file mode 100644 index 00000000..b3f236f7 --- /dev/null +++ b/policy-endpoints/src/main/java/org/openecomp/policy/drools/event/comm/TopicEndpoint.java @@ -0,0 +1,692 @@ +/*- + * ============LICENSE_START======================================================= + * policy-endpoints + * ================================================================================ + * 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.event.comm; + +import java.util.ArrayList; +import java.util.List; +import java.util.Properties; + +import org.openecomp.policy.drools.event.comm.bus.DmaapTopicSink; +import org.openecomp.policy.drools.event.comm.bus.DmaapTopicSource; +import org.openecomp.policy.drools.event.comm.bus.UebTopicSink; +import org.openecomp.policy.drools.event.comm.bus.UebTopicSource; +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.drools.properties.Lockable; +import org.openecomp.policy.drools.properties.Startable; +import com.fasterxml.jackson.annotation.JsonIgnore; + +/** + * Abstraction to managed the system's Networked Topic Endpoints, + * sources of all events input into the System. + */ +public interface TopicEndpoint extends Startable, Lockable { + + /** + * Add Topic Sources to the communication infrastructure initialized per + * properties + * + * @param properties properties for Topic Source construction + * @return a generic Topic Source + * @throws IllegalArgumentException when invalid arguments are provided + */ + public List<? extends TopicSource> addTopicSources(Properties properties) + throws IllegalArgumentException; + + /** + * Add Topic Sinks to the communication infrastructure initialized per + * properties + * + * @param properties properties for Topic Sink construction + * @return a generic Topic Sink + * @throws IllegalArgumentException when invalid arguments are provided + */ + public List<? extends TopicSink> addTopicSinks(Properties properties) + throws IllegalArgumentException; + + /** + * gets all Topic Sources + * @return the Topic Source List + */ + List<? extends TopicSource> getTopicSources(); + + /** + * get the Topic Sources for the given topic name + * + * @param topicName the topic name + * + * @return the Topic Source List + * @throws IllegalStateException if the entity is in an invalid state + * @throws IllegalArgumentException if invalid parameters are present + */ + public List<? extends TopicSource> getTopicSources(List<String> topicNames) + throws IllegalStateException, IllegalArgumentException; + + /** + * gets the Topic Source for the given topic name and + * underlying communication infrastructure type + * + * @param commType communication infrastructure type + * @param topicName the topic name + * + * @return the Topic Source + * @throws IllegalStateException if the entity is in an invalid state, for + * example multiple TopicReaders for a topic name and communication infrastructure + * @throws IllegalArgumentException if invalid parameters are present + * @throws UnsupportedOperationException if the operation is not supported. + */ + public TopicSource getTopicSource(Topic.CommInfrastructure commType, + String topicName) + throws IllegalStateException, IllegalArgumentException, + UnsupportedOperationException; + + /** + * get the UEB Topic Source for the given topic name + * + * @param topicName the topic name + * + * @return the UEB Topic Source + * @throws IllegalStateException if the entity is in an invalid state, for + * example multiple TopicReaders for a topic name and communication infrastructure + * @throws IllegalArgumentException if invalid parameters are present + */ + public UebTopicSource getUebTopicSource(String topicName) + throws IllegalStateException, IllegalArgumentException; + + /** + * get the DMAAP Topic Source for the given topic name + * + * @param topicName the topic name + * + * @return the DMAAP Topic Source + * @throws IllegalStateException if the entity is in an invalid state, for + * example multiple TopicReaders for a topic name and communication infrastructure + * @throws IllegalArgumentException if invalid parameters are present + */ + public DmaapTopicSource getDmaapTopicSource(String topicName) + throws IllegalStateException, IllegalArgumentException; + + /** + * get the Topic Sinks for the given topic name + * + * @param topicNames the topic names + * @return the Topic Sink List + * @throws IllegalStateException + * @throws IllegalArgumentException + */ + public List<? extends TopicSink> getTopicSinks(List<String> topicNames) + throws IllegalStateException, IllegalArgumentException; + + /** + * get the Topic Sinks for the given topic name and + * underlying communication infrastructure type + * + * @param topicName the topic name + * @param commType communication infrastructure type + * + * @return the Topic Sink List + * @throws IllegalStateException if the entity is in an invalid state, for + * example multiple TopicWriters for a topic name and communication infrastructure + * @throws IllegalArgumentException if invalid parameters are present + */ + public TopicSink getTopicSink(Topic.CommInfrastructure commType, + String topicName) + throws IllegalStateException, IllegalArgumentException, + UnsupportedOperationException; + + /** + * get the Topic Sinks for the given topic name and + * all the underlying communication infrastructure type + * + * @param topicName the topic name + * @param commType communication infrastructure type + * + * @return the Topic Sink List + * @throws IllegalStateException if the entity is in an invalid state, for + * example multiple TopicWriters for a topic name and communication infrastructure + * @throws IllegalArgumentException if invalid parameters are present + */ + public List<? extends TopicSink> getTopicSinks(String topicName) + throws IllegalStateException, IllegalArgumentException; + + /** + * get the UEB Topic Source for the given topic name + * + * @param topicName the topic name + * + * @return the Topic Source + * @throws IllegalStateException if the entity is in an invalid state, for + * example multiple TopicReaders for a topic name and communication infrastructure + * @throws IllegalArgumentException if invalid parameters are present + */ + public UebTopicSink getUebTopicSink(String topicName) + throws IllegalStateException, IllegalArgumentException; + + /** + * get the DMAAP Topic Source for the given topic name + * + * @param topicName the topic name + * + * @return the Topic Source + * @throws IllegalStateException if the entity is in an invalid state, for + * example multiple TopicReaders for a topic name and communication infrastructure + * @throws IllegalArgumentException if invalid parameters are present + */ + public DmaapTopicSink getDmaapTopicSink(String topicName) + throws IllegalStateException, IllegalArgumentException; + + /** + * gets only the UEB Topic Sources + * @return the UEB Topic Source List + */ + public List<UebTopicSource> getUebTopicSources(); + + /** + * gets only the DMAAP Topic Sources + * @return the DMAAP Topic Source List + */ + public List<DmaapTopicSource> getDmaapTopicSources(); + + /** + * gets all Topic Sinks + * @return the Topic Sink List + */ + public List<? extends TopicSink> getTopicSinks(); + + /** + * gets only the UEB Topic Sinks + * @return the UEB Topic Sink List + */ + public List<UebTopicSink> getUebTopicSinks(); + + /** + * gets only the DMAAP Topic Sinks + * @return the DMAAP Topic Sink List + */ + public List<DmaapTopicSink> getDmaapTopicSinks(); + + /** + * singleton for global access + */ + public static final TopicEndpoint manager = new ProxyTopicEndpointManager(); +} + +/* + * ----------------- implementation ------------------- + */ + +/** + * This implementation of the Topic Endpoint Manager, proxies operations to appropriate + * implementations according to the communication infrastructure that are supported + */ +class ProxyTopicEndpointManager implements TopicEndpoint { + // get an instance of logger + private static Logger logger = FlexLogger.getLogger(ProxyTopicEndpointManager.class); + /** + * Is this element locked? + */ + protected volatile boolean locked = false; + + /** + * Is this element alive? + */ + protected volatile boolean alive = false; + + /** + * {@inheritDoc} + */ + @Override + public List<? extends TopicSource> addTopicSources(Properties properties) throws IllegalArgumentException { + + // 1. Create UEB Sources + // 2. Create DMAAP Sources + + List<TopicSource> sources = new ArrayList<TopicSource>(); + + sources.addAll(UebTopicSource.factory.build(properties)); + sources.addAll(DmaapTopicSource.factory.build(properties)); + + if (this.isLocked()) { + for (TopicSource source : sources) { + source.lock(); + } + } + + return sources; + } + + /** + * {@inheritDoc} + */ + @Override + public List<? extends TopicSink> addTopicSinks(Properties properties) throws IllegalArgumentException { + // 1. Create UEB Sinks + // 2. Create DMAAP Sinks + + List<TopicSink> sinks = new ArrayList<TopicSink>(); + + sinks.addAll(UebTopicSink.factory.build(properties)); + sinks.addAll(DmaapTopicSink.factory.build(properties)); + + if (this.isLocked()) { + for (TopicSink sink : sinks) { + sink.lock(); + } + } + + return sinks; + } + + /** + * {@inheritDoc} + */ + @Override + public List<? extends TopicSource> getTopicSources() { + + List<TopicSource> sources = new ArrayList<TopicSource>(); + + sources.addAll(UebTopicSource.factory.inventory()); + sources.addAll(DmaapTopicSource.factory.inventory()); + + return sources; + } + + /** + * {@inheritDoc} + */ + @Override + public List<? extends TopicSink> getTopicSinks() { + + List<TopicSink> sinks = new ArrayList<TopicSink>(); + + sinks.addAll(UebTopicSink.factory.inventory()); + sinks.addAll(DmaapTopicSink.factory.inventory()); + + return sinks; + } + + /** + * {@inheritDoc} + */ + @JsonIgnore + @Override + public List<UebTopicSource> getUebTopicSources() { + return UebTopicSource.factory.inventory(); + } + + /** + * {@inheritDoc} + */ + @JsonIgnore + @Override + public List<DmaapTopicSource> getDmaapTopicSources() { + return DmaapTopicSource.factory.inventory(); + } + + /** + * {@inheritDoc} + */ + @JsonIgnore + @Override + public List<UebTopicSink> getUebTopicSinks() { + return UebTopicSink.factory.inventory(); + } + + /** + * {@inheritDoc} + */ + @JsonIgnore + @Override + public List<DmaapTopicSink> getDmaapTopicSinks() { + return DmaapTopicSink.factory.inventory(); + } + + /** + * {@inheritDoc} + */ + @Override + public boolean start() throws IllegalStateException { + + synchronized (this) { + if (this.locked) { + throw new IllegalStateException(this + " is locked"); + } + + if (this.alive) { + return true; + } + + this.alive = true; + } + + List<Startable> endpoints = getEndpoints(); + + boolean success = true; + for (Startable endpoint: endpoints) { + try { + success = endpoint.start() && success; + } catch (Exception e) { + success = false; + logger.error(MessageCodes.EXCEPTION_ERROR, e, endpoint.toString(), this.toString()); + } + } + + return success; + } + + + /** + * {@inheritDoc} + */ + @Override + public boolean stop() throws IllegalStateException { + + /* + * stop regardless if it is locked, in other + * words, stop operation has precedence over + * locks. + */ + synchronized (this) { + this.alive = false; + } + + List<Startable> endpoints = getEndpoints(); + + boolean success = true; + for (Startable endpoint: endpoints) { + try { + success = endpoint.stop() && success; + } catch (Exception e) { + success = false; + logger.error(MessageCodes.EXCEPTION_ERROR, e, endpoint.toString(), this.toString()); + } + } + + return success; + } + + /** + * + * @return list of managed endpoints + */ + @JsonIgnore + protected List<Startable> getEndpoints() { + List<Startable> endpoints = new ArrayList<Startable>(); + + endpoints.addAll(this.getTopicSources()); + endpoints.addAll(this.getTopicSinks()); + + return endpoints; + } + + + /** + * {@inheritDoc} + */ + @Override + public void shutdown() throws IllegalStateException { + UebTopicSource.factory.destroy(); + UebTopicSink.factory.destroy(); + + DmaapTopicSource.factory.destroy(); + DmaapTopicSink.factory.destroy(); + } + + /** + * {@inheritDoc} + */ + @Override + public boolean isAlive() { + return this.alive; + } + + /** + * {@inheritDoc} + */ + @Override + public boolean lock() { + + synchronized (this) { + if (locked) + return true; + + this.locked = true; + } + + for (TopicSource source: this.getTopicSources()) { + source.lock(); + } + + for (TopicSink sink: this.getTopicSinks()) { + sink.lock(); + } + + return true; + } + + /** + * {@inheritDoc} + */ + @Override + public boolean unlock() { + synchronized (this) { + if (!locked) + return true; + + this.locked = false; + } + + for (TopicSource source: this.getTopicSources()) { + source.unlock(); + } + + for (TopicSink sink: this.getTopicSinks()) { + sink.unlock(); + } + + return true; + } + + /** + * {@inheritDoc} + */ + @Override + public boolean isLocked() { + return this.locked; + } + + /** + * {@inheritDoc} + */ + @Override + public List<? extends TopicSource> getTopicSources(List<String> topicNames) + throws IllegalStateException, IllegalArgumentException { + + if (topicNames == null) { + throw new IllegalArgumentException("must provide a list of topics"); + } + + List<TopicSource> sources = new ArrayList<TopicSource>(); + for (String topic: topicNames) { + try { + TopicSource uebSource = this.getUebTopicSource(topic); + if (uebSource != null) + sources.add(uebSource); + } catch (Exception e) { + logger.info("No UEB source for topic: " + topic); + } + + try { + TopicSource dmaapSource = this.getDmaapTopicSource(topic); + if (dmaapSource != null) + sources.add(dmaapSource); + } catch (Exception e) { + logger.info("No DMAAP source for topic: " + topic); + } + } + return sources; + } + + /** + * {@inheritDoc} + */ + @Override + public List<? extends TopicSink> getTopicSinks(List<String> topicNames) + throws IllegalStateException, IllegalArgumentException { + + if (topicNames == null) { + throw new IllegalArgumentException("must provide a list of topics"); + } + + List<TopicSink> sinks = new ArrayList<TopicSink>(); + for (String topic: topicNames) { + try { + TopicSink uebSink = this.getUebTopicSink(topic); + if (uebSink != null) + sinks.add(uebSink); + } catch (Exception e) { + logger.info("No UEB sink for topic: " + topic); + } + + try { + TopicSink dmaapSink = this.getDmaapTopicSink(topic); + if (dmaapSink != null) + sinks.add(dmaapSink); + } catch (Exception e) { + logger.info("No DMAAP sink for topic: " + topic); + } + } + return sinks; + } + + /** + * {@inheritDoc} + */ + @Override + public TopicSource getTopicSource(Topic.CommInfrastructure commType, String topicName) + throws IllegalStateException, IllegalArgumentException, UnsupportedOperationException { + + if (commType == null) { + throw new IllegalArgumentException + ("Invalid parameter: a communication infrastructure required to fetch " + topicName); + } + + if (topicName == null) { + throw new IllegalArgumentException + ("Invalid parameter: a communication infrastructure required to fetch " + topicName); + } + + switch (commType) { + case UEB: + return this.getUebTopicSource(topicName); + case DMAAP: + return this.getDmaapTopicSource(topicName); + case REST: + default: + throw new UnsupportedOperationException("Unsupported " + commType.name()); + } + } + + /** + * {@inheritDoc} + */ + @Override + public TopicSink getTopicSink(Topic.CommInfrastructure commType, String topicName) + throws IllegalStateException, IllegalArgumentException, UnsupportedOperationException { + if (commType == null) { + throw new IllegalArgumentException + ("Invalid parameter: a communication infrastructure required to fetch " + topicName); + } + + if (topicName == null) { + throw new IllegalArgumentException + ("Invalid parameter: a communication infrastructure required to fetch " + topicName); + } + + switch (commType) { + case UEB: + return this.getUebTopicSink(topicName); + case DMAAP: + return this.getDmaapTopicSink(topicName); + case REST: + default: + throw new UnsupportedOperationException("Unsupported " + commType.name()); + } + } + + /** + * {@inheritDoc} + */ + @Override + public List<? extends TopicSink> getTopicSinks(String topicName) + throws IllegalStateException, IllegalArgumentException { + + if (topicName == null) { + throw new IllegalArgumentException + ("Invalid parameter: a communication infrastructure required to fetch " + topicName); + } + + List<TopicSink> sinks = new ArrayList<TopicSink>(); + + try { + sinks.add(this.getUebTopicSink(topicName)); + } catch (Exception e) { + ; + } + + try { + sinks.add(this.getDmaapTopicSink(topicName)); + } catch (Exception e) { + ; + } + + return sinks; + } + + /** + * {@inheritDoc} + */ + @Override + public UebTopicSource getUebTopicSource(String topicName) throws IllegalStateException, IllegalArgumentException { + return UebTopicSource.factory.get(topicName); + } + + /** + * {@inheritDoc} + */ + @Override + public UebTopicSink getUebTopicSink(String topicName) throws IllegalStateException, IllegalArgumentException { + return UebTopicSink.factory.get(topicName); + } + + @Override + public DmaapTopicSource getDmaapTopicSource(String topicName) + throws IllegalStateException, IllegalArgumentException { + return DmaapTopicSource.factory.get(topicName); + } + + @Override + public DmaapTopicSink getDmaapTopicSink(String topicName) throws IllegalStateException, IllegalArgumentException { + return DmaapTopicSink.factory.get(topicName); + } + +} diff --git a/policy-endpoints/src/main/java/org/openecomp/policy/drools/event/comm/TopicListener.java b/policy-endpoints/src/main/java/org/openecomp/policy/drools/event/comm/TopicListener.java new file mode 100644 index 00000000..7a2e9711 --- /dev/null +++ b/policy-endpoints/src/main/java/org/openecomp/policy/drools/event/comm/TopicListener.java @@ -0,0 +1,42 @@ +/*- + * ============LICENSE_START======================================================= + * policy-endpoints + * ================================================================================ + * 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.event.comm; + +/** + * Listener for event messages entering the Policy Engine + */ +public interface TopicListener { + + /** + * Notification of a new Event over a given Topic + * + * @param commType communication infrastructure type + * @param topic topic name + * @param event event message as a string + * + * @return boolean. True if the invoking event dispatcher should continue + * dispatching the event to subsequent listeners. False if it is requested + * to the invoking event dispatcher to stop dispatching the same event to + * other listeners of less priority. This mechanism is generally not used. + */ + public boolean onTopicEvent(Topic.CommInfrastructure commType, String topic, String event); + +} diff --git a/policy-endpoints/src/main/java/org/openecomp/policy/drools/event/comm/TopicRegisterable.java b/policy-endpoints/src/main/java/org/openecomp/policy/drools/event/comm/TopicRegisterable.java new file mode 100644 index 00000000..2ce8e9e7 --- /dev/null +++ b/policy-endpoints/src/main/java/org/openecomp/policy/drools/event/comm/TopicRegisterable.java @@ -0,0 +1,42 @@ +/*- + * ============LICENSE_START======================================================= + * policy-endpoints + * ================================================================================ + * 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.event.comm; + +/** + * Marks a Topic entity as registerable + */ +public interface TopicRegisterable { + + /** + * Register for notification of events with this Topic Entity + * + * @param topicListener the listener of events + */ + public void register(TopicListener topicListener); + + /** + * Unregisters for notification of events with this Topic Entity + * + * @param topicListener the listener of events + */ + public void unregister(TopicListener topicListener); + +} diff --git a/policy-endpoints/src/main/java/org/openecomp/policy/drools/event/comm/TopicSink.java b/policy-endpoints/src/main/java/org/openecomp/policy/drools/event/comm/TopicSink.java new file mode 100644 index 00000000..2250b1ea --- /dev/null +++ b/policy-endpoints/src/main/java/org/openecomp/policy/drools/event/comm/TopicSink.java @@ -0,0 +1,42 @@ +/*- + * ============LICENSE_START======================================================= + * policy-endpoints + * ================================================================================ + * 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.event.comm; + +import org.openecomp.policy.drools.properties.Lockable; +import org.openecomp.policy.drools.properties.Startable; + +/** + * Marks a given Topic Endpoint as able to send messages over a topic + */ +public interface TopicSink extends Topic, Startable, Lockable { + + /** + * Sends a string message over this Topic Endpoint + * + * @param message message to send + * @return true if the send operation succeeded, false otherwise + * @throws IllegalArgumentException an invalid message has been provided + * @throws IllegalStateException the entity is in an state that prevents + * it from sending messages, for example, locked or stopped. + */ + public boolean send(String message) throws IllegalArgumentException, IllegalStateException; + +} diff --git a/policy-endpoints/src/main/java/org/openecomp/policy/drools/event/comm/TopicSource.java b/policy-endpoints/src/main/java/org/openecomp/policy/drools/event/comm/TopicSource.java new file mode 100644 index 00000000..0dfbe1c4 --- /dev/null +++ b/policy-endpoints/src/main/java/org/openecomp/policy/drools/event/comm/TopicSource.java @@ -0,0 +1,40 @@ +/*- + * ============LICENSE_START======================================================= + * policy-endpoints + * ================================================================================ + * 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.event.comm; + +import org.openecomp.policy.drools.properties.Lockable; +import org.openecomp.policy.drools.properties.Startable; + +/** + * Marker for a Topic Entity, indicating that the entity is able to read + * over a topic + */ +public interface TopicSource extends TopicRegisterable, Topic, Startable, Lockable { + + /** + * pushes an event into the source programatically + * + * @param event the event in json format + * @return true if it can be processed correctly, false otherwise + */ + public boolean offer(String event); + +} diff --git a/policy-endpoints/src/main/java/org/openecomp/policy/drools/event/comm/bus/BusTopic.java b/policy-endpoints/src/main/java/org/openecomp/policy/drools/event/comm/bus/BusTopic.java new file mode 100644 index 00000000..c38f627e --- /dev/null +++ b/policy-endpoints/src/main/java/org/openecomp/policy/drools/event/comm/bus/BusTopic.java @@ -0,0 +1,26 @@ +/*- + * ============LICENSE_START======================================================= + * policy-endpoints + * ================================================================================ + * 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.event.comm.bus; + +public interface BusTopic { + public String getApiKey(); + public String getApiSecret(); +} diff --git a/policy-endpoints/src/main/java/org/openecomp/policy/drools/event/comm/bus/BusTopicSink.java b/policy-endpoints/src/main/java/org/openecomp/policy/drools/event/comm/bus/BusTopicSink.java new file mode 100644 index 00000000..30978c27 --- /dev/null +++ b/policy-endpoints/src/main/java/org/openecomp/policy/drools/event/comm/bus/BusTopicSink.java @@ -0,0 +1,47 @@ +/*- + * ============LICENSE_START======================================================= + * policy-endpoints + * ================================================================================ + * 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.event.comm.bus; + +import org.openecomp.policy.drools.event.comm.TopicSink; + +/** + * Topic Sink over Bus Infrastructure (DMAAP/UEB) + */ +public interface BusTopicSink extends BusTopic, TopicSink { + /** + * Log Failures after X number of retries + */ + public static final int DEFAULT_LOG_SEND_FAILURES_AFTER = 1; + + /** + * Sets the UEB partition key for published messages + * + * @param partitionKey the partition key + */ + public void setPartitionKey(String partitionKey); + + /** + * return the partition key in used by the system to publish messages + * + * @return the partition key + */ + public String getPartitionKey(); +} diff --git a/policy-endpoints/src/main/java/org/openecomp/policy/drools/event/comm/bus/BusTopicSource.java b/policy-endpoints/src/main/java/org/openecomp/policy/drools/event/comm/bus/BusTopicSource.java new file mode 100644 index 00000000..e6a46d2f --- /dev/null +++ b/policy-endpoints/src/main/java/org/openecomp/policy/drools/event/comm/bus/BusTopicSource.java @@ -0,0 +1,83 @@ +/*- + * ============LICENSE_START======================================================= + * policy-endpoints + * ================================================================================ + * 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.event.comm.bus; + +import org.openecomp.policy.drools.event.comm.TopicSource; + +/** + * Generic Topic Source for UEB/DMAAP Communication Infrastructure + * + */ +public interface BusTopicSource extends BusTopic, TopicSource { + + /** + * Default Consumer Instance Value + */ + public static String DEFAULT_CONSUMER_INSTANCE = "0"; + + /** + * Default Timeout fetching in milliseconds + */ + public static int DEFAULT_TIMEOUT_MS_FETCH = 15000; + + /** + * Default maximum number of messages fetch at the time + */ + public static int DEFAULT_LIMIT_FETCH = 100; + + /** + * Definition of No Timeout fetching + */ + public static int NO_TIMEOUT_MS_FETCH = -1; + + /** + * Definition of No limit fetching + */ + public static int NO_LIMIT_FETCH = -1; + + /** + * gets the consumer group + * + * @return consumer group + */ + public String getConsumerGroup(); + + /** + * gets the consumer instance + * + * @return consumer instance + */ + public String getConsumerInstance(); + + /** + * gets the fetch timeout + * + * @return fetch timeout + */ + public int getFetchTimeout(); + + /** + * gets the fetch limit + * + * @return fetch limit + */ + public int getFetchLimit(); +} diff --git a/policy-endpoints/src/main/java/org/openecomp/policy/drools/event/comm/bus/DmaapTopicSink.java b/policy-endpoints/src/main/java/org/openecomp/policy/drools/event/comm/bus/DmaapTopicSink.java new file mode 100644 index 00000000..3c55c9f3 --- /dev/null +++ b/policy-endpoints/src/main/java/org/openecomp/policy/drools/event/comm/bus/DmaapTopicSink.java @@ -0,0 +1,30 @@ +/*- + * ============LICENSE_START======================================================= + * policy-endpoints + * ================================================================================ + * 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.event.comm.bus; + +public interface DmaapTopicSink extends BusTopicSink { + + /** + * Factory of UebTopicWriter for instantiation and management purposes + */ + + public static final DmaapTopicSinkFactory factory = new IndexedDmaapTopicSinkFactory(); +} diff --git a/policy-endpoints/src/main/java/org/openecomp/policy/drools/event/comm/bus/DmaapTopicSinkFactory.java b/policy-endpoints/src/main/java/org/openecomp/policy/drools/event/comm/bus/DmaapTopicSinkFactory.java new file mode 100644 index 00000000..5b4cfd42 --- /dev/null +++ b/policy-endpoints/src/main/java/org/openecomp/policy/drools/event/comm/bus/DmaapTopicSinkFactory.java @@ -0,0 +1,308 @@ +/*- + * ============LICENSE_START======================================================= + * policy-endpoints + * ================================================================================ + * 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.event.comm.bus; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Properties; + +import org.openecomp.policy.drools.event.comm.bus.internal.InlineDmaapTopicSink; +import org.openecomp.policy.common.logging.flexlogger.FlexLogger; +import org.openecomp.policy.common.logging.flexlogger.Logger; +import org.openecomp.policy.drools.properties.PolicyProperties; + +/** + * DMAAP Topic Sink Factory + */ +public interface DmaapTopicSinkFactory { + + /** + * Instantiates a new DMAAP Topic Sink + * + * @param servers list of servers + * @param topic topic name + * @param apiKey API Key + * @param apiSecret API Secret + * @param userName AAF user name + * @param password AAF password + * @param partitionKey Consumer Group + * @param managed is this sink endpoint managed? + * + * @return an DMAAP Topic Sink + * @throws IllegalArgumentException if invalid parameters are present + */ + public DmaapTopicSink build(List<String> servers, + String topic, + String apiKey, + String apiSecret, + String userName, + String password, + String partitionKey, + boolean managed) + throws IllegalArgumentException; + + /** + * Creates an DMAAP Topic Sink based on properties files + * + * @param properties Properties containing initialization values + * + * @return an DMAAP Topic Sink + * @throws IllegalArgumentException if invalid parameters are present + */ + public List<DmaapTopicSink> build(Properties properties) + throws IllegalArgumentException; + + /** + * Instantiates a new DMAAP Topic Sink + * + * @param servers list of servers + * @param topic topic name + * + * @return an DMAAP Topic Sink + * @throws IllegalArgumentException if invalid parameters are present + */ + public DmaapTopicSink build(List<String> servers, String topic) + throws IllegalArgumentException; + + /** + * Destroys an DMAAP Topic Sink based on a topic + * + * @param topic topic name + * @throws IllegalArgumentException if invalid parameters are present + */ + public void destroy(String topic); + + /** + * gets an DMAAP Topic Sink based on topic name + * @param topic the topic name + * + * @return an DMAAP Topic Sink with topic name + * @throws IllegalArgumentException if an invalid topic is provided + * @throws IllegalStateException if the DMAAP Topic Reader is + * an incorrect state + */ + public DmaapTopicSink get(String topic) + throws IllegalArgumentException, IllegalStateException; + + /** + * Provides a snapshot of the DMAAP Topic Sinks + * @return a list of the DMAAP Topic Sinks + */ + public List<DmaapTopicSink> inventory(); + + /** + * Destroys all DMAAP Topic Sinks + */ + public void destroy(); +} + +/* ------------- implementation ----------------- */ + +/** + * Factory of DMAAP Reader Topics indexed by topic name + */ +class IndexedDmaapTopicSinkFactory implements DmaapTopicSinkFactory { + // get an instance of logger + private static Logger logger = FlexLogger.getLogger(IndexedDmaapTopicSinkFactory.class); + + /** + * DMAAP Topic Name Index + */ + protected HashMap<String, DmaapTopicSink> dmaapTopicWriters = + new HashMap<String, DmaapTopicSink>(); + + /** + * {@inheritDoc} + */ + @Override + public DmaapTopicSink build(List<String> servers, + String topic, + String apiKey, + String apiSecret, + String userName, + String password, + String partitionKey, + boolean managed) + throws IllegalArgumentException { + + if (topic == null || topic.isEmpty()) { + throw new IllegalArgumentException("A topic must be provided"); + } + + synchronized (this) { + if (dmaapTopicWriters.containsKey(topic)) { + return dmaapTopicWriters.get(topic); + } + + DmaapTopicSink dmaapTopicSink = + new InlineDmaapTopicSink(servers, topic, + apiKey, apiSecret, + userName, password, + partitionKey); + + if (managed) + dmaapTopicWriters.put(topic, dmaapTopicSink); + return dmaapTopicSink; + } + } + + + /** + * {@inheritDoc} + */ + @Override + public DmaapTopicSink build(List<String> servers, String topic) throws IllegalArgumentException { + return this.build(servers, topic, null, null, null, null, null, true); + } + + + /** + * {@inheritDoc} + */ + @Override + public List<DmaapTopicSink> build(Properties properties) throws IllegalArgumentException { + + String writeTopics = properties.getProperty(PolicyProperties.PROPERTY_DMAAP_SINK_TOPICS); + if (writeTopics == null || writeTopics.isEmpty()) { + logger.warn("No topic for DMAAP Sink " + properties); + return new ArrayList<DmaapTopicSink>(); + } + List<String> writeTopicList = new ArrayList<String>(Arrays.asList(writeTopics.split("\\s*,\\s*"))); + + synchronized(this) { + List<DmaapTopicSink> dmaapTopicWriters = new ArrayList<DmaapTopicSink>(); + for (String topic: writeTopicList) { + + String servers = properties.getProperty(PolicyProperties.PROPERTY_DMAAP_SINK_TOPICS + "." + + topic + + PolicyProperties.PROPERTY_TOPIC_SERVERS_SUFFIX); + if (servers == null || servers.isEmpty()) { + logger.error("No DMAAP servers provided in " + properties); + continue; + } + + List<String> serverList = new ArrayList<String>(Arrays.asList(servers.split("\\s*,\\s*"))); + + String apiKey = properties.getProperty(PolicyProperties.PROPERTY_DMAAP_SINK_TOPICS + + "." + topic + + PolicyProperties.PROPERTY_TOPIC_API_KEY_SUFFIX); + String apiSecret = properties.getProperty(PolicyProperties.PROPERTY_DMAAP_SINK_TOPICS + + "." + topic + + PolicyProperties.PROPERTY_TOPIC_API_SECRET_SUFFIX); + + String aafMechId = properties.getProperty(PolicyProperties.PROPERTY_DMAAP_SINK_TOPICS + + "." + topic + + PolicyProperties.PROPERTY_TOPIC_AAF_MECHID_SUFFIX); + String aafPassword = properties.getProperty(PolicyProperties.PROPERTY_DMAAP_SINK_TOPICS + + "." + topic + + PolicyProperties.PROPERTY_TOPIC_AAF_PASSWORD_SUFFIX); + + String partitionKey = properties.getProperty(PolicyProperties.PROPERTY_DMAAP_SINK_TOPICS + + "." + topic + + PolicyProperties.PROPERTY_TOPIC_SINK_PARTITION_KEY_SUFFIX); + + String managedString = properties.getProperty(PolicyProperties.PROPERTY_UEB_SINK_TOPICS + "." + topic + + PolicyProperties.PROPERTY_MANAGED_SUFFIX); + boolean managed = true; + if (managedString != null && !managedString.isEmpty()) { + managed = Boolean.parseBoolean(managedString); + } + + DmaapTopicSink dmaapTopicSink = this.build(serverList, topic, + apiKey, apiSecret, aafMechId, aafPassword, + partitionKey, managed); + dmaapTopicWriters.add(dmaapTopicSink); + } + return dmaapTopicWriters; + } + } + + /** + * {@inheritDoc} + */ + @Override + public void destroy(String topic) + throws IllegalArgumentException { + + if (topic == null || topic.isEmpty()) { + throw new IllegalArgumentException("A topic must be provided"); + } + + DmaapTopicSink dmaapTopicWriter; + synchronized(this) { + if (!dmaapTopicWriters.containsKey(topic)) { + return; + } + + dmaapTopicWriter = dmaapTopicWriters.remove(topic); + } + + dmaapTopicWriter.shutdown(); + } + + /** + * {@inheritDoc} + */ + @Override + public void destroy() { + List<DmaapTopicSink> writers = this.inventory(); + for (DmaapTopicSink writer: writers) { + writer.shutdown(); + } + + synchronized(this) { + this.dmaapTopicWriters.clear(); + } + } + + /** + * {@inheritDoc} + */ + @Override + public DmaapTopicSink get(String topic) + throws IllegalArgumentException, IllegalStateException { + + if (topic == null || topic.isEmpty()) { + throw new IllegalArgumentException("A topic must be provided"); + } + + synchronized(this) { + if (dmaapTopicWriters.containsKey(topic)) { + return dmaapTopicWriters.get(topic); + } else { + throw new IllegalStateException("DmaapTopicSink for " + topic + " not found"); + } + } + } + + /** + * {@inheritDoc} + */ + @Override + public synchronized List<DmaapTopicSink> inventory() { + List<DmaapTopicSink> writers = + new ArrayList<DmaapTopicSink>(this.dmaapTopicWriters.values()); + return writers; + } + +} diff --git a/policy-endpoints/src/main/java/org/openecomp/policy/drools/event/comm/bus/DmaapTopicSource.java b/policy-endpoints/src/main/java/org/openecomp/policy/drools/event/comm/bus/DmaapTopicSource.java new file mode 100644 index 00000000..8da7906a --- /dev/null +++ b/policy-endpoints/src/main/java/org/openecomp/policy/drools/event/comm/bus/DmaapTopicSource.java @@ -0,0 +1,29 @@ +/*- + * ============LICENSE_START======================================================= + * policy-endpoints + * ================================================================================ + * 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.event.comm.bus; + +public interface DmaapTopicSource extends BusTopicSource { + + /** + * factory for managing and tracking DMAAP sources + */ + public static DmaapTopicSourceFactory factory = new IndexedDmaapTopicSourceFactory(); +} diff --git a/policy-endpoints/src/main/java/org/openecomp/policy/drools/event/comm/bus/DmaapTopicSourceFactory.java b/policy-endpoints/src/main/java/org/openecomp/policy/drools/event/comm/bus/DmaapTopicSourceFactory.java new file mode 100644 index 00000000..f8d85eb7 --- /dev/null +++ b/policy-endpoints/src/main/java/org/openecomp/policy/drools/event/comm/bus/DmaapTopicSourceFactory.java @@ -0,0 +1,380 @@ +/*- + * ============LICENSE_START======================================================= + * policy-endpoints + * ================================================================================ + * 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.event.comm.bus; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Properties; + +import org.openecomp.policy.drools.event.comm.bus.internal.SingleThreadedDmaapTopicSource; +import org.openecomp.policy.common.logging.flexlogger.FlexLogger; +import org.openecomp.policy.common.logging.flexlogger.Logger; +import org.openecomp.policy.drools.properties.PolicyProperties; +/** + * DMAAP Topic Source Factory + */ +public interface DmaapTopicSourceFactory { + + /** + * Creates an DMAAP Topic Source based on properties files + * + * @param properties Properties containing initialization values + * + * @return an DMAAP Topic Source + * @throws IllegalArgumentException if invalid parameters are present + */ + public List<DmaapTopicSource> build(Properties properties) + throws IllegalArgumentException; + + /** + * Instantiates a new DMAAP Topic Source + * + * @param servers list of servers + * @param topic topic name + * @param apiKey API Key + * @param apiSecret API Secret + * @param userName user name + * @param password password + * @param consumerGroup Consumer Group + * @param consumerInstance Consumer Instance + * @param fetchTimeout Read Fetch Timeout + * @param fetchLimit Fetch Limit + * @param managed is this endpoind managed? + * + * @return an DMAAP Topic Source + * @throws IllegalArgumentException if invalid parameters are present + */ + public DmaapTopicSource build(List<String> servers, + String topic, + String apiKey, + String apiSecret, + String userName, + String password, + String consumerGroup, + String consumerInstance, + int fetchTimeout, + int fetchLimit, + boolean managed) + throws IllegalArgumentException; + + /** + * Instantiates a new DMAAP Topic Source + * + * @param servers list of servers + * @param topic topic name + * @param apiKey API Key + * @param apiSecret API Secret + * + * @return an DMAAP Topic Source + * @throws IllegalArgumentException if invalid parameters are present + */ + public DmaapTopicSource build(List<String> servers, + String topic, + String apiKey, + String apiSecret) + throws IllegalArgumentException; + + /** + * Instantiates a new DMAAP Topic Source + * + * @param uebTopicReaderType Implementation type + * @param servers list of servers + * @param topic topic name + * + * @return an DMAAP Topic Source + * @throws IllegalArgumentException if invalid parameters are present + */ + public DmaapTopicSource build(List<String> servers, + String topic) + throws IllegalArgumentException; + + /** + * Destroys an DMAAP Topic Source based on a topic + * + * @param topic topic name + * @throws IllegalArgumentException if invalid parameters are present + */ + public void destroy(String topic); + + /** + * Destroys all DMAAP Topic Sources + */ + public void destroy(); + + /** + * gets an DMAAP Topic Source based on topic name + * @param topic the topic name + * @return an DMAAP Topic Source with topic name + * @throws IllegalArgumentException if an invalid topic is provided + * @throws IllegalStateException if the DMAAP Topic Source is + * an incorrect state + */ + public DmaapTopicSource get(String topic) + throws IllegalArgumentException, IllegalStateException; + + /** + * Provides a snapshot of the DMAAP Topic Sources + * @return a list of the DMAAP Topic Sources + */ + public List<DmaapTopicSource> inventory(); +} + + +/* ------------- implementation ----------------- */ + +/** + * Factory of DMAAP Source Topics indexed by topic name + */ + +class IndexedDmaapTopicSourceFactory implements DmaapTopicSourceFactory { + // get an instance of logger + private static Logger logger = FlexLogger.getLogger(IndexedDmaapTopicSourceFactory.class); + /** + * UEB Topic Name Index + */ + protected HashMap<String, DmaapTopicSource> dmaapTopicSources = + new HashMap<String, DmaapTopicSource>(); + + /** + * {@inheritDoc} + */ + @Override + public DmaapTopicSource build(List<String> servers, + String topic, + String apiKey, + String apiSecret, + String userName, + String password, + String consumerGroup, + String consumerInstance, + int fetchTimeout, + int fetchLimit, + boolean managed) + throws IllegalArgumentException { + + if (topic == null || topic.isEmpty()) { + throw new IllegalArgumentException("A topic must be provided"); + } + + synchronized(this) { + if (dmaapTopicSources.containsKey(topic)) { + return dmaapTopicSources.get(topic); + } + + DmaapTopicSource dmaapTopicSource = + new SingleThreadedDmaapTopicSource(servers, topic, + apiKey, apiSecret, userName, password, + consumerGroup, consumerInstance, + fetchTimeout, fetchLimit); + + if (managed) + dmaapTopicSources.put(topic, dmaapTopicSource); + + return dmaapTopicSource; + } + } + + /** + * {@inheritDoc} + */ + @Override + public List<DmaapTopicSource> build(Properties properties) + throws IllegalArgumentException { + + String readTopics = properties.getProperty(PolicyProperties.PROPERTY_DMAAP_SOURCE_TOPICS); + if (readTopics == null || readTopics.isEmpty()) { + logger.warn("No topic for UEB Source " + properties); + return new ArrayList<DmaapTopicSource>(); + } + List<String> readTopicList = new ArrayList<String>(Arrays.asList(readTopics.split("\\s*,\\s*"))); + + List<DmaapTopicSource> dmaapTopicSource_s = new ArrayList<DmaapTopicSource>(); + synchronized(this) { + for (String topic: readTopicList) { + + String servers = properties.getProperty(PolicyProperties.PROPERTY_DMAAP_SOURCE_TOPICS + "." + + topic + + PolicyProperties.PROPERTY_TOPIC_SERVERS_SUFFIX); + + if (servers == null || servers.isEmpty()) { + logger.error("No UEB servers provided in " + properties); + continue; + } + + List<String> serverList = new ArrayList<String>(Arrays.asList(servers.split("\\s*,\\s*"))); + + String apiKey = properties.getProperty(PolicyProperties.PROPERTY_DMAAP_SOURCE_TOPICS + + "." + topic + + PolicyProperties.PROPERTY_TOPIC_API_KEY_SUFFIX); + + String apiSecret = properties.getProperty(PolicyProperties.PROPERTY_DMAAP_SOURCE_TOPICS + + "." + topic + + PolicyProperties.PROPERTY_TOPIC_API_SECRET_SUFFIX); + + String aafMechId = properties.getProperty(PolicyProperties.PROPERTY_DMAAP_SOURCE_TOPICS + + "." + topic + + PolicyProperties.PROPERTY_TOPIC_AAF_MECHID_SUFFIX); + + String aafPassword = properties.getProperty(PolicyProperties.PROPERTY_DMAAP_SOURCE_TOPICS + + "." + topic + + PolicyProperties.PROPERTY_TOPIC_AAF_PASSWORD_SUFFIX); + + String consumerGroup = properties.getProperty(PolicyProperties.PROPERTY_DMAAP_SOURCE_TOPICS + + "." + topic + + PolicyProperties.PROPERTY_TOPIC_SOURCE_CONSUMER_GROUP_SUFFIX); + + String consumerInstance = properties.getProperty(PolicyProperties.PROPERTY_DMAAP_SOURCE_TOPICS + + "." + topic + + PolicyProperties.PROPERTY_TOPIC_SOURCE_CONSUMER_INSTANCE_SUFFIX); + + String fetchTimeoutString = properties.getProperty(PolicyProperties.PROPERTY_DMAAP_SOURCE_TOPICS + + "." + topic + + PolicyProperties.PROPERTY_TOPIC_SOURCE_FETCH_TIMEOUT_SUFFIX); + int fetchTimeout = DmaapTopicSource.DEFAULT_TIMEOUT_MS_FETCH; + if (fetchTimeoutString != null && !fetchTimeoutString.isEmpty()) { + try { + fetchTimeout = Integer.parseInt(fetchTimeoutString); + } catch (NumberFormatException nfe) { + logger.warn("Fetch Timeout in invalid format for topic " + topic + ": " + fetchTimeoutString); + } + } + + String fetchLimitString = properties.getProperty(PolicyProperties.PROPERTY_DMAAP_SOURCE_TOPICS + + "." + topic + + PolicyProperties.PROPERTY_TOPIC_SOURCE_FETCH_TIMEOUT_SUFFIX); + int fetchLimit = DmaapTopicSource.DEFAULT_LIMIT_FETCH; + if (fetchLimitString != null && !fetchLimitString.isEmpty()) { + try { + fetchLimit = Integer.parseInt(fetchLimitString); + } catch (NumberFormatException nfe) { + logger.warn("Fetch Limit in invalid format for topic " + topic + ": " + fetchLimitString); + } + } + + String managedString = properties.getProperty(PolicyProperties.PROPERTY_DMAAP_SOURCE_TOPICS + + "." + topic + + PolicyProperties.PROPERTY_MANAGED_SUFFIX); + boolean managed = true; + if (managedString != null && !managedString.isEmpty()) { + managed = Boolean.parseBoolean(managedString); + } + + DmaapTopicSource uebTopicSource = this.build(serverList, topic, + apiKey, apiSecret, aafMechId, aafPassword, + consumerGroup, consumerInstance, + fetchTimeout, fetchLimit, managed); + dmaapTopicSource_s.add(uebTopicSource); + } + } + return dmaapTopicSource_s; + } + + /** + * {@inheritDoc} + */ + @Override + public DmaapTopicSource build(List<String> servers, + String topic, + String apiKey, + String apiSecret) { + return this.build(servers, topic, + apiKey, apiSecret, null, null, + null, null, + DmaapTopicSource.DEFAULT_TIMEOUT_MS_FETCH, + DmaapTopicSource.DEFAULT_LIMIT_FETCH, + true); + } + + /** + * {@inheritDoc} + */ + @Override + public DmaapTopicSource build(List<String> servers, String topic) { + return this.build(servers, topic, null, null); + } + + /** + * {@inheritDoc} + */ + @Override + public void destroy(String topic) + throws IllegalArgumentException { + + if (topic == null || topic.isEmpty()) { + throw new IllegalArgumentException("A topic must be provided"); + } + + DmaapTopicSource uebTopicSource; + + synchronized(this) { + if (!dmaapTopicSources.containsKey(topic)) { + return; + } + + uebTopicSource = dmaapTopicSources.remove(topic); + } + + uebTopicSource.shutdown(); + } + + /** + * {@inheritDoc} + */ + @Override + public DmaapTopicSource get(String topic) + throws IllegalArgumentException, IllegalStateException { + + if (topic == null || topic.isEmpty()) { + throw new IllegalArgumentException("A topic must be provided"); + } + + synchronized(this) { + if (dmaapTopicSources.containsKey(topic)) { + return dmaapTopicSources.get(topic); + } else { + throw new IllegalArgumentException("DmaapTopicSource for " + topic + " not found"); + } + } + } + + @Override + public synchronized List<DmaapTopicSource> inventory() { + List<DmaapTopicSource> readers = + new ArrayList<DmaapTopicSource>(this.dmaapTopicSources.values()); + return readers; + } + + @Override + public void destroy() { + List<DmaapTopicSource> readers = this.inventory(); + for (DmaapTopicSource reader: readers) { + reader.shutdown(); + } + + synchronized(this) { + this.dmaapTopicSources.clear(); + } + } + +} + diff --git a/policy-endpoints/src/main/java/org/openecomp/policy/drools/event/comm/bus/UebTopicSink.java b/policy-endpoints/src/main/java/org/openecomp/policy/drools/event/comm/bus/UebTopicSink.java new file mode 100644 index 00000000..efa4dc5e --- /dev/null +++ b/policy-endpoints/src/main/java/org/openecomp/policy/drools/event/comm/bus/UebTopicSink.java @@ -0,0 +1,32 @@ +/*- + * ============LICENSE_START======================================================= + * policy-endpoints + * ================================================================================ + * 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.event.comm.bus; + +/** + * Topic Writer over UEB Infrastructure + */ +public interface UebTopicSink extends BusTopicSink { + + /** + * Factory of UebTopicWriter for instantiation and management purposes + */ + public static final UebTopicSinkFactory factory = new IndexedUebTopicSinkFactory(); +} diff --git a/policy-endpoints/src/main/java/org/openecomp/policy/drools/event/comm/bus/UebTopicSinkFactory.java b/policy-endpoints/src/main/java/org/openecomp/policy/drools/event/comm/bus/UebTopicSinkFactory.java new file mode 100644 index 00000000..85b98838 --- /dev/null +++ b/policy-endpoints/src/main/java/org/openecomp/policy/drools/event/comm/bus/UebTopicSinkFactory.java @@ -0,0 +1,292 @@ +/*- + * ============LICENSE_START======================================================= + * policy-endpoints + * ================================================================================ + * 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.event.comm.bus; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Properties; + +import org.openecomp.policy.drools.event.comm.bus.internal.InlineUebTopicSink; +import org.openecomp.policy.common.logging.flexlogger.FlexLogger; +import org.openecomp.policy.common.logging.flexlogger.Logger; +import org.openecomp.policy.drools.properties.PolicyProperties; + +/** + * UEB Topic Sink Factory + */ +public interface UebTopicSinkFactory { + + /** + * Instantiates a new UEB Topic Writer + * + * @param servers list of servers + * @param topic topic name + * @param apiKey API Key + * @param apiSecret API Secret + * @param partitionKey Consumer Group + * @param managed is this sink endpoint managed? + * + * @return an UEB Topic Writer + * @throws IllegalArgumentException if invalid parameters are present + */ + public UebTopicSink build(List<String> servers, + String topic, + String apiKey, + String apiSecret, + String partitionKey, + boolean managed) + throws IllegalArgumentException; + + /** + * Creates an UEB Topic Writer based on properties files + * + * @param properties Properties containing initialization values + * + * @return an UEB Topic Writer + * @throws IllegalArgumentException if invalid parameters are present + */ + public List<UebTopicSink> build(Properties properties) + throws IllegalArgumentException; + + /** + * Instantiates a new UEB Topic Writer + * + * @param servers list of servers + * @param topic topic name + * + * @return an UEB Topic Writer + * @throws IllegalArgumentException if invalid parameters are present + */ + public UebTopicSink build(List<String> servers, String topic) + throws IllegalArgumentException; + + /** + * Destroys an UEB Topic Writer based on a topic + * + * @param topic topic name + * @throws IllegalArgumentException if invalid parameters are present + */ + public void destroy(String topic); + + /** + * gets an UEB Topic Writer based on topic name + * @param topic the topic name + * + * @return an UEB Topic Writer with topic name + * @throws IllegalArgumentException if an invalid topic is provided + * @throws IllegalStateException if the UEB Topic Reader is + * an incorrect state + */ + public UebTopicSink get(String topic) + throws IllegalArgumentException, IllegalStateException; + + /** + * Provides a snapshot of the UEB Topic Writers + * @return a list of the UEB Topic Writers + */ + public List<UebTopicSink> inventory(); + + /** + * Destroys all UEB Topic Writers + */ + public void destroy(); +} + +/* ------------- implementation ----------------- */ + +/** + * Factory of UEB Reader Topics indexed by topic name + */ +class IndexedUebTopicSinkFactory implements UebTopicSinkFactory { + // get an instance of logger + private static Logger logger = FlexLogger.getLogger(IndexedUebTopicSinkFactory.class); + /** + * UEB Topic Name Index + */ + protected HashMap<String, UebTopicSink> uebTopicSinks = + new HashMap<String, UebTopicSink>(); + + /** + * {@inheritDoc} + */ + @Override + public UebTopicSink build(List<String> servers, + String topic, + String apiKey, + String apiSecret, + String partitionKey, + boolean managed) + throws IllegalArgumentException { + + if (topic == null || topic.isEmpty()) { + throw new IllegalArgumentException("A topic must be provided"); + } + + synchronized (this) { + if (uebTopicSinks.containsKey(topic)) { + return uebTopicSinks.get(topic); + } + + UebTopicSink uebTopicWriter = + new InlineUebTopicSink(servers, topic, + apiKey, apiSecret,partitionKey); + + if (managed) + uebTopicSinks.put(topic, uebTopicWriter); + + return uebTopicWriter; + } + } + + + /** + * {@inheritDoc} + */ + @Override + public UebTopicSink build(List<String> servers, String topic) throws IllegalArgumentException { + return this.build(servers, topic, null, null, null, true); + } + + + /** + * {@inheritDoc} + */ + @Override + public List<UebTopicSink> build(Properties properties) throws IllegalArgumentException { + + String writeTopics = properties.getProperty(PolicyProperties.PROPERTY_UEB_SINK_TOPICS); + if (writeTopics == null || writeTopics.isEmpty()) { + logger.warn("No topic for UEB Sink " + properties); + return new ArrayList<UebTopicSink>(); + } + List<String> writeTopicList = new ArrayList<String>(Arrays.asList(writeTopics.split("\\s*,\\s*"))); + + synchronized(this) { + List<UebTopicSink> uebTopicWriters = new ArrayList<UebTopicSink>(); + for (String topic: writeTopicList) { + + String servers = properties.getProperty(PolicyProperties.PROPERTY_UEB_SINK_TOPICS + "." + + topic + + PolicyProperties.PROPERTY_TOPIC_SERVERS_SUFFIX); + if (servers == null || servers.isEmpty()) { + logger.error("No UEB servers provided in " + properties); + continue; + } + + List<String> serverList = new ArrayList<String>(Arrays.asList(servers.split("\\s*,\\s*"))); + + String apiKey = properties.getProperty(PolicyProperties.PROPERTY_UEB_SINK_TOPICS + + "." + topic + + PolicyProperties.PROPERTY_TOPIC_API_KEY_SUFFIX); + String apiSecret = properties.getProperty(PolicyProperties.PROPERTY_UEB_SINK_TOPICS + + "." + topic + + PolicyProperties.PROPERTY_TOPIC_API_SECRET_SUFFIX); + String partitionKey = properties.getProperty(PolicyProperties.PROPERTY_UEB_SINK_TOPICS + + "." + topic + + PolicyProperties.PROPERTY_TOPIC_SINK_PARTITION_KEY_SUFFIX); + + String managedString = properties.getProperty(PolicyProperties.PROPERTY_UEB_SINK_TOPICS + "." + topic + + PolicyProperties.PROPERTY_MANAGED_SUFFIX); + boolean managed = true; + if (managedString != null && !managedString.isEmpty()) { + managed = Boolean.parseBoolean(managedString); + } + + UebTopicSink uebTopicWriter = this.build(serverList, topic, + apiKey, apiSecret, + partitionKey, managed); + uebTopicWriters.add(uebTopicWriter); + } + return uebTopicWriters; + } + } + + /** + * {@inheritDoc} + */ + @Override + public void destroy(String topic) + throws IllegalArgumentException { + + if (topic == null || topic.isEmpty()) { + throw new IllegalArgumentException("A topic must be provided"); + } + + UebTopicSink uebTopicWriter; + synchronized(this) { + if (!uebTopicSinks.containsKey(topic)) { + return; + } + + uebTopicWriter = uebTopicSinks.remove(topic); + } + + uebTopicWriter.shutdown(); + } + + /** + * {@inheritDoc} + */ + @Override + public void destroy() { + List<UebTopicSink> writers = this.inventory(); + for (UebTopicSink writer: writers) { + writer.shutdown(); + } + + synchronized(this) { + this.uebTopicSinks.clear(); + } + } + + /** + * {@inheritDoc} + */ + @Override + public UebTopicSink get(String topic) + throws IllegalArgumentException, IllegalStateException { + + if (topic == null || topic.isEmpty()) { + throw new IllegalArgumentException("A topic must be provided"); + } + + synchronized(this) { + if (uebTopicSinks.containsKey(topic)) { + return uebTopicSinks.get(topic); + } else { + throw new IllegalStateException("UebTopicSink for " + topic + " not found"); + } + } + } + + /** + * {@inheritDoc} + */ + @Override + public synchronized List<UebTopicSink> inventory() { + List<UebTopicSink> writers = + new ArrayList<UebTopicSink>(this.uebTopicSinks.values()); + return writers; + } + +} diff --git a/policy-endpoints/src/main/java/org/openecomp/policy/drools/event/comm/bus/UebTopicSource.java b/policy-endpoints/src/main/java/org/openecomp/policy/drools/event/comm/bus/UebTopicSource.java new file mode 100644 index 00000000..4da01302 --- /dev/null +++ b/policy-endpoints/src/main/java/org/openecomp/policy/drools/event/comm/bus/UebTopicSource.java @@ -0,0 +1,34 @@ +/*- + * ============LICENSE_START======================================================= + * policy-endpoints + * ================================================================================ + * 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.event.comm.bus; + +/** + * Topic Source for UEB Communication Infrastructure + * + */ +public interface UebTopicSource extends BusTopicSource { + + /** + * factory for managing and tracking UEB readers + */ + public static UebTopicSourceFactory factory = + new IndexedUebTopicSourceFactory(); +} diff --git a/policy-endpoints/src/main/java/org/openecomp/policy/drools/event/comm/bus/UebTopicSourceFactory.java b/policy-endpoints/src/main/java/org/openecomp/policy/drools/event/comm/bus/UebTopicSourceFactory.java new file mode 100644 index 00000000..bf2a4038 --- /dev/null +++ b/policy-endpoints/src/main/java/org/openecomp/policy/drools/event/comm/bus/UebTopicSourceFactory.java @@ -0,0 +1,362 @@ +/*- + * ============LICENSE_START======================================================= + * policy-endpoints + * ================================================================================ + * 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.event.comm.bus; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Properties; + +import org.openecomp.policy.drools.event.comm.bus.internal.SingleThreadedUebTopicSource; +import org.openecomp.policy.common.logging.flexlogger.FlexLogger; +import org.openecomp.policy.common.logging.flexlogger.Logger; +import org.openecomp.policy.drools.properties.PolicyProperties; + +/** + * UEB Topic Source Factory + */ +public interface UebTopicSourceFactory { + + /** + * Creates an UEB Topic Source based on properties files + * + * @param properties Properties containing initialization values + * + * @return an UEB Topic Source + * @throws IllegalArgumentException if invalid parameters are present + */ + public List<UebTopicSource> build(Properties properties) + throws IllegalArgumentException; + + /** + * Instantiates a new UEB Topic Source + * + * @param servers list of servers + * @param topic topic name + * @param apiKey API Key + * @param apiSecret API Secret + * @param consumerGroup Consumer Group + * @param consumerInstance Consumer Instance + * @param fetchTimeout Read Fetch Timeout + * @param fetchLimit Fetch Limit + * @param managed is this source endpoint managed? + * + * @return an UEB Topic Source + * @throws IllegalArgumentException if invalid parameters are present + */ + public UebTopicSource build(List<String> servers, + String topic, + String apiKey, + String apiSecret, + String consumerGroup, + String consumerInstance, + int fetchTimeout, + int fetchLimit, + boolean managed) + throws IllegalArgumentException; + + /** + * Instantiates a new UEB Topic Source + * + * @param servers list of servers + * @param topic topic name + * @param apiKey API Key + * @param apiSecret API Secret + * + * @return an UEB Topic Source + * @throws IllegalArgumentException if invalid parameters are present + */ + public UebTopicSource build(List<String> servers, + String topic, + String apiKey, + String apiSecret) + throws IllegalArgumentException; + + /** + * Instantiates a new UEB Topic Source + * + * @param uebTopicSourceType Implementation type + * @param servers list of servers + * @param topic topic name + * + * @return an UEB Topic Source + * @throws IllegalArgumentException if invalid parameters are present + */ + public UebTopicSource build(List<String> servers, + String topic) + throws IllegalArgumentException; + + /** + * Destroys an UEB Topic Source based on a topic + * + * @param topic topic name + * @throws IllegalArgumentException if invalid parameters are present + */ + public void destroy(String topic); + + /** + * Destroys all UEB Topic Sources + */ + public void destroy(); + + /** + * gets an UEB Topic Source based on topic name + * @param topic the topic name + * @return an UEB Topic Source with topic name + * @throws IllegalArgumentException if an invalid topic is provided + * @throws IllegalStateException if the UEB Topic Source is + * an incorrect state + */ + public UebTopicSource get(String topic) + throws IllegalArgumentException, IllegalStateException; + + /** + * Provides a snapshot of the UEB Topic Sources + * @return a list of the UEB Topic Sources + */ + public List<UebTopicSource> inventory(); +} + +/* ------------- implementation ----------------- */ + +/** + * Factory of UEB Source Topics indexed by topic name + */ +class IndexedUebTopicSourceFactory implements UebTopicSourceFactory { + // get an instance of logger + private static Logger logger = FlexLogger.getLogger(IndexedUebTopicSourceFactory.class); + /** + * UEB Topic Name Index + */ + protected HashMap<String, UebTopicSource> uebTopicSources = + new HashMap<String, UebTopicSource>(); + + /** + * {@inheritDoc} + */ + @Override + public UebTopicSource build(List<String> servers, + String topic, + String apiKey, + String apiSecret, + String consumerGroup, + String consumerInstance, + int fetchTimeout, + int fetchLimit, + boolean managed) + throws IllegalArgumentException { + + if (topic == null || topic.isEmpty()) { + throw new IllegalArgumentException("A topic must be provided"); + } + + synchronized(this) { + if (uebTopicSources.containsKey(topic)) { + return uebTopicSources.get(topic); + } + + UebTopicSource uebTopicSource = + new SingleThreadedUebTopicSource(servers, topic, + apiKey, apiSecret, + consumerGroup, consumerInstance, + fetchTimeout, fetchLimit); + + if (managed) + uebTopicSources.put(topic, uebTopicSource); + + return uebTopicSource; + } + } + + /** + * {@inheritDoc} + */ + @Override + public List<UebTopicSource> build(Properties properties) + throws IllegalArgumentException { + + String readTopics = properties.getProperty(PolicyProperties.PROPERTY_UEB_SOURCE_TOPICS); + if (readTopics == null || readTopics.isEmpty()) { + logger.warn("No topic for UEB Source " + properties); + return new ArrayList<UebTopicSource>(); + } + List<String> readTopicList = new ArrayList<String>(Arrays.asList(readTopics.split("\\s*,\\s*"))); + + List<UebTopicSource> uebTopicSources = new ArrayList<UebTopicSource>(); + synchronized(this) { + for (String topic: readTopicList) { + + String servers = properties.getProperty(PolicyProperties.PROPERTY_UEB_SOURCE_TOPICS + "." + + topic + + PolicyProperties.PROPERTY_TOPIC_SERVERS_SUFFIX); + + if (servers == null || servers.isEmpty()) { + logger.error("No UEB servers provided in " + properties); + continue; + } + + List<String> serverList = new ArrayList<String>(Arrays.asList(servers.split("\\s*,\\s*"))); + + String apiKey = properties.getProperty(PolicyProperties.PROPERTY_UEB_SOURCE_TOPICS + + "." + topic + + PolicyProperties.PROPERTY_TOPIC_API_KEY_SUFFIX); + + String apiSecret = properties.getProperty(PolicyProperties.PROPERTY_UEB_SOURCE_TOPICS + + "." + topic + + PolicyProperties.PROPERTY_TOPIC_API_SECRET_SUFFIX); + + String consumerGroup = properties.getProperty(PolicyProperties.PROPERTY_UEB_SOURCE_TOPICS + + "." + topic + + PolicyProperties.PROPERTY_TOPIC_SOURCE_CONSUMER_GROUP_SUFFIX); + + String consumerInstance = properties.getProperty(PolicyProperties.PROPERTY_UEB_SOURCE_TOPICS + + "." + topic + + PolicyProperties.PROPERTY_TOPIC_SOURCE_CONSUMER_INSTANCE_SUFFIX); + + String fetchTimeoutString = properties.getProperty(PolicyProperties.PROPERTY_UEB_SOURCE_TOPICS + + "." + topic + + PolicyProperties.PROPERTY_TOPIC_SOURCE_FETCH_TIMEOUT_SUFFIX); + int fetchTimeout = UebTopicSource.DEFAULT_TIMEOUT_MS_FETCH; + if (fetchTimeoutString != null && !fetchTimeoutString.isEmpty()) { + try { + fetchTimeout = Integer.parseInt(fetchTimeoutString); + } catch (NumberFormatException nfe) { + logger.warn("Fetch Timeout in invalid format for topic " + topic + ": " + fetchTimeoutString); + } + } + + String fetchLimitString = properties.getProperty(PolicyProperties.PROPERTY_UEB_SOURCE_TOPICS + + "." + topic + + PolicyProperties.PROPERTY_TOPIC_SOURCE_FETCH_TIMEOUT_SUFFIX); + int fetchLimit = UebTopicSource.DEFAULT_LIMIT_FETCH; + if (fetchLimitString != null && !fetchLimitString.isEmpty()) { + try { + fetchLimit = Integer.parseInt(fetchLimitString); + } catch (NumberFormatException nfe) { + logger.warn("Fetch Limit in invalid format for topic " + topic + ": " + fetchLimitString); + } + } + + String managedString = properties.getProperty(PolicyProperties.PROPERTY_UEB_SOURCE_TOPICS + "." + + topic + PolicyProperties.PROPERTY_MANAGED_SUFFIX); + boolean managed = true; + if (managedString != null && !managedString.isEmpty()) { + managed = Boolean.parseBoolean(managedString); + } + + UebTopicSource uebTopicSource = this.build(serverList, topic, + apiKey, apiSecret, + consumerGroup, consumerInstance, + fetchTimeout, fetchLimit, managed); + uebTopicSources.add(uebTopicSource); + } + } + return uebTopicSources; + } + + /** + * {@inheritDoc} + */ + @Override + public UebTopicSource build(List<String> servers, + String topic, + String apiKey, + String apiSecret) { + return this.build(servers, topic, + apiKey, apiSecret, + null, null, + UebTopicSource.DEFAULT_TIMEOUT_MS_FETCH, + UebTopicSource.DEFAULT_LIMIT_FETCH, true); + } + + /** + * {@inheritDoc} + */ + @Override + public UebTopicSource build(List<String> servers, String topic) { + return this.build(servers, topic, null, null); + } + + /** + * {@inheritDoc} + */ + @Override + public void destroy(String topic) + throws IllegalArgumentException { + + if (topic == null || topic.isEmpty()) { + throw new IllegalArgumentException("A topic must be provided"); + } + + UebTopicSource uebTopicSource; + + synchronized(this) { + if (!uebTopicSources.containsKey(topic)) { + return; + } + + uebTopicSource = uebTopicSources.remove(topic); + } + + uebTopicSource.shutdown(); + } + + /** + * {@inheritDoc} + */ + @Override + public UebTopicSource get(String topic) + throws IllegalArgumentException, IllegalStateException { + + if (topic == null || topic.isEmpty()) { + throw new IllegalArgumentException("A topic must be provided"); + } + + synchronized(this) { + if (uebTopicSources.containsKey(topic)) { + return uebTopicSources.get(topic); + } else { + throw new IllegalStateException("UebTopiceSource for " + topic + " not found"); + } + } + } + + @Override + public synchronized List<UebTopicSource> inventory() { + List<UebTopicSource> readers = + new ArrayList<UebTopicSource>(this.uebTopicSources.values()); + return readers; + } + + @Override + public void destroy() { + List<UebTopicSource> readers = this.inventory(); + for (UebTopicSource reader: readers) { + reader.shutdown(); + } + + synchronized(this) { + this.uebTopicSources.clear(); + } + } + +} diff --git a/policy-endpoints/src/main/java/org/openecomp/policy/drools/event/comm/bus/internal/BusConsumer.java b/policy-endpoints/src/main/java/org/openecomp/policy/drools/event/comm/bus/internal/BusConsumer.java new file mode 100644 index 00000000..6fee5ce0 --- /dev/null +++ b/policy-endpoints/src/main/java/org/openecomp/policy/drools/event/comm/bus/internal/BusConsumer.java @@ -0,0 +1,204 @@ +/*- + * ============LICENSE_START======================================================= + * policy-endpoints + * ================================================================================ + * 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.event.comm.bus.internal; + +import java.net.MalformedURLException; +import java.security.GeneralSecurityException; +import java.util.List; +import java.util.Properties; + +import com.att.nsa.cambria.client.CambriaClientBuilders; +import com.att.nsa.cambria.client.CambriaConsumer; +import com.att.nsa.mr.client.impl.MRConsumerImpl; +import com.att.nsa.mr.test.clients.ProtocolTypeConstants; +import com.att.nsa.cambria.client.CambriaClientBuilders.ConsumerBuilder; + +/** + * Wrapper around libraries to consume from message bus + * + */ +public interface BusConsumer { + + /** + * fetch messages + * + * @return list of messages + * @throws Exception when error encountered by underlying libraries + */ + public Iterable<String> fetch() throws Exception; + + /** + * close underlying library consumer + */ + public void close(); + + /** + * Cambria based consumer + */ + public static class CambriaConsumerWrapper implements BusConsumer { + /** + * Cambria client + */ + protected CambriaConsumer consumer; + + /** + * Cambria Consumer Wrapper + * + * @param servers messaging bus hosts + * @param topic topic + * @param apiKey API Key + * @param apiSecret API Secret + * @param consumerGroup Consumer Group + * @param consumerInstance Consumer Instance + * @param fetchTimeout Fetch Timeout + * @param fetchLimit Fetch Limit + * @throws GeneralSecurityException + * @throws MalformedURLException + */ + public CambriaConsumerWrapper(List<String> servers, String topic, + String apiKey, String apiSecret, + String consumerGroup, String consumerInstance, + int fetchTimeout, int fetchLimit) + throws IllegalArgumentException { + + ConsumerBuilder builder = + new CambriaClientBuilders.ConsumerBuilder(); + + builder.knownAs(consumerGroup, consumerInstance) + .usingHosts(servers) + .onTopic(topic) + .waitAtServer(fetchTimeout) + .receivingAtMost(fetchLimit); + + if (apiKey != null && !apiKey.isEmpty() && + apiSecret != null && !apiSecret.isEmpty()) { + builder.authenticatedBy(apiKey, apiSecret); + } + + try { + this.consumer = builder.build(); + } catch (MalformedURLException | GeneralSecurityException e) { + throw new IllegalArgumentException(e); + } + } + + /** + * {@inheritDoc} + */ + public Iterable<String> fetch() throws Exception { + return this.consumer.fetch(); + } + + /** + * {@inheritDoc} + */ + public void close() { + this.consumer.close(); + } + + @Override + public String toString() { + return "CambriaConsumerWrapper []"; + } + } + + /** + * MR based consumer + */ + public static class DmaapConsumerWrapper implements BusConsumer { + + /** + * MR Consumer + */ + protected MRConsumerImpl consumer; + + /** + * MR Consumer Wrapper + * + * @param servers messaging bus hosts + * @param topic topic + * @param apiKey API Key + * @param apiSecret API Secret + * @param aafLogin AAF Login + * @param aafPassword AAF Password + * @param consumerGroup Consumer Group + * @param consumerInstance Consumer Instance + * @param fetchTimeout Fetch Timeout + * @param fetchLimit Fetch Limit + */ + public DmaapConsumerWrapper(List<String> servers, String topic, + String apiKey, String apiSecret, + String aafLogin, String aafPassword, + String consumerGroup, String consumerInstance, + int fetchTimeout, int fetchLimit) + throws Exception { + + this.consumer = new MRConsumerImpl(servers, topic, + consumerGroup, consumerInstance, + fetchTimeout, fetchLimit, + null, apiKey, apiSecret); + + this.consumer.setUsername(aafLogin); + this.consumer.setPassword(aafPassword); + + this.consumer.setProtocolFlag(ProtocolTypeConstants.AAF_AUTH.getValue()); + + Properties props = new Properties(); + props.setProperty("Protocol", "http"); + this.consumer.setProps(props); + this.consumer.setHost(servers.get(0) + ":3904");; + } + + /** + * {@inheritDoc} + */ + public Iterable<String> fetch() throws Exception { + return this.consumer.fetch(); + } + + /** + * {@inheritDoc} + */ + public void close() { + this.consumer.close(); + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder. + append("DmaapConsumerWrapper ["). + append("consumer.getAuthDate()=").append(consumer.getAuthDate()). + append(", consumer.getAuthKey()=").append(consumer.getAuthKey()). + append(", consumer.getHost()=").append(consumer.getHost()). + append(", consumer.getProtocolFlag()=").append(consumer.getProtocolFlag()). + append(", consumer.getUsername()=").append(consumer.getUsername()). + append("]"); + return builder.toString(); + } + } + + +} + + + + diff --git a/policy-endpoints/src/main/java/org/openecomp/policy/drools/event/comm/bus/internal/BusPublisher.java b/policy-endpoints/src/main/java/org/openecomp/policy/drools/event/comm/bus/internal/BusPublisher.java new file mode 100644 index 00000000..798bf989 --- /dev/null +++ b/policy-endpoints/src/main/java/org/openecomp/policy/drools/event/comm/bus/internal/BusPublisher.java @@ -0,0 +1,231 @@ +/*- + * ============LICENSE_START======================================================= + * policy-endpoints + * ================================================================================ + * 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.event.comm.bus.internal; + +import java.net.MalformedURLException; +import java.security.GeneralSecurityException; +import java.util.ArrayList; +import java.util.List; +import java.util.Properties; +import java.util.concurrent.TimeUnit; + +import org.openecomp.policy.common.logging.eelf.PolicyLogger; +import com.att.nsa.cambria.client.CambriaBatchingPublisher; +import com.att.nsa.cambria.client.CambriaClientBuilders; +import com.att.nsa.cambria.client.CambriaClientBuilders.PublisherBuilder; +import com.att.nsa.mr.client.impl.MRSimplerBatchPublisher; +import com.att.nsa.mr.test.clients.ProtocolTypeConstants; +import com.fasterxml.jackson.annotation.JsonIgnore; + +public interface BusPublisher { + + /** + * sends a message + * + * @param partition id + * @param message the message + * @return true if success, false otherwise + * @throws IllegalArgumentException if no message provided + */ + public boolean send(String partitionId, String message) throws IllegalArgumentException; + + /** + * closes the publisher + */ + public void close(); + + /** + * Cambria based library publisher + */ + public static class CambriaPublisherWrapper implements BusPublisher { + + /** + * The actual Cambria publisher + */ + @JsonIgnore + protected volatile CambriaBatchingPublisher publisher; + + public CambriaPublisherWrapper(List<String> servers, String topic, + String apiKey, + String apiSecret) + throws IllegalArgumentException { + PublisherBuilder builder = new CambriaClientBuilders.PublisherBuilder(); + + builder.usingHosts(servers) + .onTopic(topic); + + // Only supported in 0.2.4 version + // .logSendFailuresAfter(DEFAULT_LOG_SEND_FAILURES_AFTER); + + if (apiKey != null && !apiKey.isEmpty() && + apiSecret != null && !apiSecret.isEmpty()) { + builder.authenticatedBy(apiKey, apiSecret); + } + + try { + this.publisher = builder.build(); + } catch (MalformedURLException | GeneralSecurityException e) { + throw new IllegalArgumentException(e); + } + } + + /** + * {@inheritDoc} + */ + @Override + public boolean send(String partitionId, String message) + throws IllegalArgumentException { + if (message == null) + throw new IllegalArgumentException("No message provided"); + + try { + this.publisher.send(partitionId, message); + } catch (Exception e) { + PolicyLogger.warn(CambriaPublisherWrapper.class.getName(), + "SEND of " + message + " IN " + + this + " cannot be performed because of " + + e.getMessage()); + return false; + } + return true; + } + + /** + * {@inheritDoc} + */ + @Override + public void close() { + if (PolicyLogger.isInfoEnabled()) + PolicyLogger.info(CambriaPublisherWrapper.class.getName(), + "CREATION: " + this); + + try { + this.publisher.close(); + } catch (Exception e) { + PolicyLogger.warn(CambriaPublisherWrapper.class.getName(), + "CLOSE on " + this + " FAILED because of " + + e.getMessage()); + } + } + + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("CambriaPublisherWrapper ["). + append("publisher.getPendingMessageCount()="). + append(publisher.getPendingMessageCount()). + append("]"); + return builder.toString(); + } + + } + + /** + * DmaapClient library wrapper + */ + public static class DmaapPublisherWrapper implements BusPublisher { + /** + * MR based Publisher + */ + protected MRSimplerBatchPublisher publisher; + + public DmaapPublisherWrapper(List<String> servers, String topic, + String aafLogin, + String aafPassword) { + + ArrayList<String> dmaapServers = new ArrayList<String>(); + for (String server: servers) { + dmaapServers.add(server + ":3904"); + } + + this.publisher = + new MRSimplerBatchPublisher.Builder(). + againstUrls(dmaapServers). + onTopic(topic). + build(); + + this.publisher.setProtocolFlag(ProtocolTypeConstants.AAF_AUTH.getValue()); + + this.publisher.setUsername(aafLogin); + this.publisher.setPassword(aafPassword); + + Properties props = new Properties(); + props.setProperty("Protocol", "http"); + props.setProperty("contenttype", "application/json"); + + this.publisher.setProps(props); + + this.publisher.setHost(servers.get(0)); + + if (PolicyLogger.isInfoEnabled()) + PolicyLogger.info(DmaapPublisherWrapper.class.getName(), + "CREATION: " + this); + } + + /** + * {@inheritDoc} + */ + @Override + public void close() { + if (PolicyLogger.isInfoEnabled()) + PolicyLogger.info(DmaapPublisherWrapper.class.getName(), + "CREATION: " + this); + + try { + this.publisher.close(1, TimeUnit.SECONDS); + } catch (Exception e) { + PolicyLogger.warn(DmaapPublisherWrapper.class.getName(), + "CLOSE: " + this + " because of " + + e.getMessage()); + } + } + + /** + * {@inheritDoc} + */ + @Override + public boolean send(String partitionId, String message) + throws IllegalArgumentException { + if (message == null) + throw new IllegalArgumentException("No message provided"); + + this.publisher.send(partitionId, message); + return true; + + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("DmaapPublisherWrapper ["). + append("publisher.getAuthDate()=").append(publisher.getAuthDate()). + append(", publisher.getAuthKey()=").append(publisher.getAuthKey()). + append(", publisher.getHost()=").append(publisher.getHost()). + append(", publisher.getProtocolFlag()=").append(publisher.getProtocolFlag()). + append(", publisher.getUsername()=").append(publisher.getUsername()). + append(", publisher.getPendingMessageCount()=").append(publisher.getPendingMessageCount()). + append("]"); + return builder.toString(); + } + } + +} diff --git a/policy-endpoints/src/main/java/org/openecomp/policy/drools/event/comm/bus/internal/BusTopicBase.java b/policy-endpoints/src/main/java/org/openecomp/policy/drools/event/comm/bus/internal/BusTopicBase.java new file mode 100644 index 00000000..e36e3afc --- /dev/null +++ b/policy-endpoints/src/main/java/org/openecomp/policy/drools/event/comm/bus/internal/BusTopicBase.java @@ -0,0 +1,112 @@ +/*- + * ============LICENSE_START======================================================= + * policy-endpoints + * ================================================================================ + * 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.event.comm.bus.internal; + +import java.util.List; + +import org.apache.commons.collections4.queue.CircularFifoQueue; + +import org.openecomp.policy.drools.event.comm.Topic; +import org.openecomp.policy.drools.event.comm.bus.BusTopic; + +public abstract class BusTopicBase implements BusTopic, Topic { + + protected List<String> servers; + + protected String topic; + + protected String apiKey; + protected String apiSecret; + + protected CircularFifoQueue<String> recentEvents = new CircularFifoQueue<String>(10); + + public BusTopicBase(List<String> servers, + String topic, + String apiKey, + String apiSecret) + throws IllegalArgumentException { + + if (servers == null || servers.isEmpty()) { + throw new IllegalArgumentException("UEB Server(s) must be provided"); + } + + if (topic == null || topic.isEmpty()) { + throw new IllegalArgumentException("An UEB Topic must be provided"); + } + + this.servers = servers; + this.topic = topic; + + this.apiKey = apiKey; + this.apiSecret = apiSecret; + } + + /** + * {@inheritDoc} + */ + @Override + public String getTopic() { + return topic; + } + + /** + * {@inheritDoc} + */ + @Override + public List<String> getServers() { + return servers; + } + + /** + * {@inheritDoc} + */ + @Override + public String getApiKey() { + return apiKey; + } + + /** + * {@inheritDoc} + */ + @Override + public String getApiSecret() { + return apiSecret; + } + + /** + * @return the recentEvents + */ + @Override + public synchronized String[] getRecentEvents() { + String[] events = new String[recentEvents.size()]; + return recentEvents.toArray(events); + } + + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("UebTopicBase [servers=").append(servers).append(", topic=").append(topic).append(", apiKey=") + .append(apiKey).append(", apiSecret=").append(apiSecret).append("]"); + return builder.toString(); + } + +} diff --git a/policy-endpoints/src/main/java/org/openecomp/policy/drools/event/comm/bus/internal/InlineBusTopicSink.java b/policy-endpoints/src/main/java/org/openecomp/policy/drools/event/comm/bus/internal/InlineBusTopicSink.java new file mode 100644 index 00000000..bd88818b --- /dev/null +++ b/policy-endpoints/src/main/java/org/openecomp/policy/drools/event/comm/bus/internal/InlineBusTopicSink.java @@ -0,0 +1,284 @@ +/*- + * ============LICENSE_START======================================================= + * policy-endpoints + * ================================================================================ + * 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.event.comm.bus.internal; + +import java.util.List; +import java.util.UUID; + +import org.apache.log4j.Logger; + +import org.openecomp.policy.drools.event.comm.bus.BusTopicSink; +import org.openecomp.policy.common.logging.flexlogger.FlexLogger; +import org.openecomp.policy.common.logging.eelf.MessageCodes; + +/** + * Transport Agnostic Bus Topic Sink to carry out the core functionality + * to interact with a sink regardless if it is UEB or DMaaP. + * + */ +public abstract class InlineBusTopicSink extends BusTopicBase implements BusTopicSink { + + /** + * logger + */ + private static org.openecomp.policy.common.logging.flexlogger.Logger logger = + FlexLogger.getLogger(InlineBusTopicSink.class); + + /** + * Not to be converted to PolicyLogger. + * This will contain all in/out traffic and only that in a single file in a concise format. + */ + protected static final Logger networkLogger = Logger.getLogger(NETWORK_LOGGER); + + /** + * The partition key to publish to + */ + protected String partitionId; + + /** + * Am I running? + * reflects invocation of start()/stop() + * !locked & start() => alive + * stop() => !alive + */ + protected volatile boolean alive = false; + + /** + * Am I locked? + * reflects invocation of lock()/unlock() operations + * locked => !alive (but not in the other direction necessarily) + * locked => !offer, !run, !start, !stop (but this last one is obvious + * since locked => !alive) + */ + protected volatile boolean locked = false; + + /** + * message bus publisher + */ + protected BusPublisher publisher; + + /** + * constructor for abstract sink + * + * @param servers servers + * @param topic topic + * @param apiKey api secret + * @param apiSecret api secret + * @param partitionId partition id + * @throws IllegalArgumentException in invalid parameters are passed in + */ + public InlineBusTopicSink(List<String> servers, String topic, + String apiKey, String apiSecret, String partitionId) + throws IllegalArgumentException { + + super(servers, topic, apiKey, apiSecret); + + if (partitionId == null || partitionId.isEmpty()) { + this.partitionId = UUID.randomUUID ().toString(); + } + } + + /** + * Initialize the Bus publisher + */ + public abstract void init(); + + /** + * {@inheritDoc} + */ + @Override + public boolean start() throws IllegalStateException { + + if (logger.isInfoEnabled()) + logger.info("START: " + this); + + synchronized(this) { + + if (this.alive) + return true; + + if (locked) + throw new IllegalStateException(this + " is locked."); + + this.alive = true; + } + + this.init(); + return true; + } + + /** + * {@inheritDoc} + */ + @Override + public boolean stop() { + + BusPublisher publisherCopy; + synchronized(this) { + this.alive = false; + publisherCopy = this.publisher; + this.publisher = null; + } + + if (publisherCopy != null) { + try { + publisherCopy.close(); + } catch (Exception e) { + logger.warn(MessageCodes.EXCEPTION_ERROR, e, "PUBLISHER.CLOSE", this.toString()); + e.printStackTrace(); + } + } else { + logger.warn("No publisher to close: " + this); + return false; + } + + return true; + } + + /** + * {@inheritDoc} + */ + @Override + public boolean lock() { + + if (logger.isInfoEnabled()) + logger.info("LOCK: " + this); + + synchronized (this) { + if (this.locked) + return true; + + this.locked = true; + } + + return this.stop(); + } + + /** + * {@inheritDoc} + */ + @Override + public boolean unlock() { + + if (logger.isInfoEnabled()) + logger.info("UNLOCK: " + this); + + synchronized(this) { + if (!this.locked) + return true; + + this.locked = false; + } + + try { + return this.start(); + } catch (Exception e) { + logger.warn("can't start after unlocking " + this + + " because of " + e.getMessage()); + e.printStackTrace(); + return false; + } + } + + /** + * {@inheritDoc} + */ + @Override + public boolean isLocked() { + return this.locked; + } + + /** + * {@inheritDoc} + */ + @Override + public boolean isAlive() { + return this.alive; + } + + /** + * {@inheritDoc} + */ + @Override + public boolean send(String message) throws IllegalArgumentException, IllegalStateException { + + if (message == null || message.isEmpty()) { + throw new IllegalArgumentException("Message to send is empty"); + } + + if (!this.alive) { + throw new IllegalStateException(this + " is stopped"); + } + + try { + synchronized (this) { + this.recentEvents.add(message); + } + + if (networkLogger.isInfoEnabled()) { + networkLogger.info("[OUT|" + this.getTopicCommInfrastructure() + "|" + + this.topic + "]:" + + message); + } + + publisher.send(this.partitionId, message); + } catch (Exception e) { + logger.error("can't start after unlocking " + this + + " because of " + e.getMessage()); + e.printStackTrace(); + return false; + } + + return true; + } + + + /** + * {@inheritDoc} + */ + @Override + public void setPartitionKey(String partitionKey) { + this.partitionId = partitionKey; + } + + /** + * {@inheritDoc} + */ + @Override + public String getPartitionKey() { + return this.partitionId; + } + + /** + * {@inheritDoc} + */ + @Override + public void shutdown() throws IllegalStateException { + this.stop(); + } + + /** + * {@inheritDoc} + */ + @Override + public abstract CommInfrastructure getTopicCommInfrastructure(); + +} diff --git a/policy-endpoints/src/main/java/org/openecomp/policy/drools/event/comm/bus/internal/InlineDmaapTopicSink.java b/policy-endpoints/src/main/java/org/openecomp/policy/drools/event/comm/bus/internal/InlineDmaapTopicSink.java new file mode 100644 index 00000000..417c6d47 --- /dev/null +++ b/policy-endpoints/src/main/java/org/openecomp/policy/drools/event/comm/bus/internal/InlineDmaapTopicSink.java @@ -0,0 +1,84 @@ +/*- + * ============LICENSE_START======================================================= + * policy-endpoints + * ================================================================================ + * 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.event.comm.bus.internal; + +import java.util.List; + +import org.openecomp.policy.drools.event.comm.Topic; +import org.openecomp.policy.drools.event.comm.bus.DmaapTopicSink; +import org.openecomp.policy.common.logging.flexlogger.FlexLogger; +import org.openecomp.policy.common.logging.flexlogger.Logger; + +/** + * This implementation publishes events for the associated DMAAP topic, + * inline with the calling thread. + */ +public class InlineDmaapTopicSink extends InlineBusTopicSink implements DmaapTopicSink { + + protected static Logger logger = + FlexLogger.getLogger(InlineDmaapTopicSink.class); + + protected final String userName; + protected final String password; + + public InlineDmaapTopicSink(List<String> servers, String topic, + String apiKey, String apiSecret, + String userName, String password, + String partitionKey) + throws IllegalArgumentException { + + super(servers, topic, apiKey, apiSecret, partitionKey); + + this.userName = userName; + this.password = password; + } + + + @Override + public void init() { + this.publisher = + new BusPublisher.DmaapPublisherWrapper(this.servers, + this.topic, + this.userName, + this.password); + if (logger.isInfoEnabled()) + logger.info("DMAAP SINK TOPIC created " + this); + } + + /** + * {@inheritDoc} + */ + @Override + public CommInfrastructure getTopicCommInfrastructure() { + return Topic.CommInfrastructure.DMAAP; + } + + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("InlineDmaapTopicSink [userName=").append(userName).append(", password=").append(password) + .append(", getTopicCommInfrastructure()=").append(getTopicCommInfrastructure()).append(", toString()=") + .append(super.toString()).append("]"); + return builder.toString(); + } + +} diff --git a/policy-endpoints/src/main/java/org/openecomp/policy/drools/event/comm/bus/internal/InlineUebTopicSink.java b/policy-endpoints/src/main/java/org/openecomp/policy/drools/event/comm/bus/internal/InlineUebTopicSink.java new file mode 100644 index 00000000..2d4b1552 --- /dev/null +++ b/policy-endpoints/src/main/java/org/openecomp/policy/drools/event/comm/bus/internal/InlineUebTopicSink.java @@ -0,0 +1,91 @@ +/*- + * ============LICENSE_START======================================================= + * policy-endpoints + * ================================================================================ + * 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.event.comm.bus.internal; + +import java.util.List; + +import org.openecomp.policy.drools.event.comm.Topic; +import org.openecomp.policy.drools.event.comm.bus.UebTopicSink; +import org.openecomp.policy.common.logging.flexlogger.FlexLogger; + +/** + * This implementation publishes events for the associated UEB topic, + * inline with the calling thread. + */ +public class InlineUebTopicSink extends InlineBusTopicSink implements UebTopicSink { + + /** + * logger + */ + private static org.openecomp.policy.common.logging.flexlogger.Logger logger = + FlexLogger.getLogger(InlineUebTopicSink.class); + + /** + * Argument-based UEB Topic Writer instantiation + * + * @param servers list of UEB servers available for publishing + * @param topic the topic to publish to + * @param apiKey the api key (optional) + * @param apiSecret the api secret (optional) + * @param partitionId the partition key (optional, autogenerated if not provided) + * + * @throws IllegalArgumentException if invalid arguments are detected + */ + public InlineUebTopicSink(List<String> servers, + String topic, + String apiKey, + String apiSecret, + String partitionId) + throws IllegalArgumentException { + super(servers, topic, apiKey, apiSecret, partitionId); + } + + /** + * Instantiation of internal resources + */ + @Override + public void init() { + + this.publisher = + new BusPublisher.CambriaPublisherWrapper(this.servers, + this.topic, + this.apiKey, + this.apiSecret); + if (logger.isInfoEnabled()) + logger.info("UEB SINK TOPIC created " + this); + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("InlineUebTopicSink [getTopicCommInfrastructure()=").append(getTopicCommInfrastructure()) + .append(", toString()=").append(super.toString()).append("]"); + return builder.toString(); + } + + /** + * {@inheritDoc} + */ + @Override + public CommInfrastructure getTopicCommInfrastructure() { + return Topic.CommInfrastructure.UEB; + } +} diff --git a/policy-endpoints/src/main/java/org/openecomp/policy/drools/event/comm/bus/internal/SingleThreadedBusTopicSource.java b/policy-endpoints/src/main/java/org/openecomp/policy/drools/event/comm/bus/internal/SingleThreadedBusTopicSource.java new file mode 100644 index 00000000..f37c349e --- /dev/null +++ b/policy-endpoints/src/main/java/org/openecomp/policy/drools/event/comm/bus/internal/SingleThreadedBusTopicSource.java @@ -0,0 +1,477 @@ +/*- + * ============LICENSE_START======================================================= + * policy-endpoints + * ================================================================================ + * 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.event.comm.bus.internal; + +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; + +import org.apache.log4j.Logger; + +import org.openecomp.policy.drools.event.comm.TopicListener; +import org.openecomp.policy.drools.event.comm.bus.BusTopicSource; +import org.openecomp.policy.common.logging.eelf.MessageCodes; +import org.openecomp.policy.common.logging.eelf.PolicyLogger; + +/** + * This topic source implementation specializes in reading messages + * over a bus topic source and notifying its listeners + */ +public abstract class SingleThreadedBusTopicSource + extends BusTopicBase + implements Runnable, BusTopicSource { + + private String className = SingleThreadedBusTopicSource.class.getName(); + /** + * Not to be converted to PolicyLogger. + * This will contain all instract /out traffic and only that in a single file in a concise format. + */ + protected static final Logger networkLogger = Logger.getLogger(NETWORK_LOGGER); + + /** + * Bus consumer group + */ + protected final String consumerGroup; + + /** + * Bus consumer instance + */ + protected final String consumerInstance; + + /** + * Bus fetch timeout + */ + protected final int fetchTimeout; + + /** + * Bus fetch limit + */ + protected final int fetchLimit; + + /** + * Message Bus Consumer + */ + protected BusConsumer consumer; + + /** + * Am I running? + * reflects invocation of start()/stop() + * !locked & start() => alive + * stop() => !alive + */ + protected volatile boolean alive = false; + + /** + * Am I locked? + * reflects invocation of lock()/unlock() operations + * locked => !alive (but not in the other direction necessarily) + * locked => !offer, !run, !start, !stop (but this last one is obvious + * since locked => !alive) + */ + protected volatile boolean locked = false; + + /** + * Independent thread reading message over my topic + */ + protected Thread busPollerThread; + + /** + * All my subscribers for new message notifications + */ + protected final ArrayList<TopicListener> topicListeners = new ArrayList<TopicListener>(); + + /** + * + * @param servers Bus servers + * @param topic Bus Topic to be monitored + * @param apiKey Bus API Key (optional) + * @param apiSecret Bus API Secret (optional) + * @param consumerGroup Bus Reader Consumer Group + * @param consumerInstance Bus Reader Instance + * @param fetchTimeout Bus fetch timeout + * @param fetchLimit Bus fetch limit + * @throws IllegalArgumentException An invalid parameter passed in + */ + public SingleThreadedBusTopicSource(List<String> servers, + String topic, + String apiKey, + String apiSecret, + String consumerGroup, + String consumerInstance, + int fetchTimeout, + int fetchLimit) + throws IllegalArgumentException { + + super(servers, topic, apiKey, apiSecret); + + if (consumerGroup == null || consumerGroup.isEmpty()) { + this.consumerGroup = UUID.randomUUID ().toString(); + } else { + this.consumerGroup = consumerGroup; + } + + if (consumerInstance == null || consumerInstance.isEmpty()) { + this.consumerInstance = DEFAULT_CONSUMER_INSTANCE; + } else { + this.consumerInstance = consumerInstance; + } + + if (fetchTimeout <= 0) { + this.fetchTimeout = NO_TIMEOUT_MS_FETCH; + } else { + this.fetchTimeout = fetchTimeout; + } + + if (fetchLimit <= 0) { + this.fetchLimit = NO_LIMIT_FETCH; + } else { + this.fetchLimit = fetchLimit; + } + } + + /** + * Initialize the Bus client + */ + public abstract void init() throws Exception; + + /** + * {@inheritDoc} + */ + @Override + public void register(TopicListener topicListener) + throws IllegalArgumentException { + + PolicyLogger.info(className,"REGISTER: " + topicListener + " INTO " + this); + + synchronized(this) { + if (topicListener == null) + throw new IllegalArgumentException("TopicListener must be provided"); + + /* check that this listener is not registered already */ + for (TopicListener listener: this.topicListeners) { + if (listener == topicListener) { + // already registered + return; + } + } + + this.topicListeners.add(topicListener); + } + + try { + this.start(); + } catch (Exception e) { + PolicyLogger.info(className, "new registration of " + topicListener + + ",but can't start source because of " + e.getMessage()); + } + } + + /** + * {@inheritDoc} + */ + @Override + public void unregister(TopicListener topicListener) { + + PolicyLogger.info(className, "UNREGISTER: " + topicListener + " FROM " + this); + + boolean stop = false; + synchronized (this) { + if (topicListener == null) + throw new IllegalArgumentException("TopicListener must be provided"); + + this.topicListeners.remove(topicListener); + stop = (this.topicListeners.isEmpty()); + } + + if (stop) { + this.stop(); + } + } + + /** + * {@inheritDoc} + */ + @Override + public boolean lock() { + PolicyLogger.info(className, "LOCK: " + this); + + synchronized (this) { + if (this.locked) + return true; + + this.locked = true; + } + + return this.stop(); + } + + /** + * {@inheritDoc} + */ + @Override + public boolean unlock() { + PolicyLogger.info(className, "UNLOCK: " + this); + + synchronized(this) { + if (!this.locked) + return true; + + this.locked = false; + } + + try { + return this.start(); + } catch (Exception e) { + PolicyLogger.warn("can't start after unlocking " + this + + " because of " + e.getMessage()); + return false; + } + } + + /** + * {@inheritDoc} + */ + @Override + public boolean start() throws IllegalStateException { + + PolicyLogger.info(className, "START: " + this); + + synchronized(this) { + + if (alive) { + return true; + } + + if (locked) { + throw new IllegalStateException(this + " is locked."); + } + + if (this.busPollerThread == null || + !this.busPollerThread.isAlive() || + this.consumer == null) { + + try { + this.init(); + this.alive = true; + this.busPollerThread = new Thread(this); + this.busPollerThread.setName(this.getTopicCommInfrastructure() + "-source-" + this.getTopic()); + busPollerThread.start(); + } catch (Exception e) { + e.printStackTrace(); + throw new IllegalStateException(e); + } + } + } + + return this.alive; + } + + /** + * {@inheritDoc} + */ + @Override + public boolean stop() { + PolicyLogger.info(className, "STOP: " + this); + + synchronized(this) { + BusConsumer consumerCopy = this.consumer; + + this.alive = false; + this.consumer = null; + + if (consumerCopy != null) { + try { + consumerCopy.close(); + } catch (Exception e) { + PolicyLogger.warn(MessageCodes.EXCEPTION_ERROR, e, "CONSUMER.CLOSE", this.toString()); + } + } + } + + Thread.yield(); + + return true; + } + + /** + * {@inheritDoc} + */ + @Override + public boolean isLocked() { + return this.locked; + } + + /** + * broadcast event to all listeners + * + * @param message the event + * @return true if all notifications are performed with no error, false otherwise + */ + protected boolean broadcast(String message) { + + /* take a snapshot of listeners */ + List<TopicListener> snapshotListeners = this.snapshotTopicListeners(); + + boolean success = true; + for (TopicListener topicListener: snapshotListeners) { + try { + topicListener.onTopicEvent(this.getTopicCommInfrastructure(), this.topic, message); + } catch (Exception e) { + PolicyLogger.warn(this.className, "ERROR notifying " + topicListener.toString() + + " because of " + e.getMessage() + " @ " + this.toString()); + success = false; + } + } + return success; + } + + /** + * take a snapshot of current topic listeners + * + * @return the topic listeners + */ + protected synchronized List<TopicListener> snapshotTopicListeners() { + @SuppressWarnings("unchecked") + List<TopicListener> listeners = (List<TopicListener>) topicListeners.clone(); + return listeners; + } + + /** + * Run thread method for the Bus Reader + */ + @Override + public void run() { + while (this.alive) { + try { + for (String event: this.consumer.fetch()) { + synchronized (this) { + this.recentEvents.add(event); + } + + if (networkLogger.isInfoEnabled()) { + networkLogger.info("IN[" + this.getTopicCommInfrastructure() + "|" + + this.topic + "]:" + + event); + } + + PolicyLogger.info(className, this.topic + " <-- " + event); + broadcast(event); + + if (!this.alive) + break; + } + } catch (Exception e) { + PolicyLogger.error( MessageCodes.EXCEPTION_ERROR, className, e, "CONSUMER.FETCH", this.toString()); + } + } + + PolicyLogger.warn(this.className, "Exiting: " + this); + } + + /** + * {@inheritDoc} + */ + @Override + public boolean offer(String event) { + PolicyLogger.info(className, "OFFER: " + event + " TO " + this); + + if (!this.alive) { + throw new IllegalStateException(this + " is not alive."); + } + + synchronized (this) { + this.recentEvents.add(event); + } + + if (networkLogger.isInfoEnabled()) { + networkLogger.info("IN[" + this.getTopicCommInfrastructure() + "|" + + this.topic + "]:" + + event); + } + + + return broadcast(event); + } + + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("SingleThreadedBusTopicSource [consumerGroup=").append(consumerGroup) + .append(", consumerInstance=").append(consumerInstance).append(", fetchTimeout=").append(fetchTimeout) + .append(", fetchLimit=").append(fetchLimit) + .append(", consumer=").append(this.consumer).append(", alive=") + .append(alive).append(", locked=").append(locked).append(", uebThread=").append(busPollerThread) + .append(", topicListeners=").append(topicListeners.size()).append(", toString()=").append(super.toString()) + .append("]"); + return builder.toString(); + } + + /** + * {@inheritDoc} + */ + @Override + public boolean isAlive() { + return alive; + } + + /** + * {@inheritDoc} + */ + @Override + public String getConsumerGroup() { + return consumerGroup; + } + + /** + * {@inheritDoc} + */ + @Override + public String getConsumerInstance() { + return consumerInstance; + } + + /** + * {@inheritDoc} + */ + @Override + public void shutdown() throws IllegalStateException { + this.stop(); + this.topicListeners.clear(); + } + + /** + * {@inheritDoc} + */ + @Override + public int getFetchTimeout() { + return fetchTimeout; + } + + /** + * {@inheritDoc} + */ + @Override + public int getFetchLimit() { + return fetchLimit; + } + +} diff --git a/policy-endpoints/src/main/java/org/openecomp/policy/drools/event/comm/bus/internal/SingleThreadedDmaapTopicSource.java b/policy-endpoints/src/main/java/org/openecomp/policy/drools/event/comm/bus/internal/SingleThreadedDmaapTopicSource.java new file mode 100644 index 00000000..e65d44a7 --- /dev/null +++ b/policy-endpoints/src/main/java/org/openecomp/policy/drools/event/comm/bus/internal/SingleThreadedDmaapTopicSource.java @@ -0,0 +1,120 @@ +/*- + * ============LICENSE_START======================================================= + * policy-endpoints + * ================================================================================ + * 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.event.comm.bus.internal; + +import java.util.List; + +import org.openecomp.policy.drools.event.comm.Topic; +import org.openecomp.policy.drools.event.comm.bus.DmaapTopicSource; +import org.openecomp.policy.common.logging.eelf.PolicyLogger; + +/** + * This topic reader implementation specializes in reading messages + * over DMAAP topic and notifying its listeners + */ +public class SingleThreadedDmaapTopicSource extends SingleThreadedBusTopicSource + implements DmaapTopicSource, Runnable { + + protected final String userName; + protected final String password; + private String className = SingleThreadedDmaapTopicSource.class.getName(); + + /** + * + * @param servers DMaaP servers + * @param topic DMaaP Topic to be monitored + * @param apiKey DMaaP API Key (optional) + * @param apiSecret DMaaP API Secret (optional) + * @param consumerGroup DMaaP Reader Consumer Group + * @param consumerInstance DMaaP Reader Instance + * @param fetchTimeout DMaaP fetch timeout + * @param fetchLimit DMaaP fetch limit + * @throws IllegalArgumentException An invalid parameter passed in + */ + public SingleThreadedDmaapTopicSource(List<String> servers, String topic, + String apiKey, String apiSecret, + String userName, String password, + String consumerGroup, String consumerInstance, + int fetchTimeout, int fetchLimit) + throws IllegalArgumentException { + + + super(servers, topic, apiKey, apiSecret, + consumerGroup, consumerInstance, + fetchTimeout, fetchLimit); + + this.userName = userName; + this.password = password; + + try { + this.init(); + } catch (Exception e) { + e.printStackTrace(); + throw new IllegalArgumentException(e); + } + } + + + /** + * Initialize the Cambria or MR Client + */ + @Override + public void init() throws Exception { + + if (this.userName == null || this.userName.isEmpty() || + this.password == null || this.password.isEmpty()) { + this.consumer = + new BusConsumer.CambriaConsumerWrapper(this.servers, this.topic, + this.apiKey, this.apiSecret, + this.consumerGroup, this.consumerInstance, + this.fetchTimeout, this.fetchLimit); + } else { + this.consumer = + new BusConsumer.DmaapConsumerWrapper(this.servers, this.topic, + this.apiKey, this.apiSecret, + this.userName, this.password, + this.consumerGroup, this.consumerInstance, + this.fetchTimeout, this.fetchLimit); + } + + PolicyLogger.info(className, "CREATION: " + this); + } + + /** + * {@inheritDoc} + */ + @Override + public CommInfrastructure getTopicCommInfrastructure() { + return Topic.CommInfrastructure.DMAAP; + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("SingleThreadedDmaapTopicSource [userName=").append(userName).append(", password=") + .append((password == null || password.isEmpty()) ? "-" : password.length()) + .append(", getTopicCommInfrastructure()=").append(getTopicCommInfrastructure()) + .append(", toString()=").append(super.toString()).append("]"); + return builder.toString(); + } + + +} diff --git a/policy-endpoints/src/main/java/org/openecomp/policy/drools/event/comm/bus/internal/SingleThreadedUebTopicSource.java b/policy-endpoints/src/main/java/org/openecomp/policy/drools/event/comm/bus/internal/SingleThreadedUebTopicSource.java new file mode 100644 index 00000000..edb55c75 --- /dev/null +++ b/policy-endpoints/src/main/java/org/openecomp/policy/drools/event/comm/bus/internal/SingleThreadedUebTopicSource.java @@ -0,0 +1,89 @@ +/*- + * ============LICENSE_START======================================================= + * policy-endpoints + * ================================================================================ + * 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.event.comm.bus.internal; + +import java.util.List; + +import org.openecomp.policy.drools.event.comm.Topic; +import org.openecomp.policy.drools.event.comm.bus.UebTopicSource; + +/** + * This topic source implementation specializes in reading messages + * over an UEB Bus topic source and notifying its listeners + */ +public class SingleThreadedUebTopicSource extends SingleThreadedBusTopicSource + implements UebTopicSource { + + /** + * + * @param servers UEB servers + * @param topic UEB Topic to be monitored + * @param apiKey UEB API Key (optional) + * @param apiSecret UEB API Secret (optional) + * @param consumerGroup UEB Reader Consumer Group + * @param consumerInstance UEB Reader Instance + * @param fetchTimeout UEB fetch timeout + * @param fetchLimit UEB fetch limit + * @throws IllegalArgumentException An invalid parameter passed in + */ + public SingleThreadedUebTopicSource(List<String> servers, String topic, + String apiKey, String apiSecret, + String consumerGroup, String consumerInstance, + int fetchTimeout, int fetchLimit) + throws IllegalArgumentException { + + super(servers, topic, apiKey, apiSecret, + consumerGroup, consumerInstance, + fetchTimeout, fetchLimit); + + + this.init(); + } + + /** + * Initialize the Cambria client + */ + @Override + public void init() { + this.consumer = + new BusConsumer.CambriaConsumerWrapper(this.servers, this.topic, + this.apiKey, this.apiSecret, + this.consumerGroup, this.consumerInstance, + this.fetchTimeout, this.fetchLimit); + } + + /** + * {@inheritDoc} + */ + @Override + public CommInfrastructure getTopicCommInfrastructure() { + return Topic.CommInfrastructure.UEB; + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("SingleThreadedUebTopicSource [getTopicCommInfrastructure()=") + .append(getTopicCommInfrastructure()).append(", toString()=").append(super.toString()).append("]"); + return builder.toString(); + } + +} diff --git a/policy-endpoints/src/main/java/org/openecomp/policy/drools/http/client/HttpClient.java b/policy-endpoints/src/main/java/org/openecomp/policy/drools/http/client/HttpClient.java new file mode 100644 index 00000000..2e81b2c8 --- /dev/null +++ b/policy-endpoints/src/main/java/org/openecomp/policy/drools/http/client/HttpClient.java @@ -0,0 +1,48 @@ +/*- + * ============LICENSE_START======================================================= + * policy-endpoints + * ================================================================================ + * 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.http.client; + +import javax.ws.rs.core.Response; + +import org.openecomp.policy.drools.properties.Startable; + +public interface HttpClient extends Startable { + + public Response get(String path); + + public Response get(); + + public static <T> T getBody(Response response, Class<T> entityType) { + return response.readEntity(entityType); + } + + public String getName(); + public boolean isHttps(); + public boolean isSelfSignedCerts(); + public String getHostname(); + public int getPort(); + public String getBasePath(); + public String getUserName(); + public String getPassword(); + public String getBaseUrl(); + + + public static final HttpClientFactory factory = new IndexedHttpClientFactory(); +} diff --git a/policy-endpoints/src/main/java/org/openecomp/policy/drools/http/client/HttpClientFactory.java b/policy-endpoints/src/main/java/org/openecomp/policy/drools/http/client/HttpClientFactory.java new file mode 100644 index 00000000..53a8c2b2 --- /dev/null +++ b/policy-endpoints/src/main/java/org/openecomp/policy/drools/http/client/HttpClientFactory.java @@ -0,0 +1,185 @@ +/*- + * ============LICENSE_START======================================================= + * policy-endpoints + * ================================================================================ + * 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.http.client; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Properties; + +import org.openecomp.policy.drools.http.client.internal.JerseyClient; +import org.openecomp.policy.drools.properties.PolicyProperties; + +public interface HttpClientFactory { + + public HttpClient build(String name, boolean https, + boolean selfSignedCerts, + String hostname, int port, + String baseUrl, String userName, + String password, boolean managed) + throws Exception; + + public ArrayList<HttpClient> build(Properties properties) throws Exception; + + public HttpClient get(String name); + + public List<HttpClient> inventory(); + + public void destroy(String name); + + public void destroy(); +} + +class IndexedHttpClientFactory implements HttpClientFactory { + + protected HashMap<String, HttpClient> clients = new HashMap<String, HttpClient>(); + + @Override + public synchronized HttpClient build(String name, boolean https, boolean selfSignedCerts, + String hostname, int port, + String baseUrl, String userName, String password, + boolean managed) + throws Exception { + if (clients.containsKey(name)) + return clients.get(name); + + JerseyClient client = + new JerseyClient(name, https, selfSignedCerts, hostname, port, baseUrl, userName, password); + + if (managed) + clients.put(name, client); + + return client; + } + + @Override + public synchronized ArrayList<HttpClient> build(Properties properties) throws Exception { + ArrayList<HttpClient> clientList = new ArrayList<HttpClient>(); + + String clientNames = properties.getProperty(PolicyProperties.PROPERTY_HTTP_CLIENT_SERVICES); + if (clientNames == null || clientNames.isEmpty()) { + return clientList; + } + + List<String> clientNameList = + new ArrayList<String>(Arrays.asList(clientNames.split("\\s*,\\s*"))); + + for (String clientName : clientNameList) { + String httpsString = properties.getProperty(PolicyProperties.PROPERTY_HTTP_CLIENT_SERVICES + "." + + clientName + + PolicyProperties.PROPERTY_HTTP_HTTPS_SUFFIX); + boolean https = false; + if (httpsString != null && !httpsString.isEmpty()) { + https = Boolean.parseBoolean(httpsString); + } + + String hostName = properties.getProperty(PolicyProperties.PROPERTY_HTTP_CLIENT_SERVICES + "." + + clientName + + PolicyProperties.PROPERTY_HTTP_HOST_SUFFIX); + + String servicePortString = properties.getProperty(PolicyProperties.PROPERTY_HTTP_CLIENT_SERVICES + "." + + clientName + + PolicyProperties.PROPERTY_HTTP_PORT_SUFFIX); + int port; + try { + if (servicePortString == null || servicePortString.isEmpty()) { + continue; + } + port = Integer.parseInt(servicePortString); + } catch (NumberFormatException nfe) { + nfe.printStackTrace(); + continue; + } + + String baseUrl = properties.getProperty(PolicyProperties.PROPERTY_HTTP_CLIENT_SERVICES + "." + + clientName + + PolicyProperties.PROPERTY_HTTP_URL_SUFFIX); + + String userName = properties.getProperty(PolicyProperties.PROPERTY_HTTP_CLIENT_SERVICES + "." + + clientName + + PolicyProperties.PROPERTY_HTTP_AUTH_USERNAME_SUFFIX); + + String password = properties.getProperty(PolicyProperties.PROPERTY_HTTP_CLIENT_SERVICES + "." + + clientName + + PolicyProperties.PROPERTY_HTTP_AUTH_PASSWORD_SUFFIX); + + String managedString = properties.getProperty(PolicyProperties.PROPERTY_HTTP_CLIENT_SERVICES + "." + + clientName + + PolicyProperties.PROPERTY_MANAGED_SUFFIX); + boolean managed = true; + if (managedString != null && !managedString.isEmpty()) { + managed = Boolean.parseBoolean(managedString); + } + + try { + HttpClient client = + this.build(clientName, https, https, hostName, port, baseUrl, + userName, password, managed); + clientList.add(client); + } catch (Exception e) { + e.printStackTrace(); + } + } + + return clientList; + } + + @Override + public synchronized HttpClient get(String name) { + if (clients.containsKey(name)) { + return clients.get(name); + } + + throw new IllegalArgumentException("Http Client " + name + " not found"); + } + + @Override + public synchronized List<HttpClient> inventory() { + return new ArrayList<HttpClient>(this.clients.values()); + } + + @Override + public synchronized void destroy(String name) { + if (!clients.containsKey(name)) { + return; + } + + HttpClient client = clients.remove(name); + try { + client.shutdown(); + } catch (IllegalStateException e) { + e.printStackTrace(); + } + } + + @Override + public void destroy() { + List<HttpClient> clientsInventory = this.inventory(); + for (HttpClient client: clientsInventory) { + client.shutdown(); + } + + synchronized(this) { + this.clients.clear(); + } + } + +} diff --git a/policy-endpoints/src/main/java/org/openecomp/policy/drools/http/client/internal/JerseyClient.java b/policy-endpoints/src/main/java/org/openecomp/policy/drools/http/client/internal/JerseyClient.java new file mode 100644 index 00000000..4fa59dc8 --- /dev/null +++ b/policy-endpoints/src/main/java/org/openecomp/policy/drools/http/client/internal/JerseyClient.java @@ -0,0 +1,242 @@ +/*- + * ============LICENSE_START======================================================= + * policy-healthcheck + * ================================================================================ + * 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.http.client.internal; + +import java.security.SecureRandom; +import java.security.cert.CertificateException; +import java.security.cert.X509Certificate; + +import javax.net.ssl.HostnameVerifier; +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLSession; +import javax.net.ssl.TrustManager; +import javax.net.ssl.X509TrustManager; +import javax.ws.rs.client.Client; +import javax.ws.rs.client.ClientBuilder; +import javax.ws.rs.core.Response; + +import org.glassfish.jersey.client.authentication.HttpAuthenticationFeature; +import org.openecomp.policy.drools.http.client.HttpClient; + +import com.fasterxml.jackson.annotation.JsonIgnore; + +public class JerseyClient implements HttpClient { + + protected final String name; + protected final boolean https; + protected final boolean selfSignedCerts; + protected final String hostname; + protected final int port; + protected final String basePath; + protected final String userName; + protected final String password; + + protected final Client client; + protected final String baseUrl; + + protected boolean alive = true; + + + public JerseyClient(String name, boolean https, + boolean selfSignedCerts, + String hostname, int port, + String basePath, String userName, + String password) + throws Exception { + + super(); + + if (name == null || name.isEmpty()) + throw new IllegalArgumentException("Name must be provided"); + + if (hostname == null || hostname.isEmpty()) + throw new IllegalArgumentException("Hostname must be provided"); + + if (port <= 0 && port >= 65535) + throw new IllegalArgumentException("Invalid Port provided: " + port); + + this.name = name; + this.https = https; + this.hostname = hostname; + this.port = port; + this.basePath = basePath; + this.userName = userName; + this.password = password; + this.selfSignedCerts = selfSignedCerts; + + StringBuffer tmpBaseUrl = new StringBuffer(); + if (this.https) { + tmpBaseUrl.append("https://"); + ClientBuilder clientBuilder; + SSLContext sslContext = SSLContext.getInstance("TLSv1.2"); + if (this.selfSignedCerts) { + sslContext.init(null, new TrustManager[]{new X509TrustManager() { + @Override + public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {} + @Override + public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {} + @Override + public X509Certificate[] getAcceptedIssuers() { return new X509Certificate[0]; } + + }}, new SecureRandom()); + clientBuilder = ClientBuilder.newBuilder().sslContext(sslContext).hostnameVerifier(new HostnameVerifier() { + @Override + public boolean verify(String hostname, SSLSession session) {return true;} + }); + } else { + sslContext.init(null, null, null); + clientBuilder = ClientBuilder.newBuilder().sslContext(sslContext); + } + this.client = clientBuilder.build(); + } else { + tmpBaseUrl.append("http://"); + this.client = ClientBuilder.newClient(); + } + + if (this.userName != null && !this.userName.isEmpty() && + this.password != null && !this.password.isEmpty()) { + HttpAuthenticationFeature authFeature = HttpAuthenticationFeature.basic(userName, password); + this.client.register(authFeature); + } + + this.baseUrl = tmpBaseUrl.append(this.hostname).append(":"). + append(this.port).append("/"). + append((this.basePath == null) ? "" : this.basePath). + toString(); + } + + @Override + public Response get(String path) { + if (path != null && !path.isEmpty()) + return this.client.target(this.baseUrl).path(path).request().get(); + else + return this.client.target(this.baseUrl).request().get(); + } + + @Override + public Response get() { + return this.client.target(this.baseUrl).request().get(); + } + + + @Override + public boolean start() throws IllegalStateException { + return alive; + } + + @Override + public boolean stop() throws IllegalStateException { + return !alive; + } + + @Override + public void shutdown() throws IllegalStateException { + synchronized(this) { + alive = false; + } + + try { + this.client.close(); + } catch (Exception e) { + e.printStackTrace(); + } + } + + @Override + public synchronized boolean isAlive() { + return this.alive; + } + + @Override + public String getName() { + return name; + } + + @Override + public boolean isHttps() { + return https; + } + + @Override + public boolean isSelfSignedCerts() { + return selfSignedCerts; + } + + @Override + public String getHostname() { + return hostname; + } + + public int getPort() { + return port; + } + + @Override + public String getBasePath() { + return basePath; + } + + @Override + public String getUserName() { + return userName; + } + + @JsonIgnore + @Override + public String getPassword() { + return password; + } + + @Override + public String getBaseUrl() { + return baseUrl; + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("JerseyClient [name="); + builder.append(name); + builder.append(", https="); + builder.append(https); + builder.append(", selfSignedCerts="); + builder.append(selfSignedCerts); + builder.append(", hostname="); + builder.append(hostname); + builder.append(", port="); + builder.append(port); + builder.append(", basePath="); + builder.append(basePath); + builder.append(", userName="); + builder.append(userName); + builder.append(", password="); + builder.append(password); + builder.append(", client="); + builder.append(client); + builder.append(", baseUrl="); + builder.append(baseUrl); + builder.append(", alive="); + builder.append(alive); + builder.append("]"); + return builder.toString(); + } + +} diff --git a/policy-endpoints/src/main/java/org/openecomp/policy/drools/http/server/HttpServletServer.java b/policy-endpoints/src/main/java/org/openecomp/policy/drools/http/server/HttpServletServer.java new file mode 100644 index 00000000..5f5dd787 --- /dev/null +++ b/policy-endpoints/src/main/java/org/openecomp/policy/drools/http/server/HttpServletServer.java @@ -0,0 +1,81 @@ +/*- + * ============LICENSE_START======================================================= + * policy-endpoints + * ================================================================================ + * 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.http.server; + +import org.openecomp.policy.drools.properties.Startable; + +/** + * A Jetty Server to server REST Requests + */ +public interface HttpServletServer extends Startable { + + /** + * + * @return port + */ + public int getPort(); + + /** + * enables basic authentication with user and password on the the relative path relativeUriPath + * + * @param user + * @param password + * @param relativeUriPath + */ + public void setBasicAuthentication(String user, String password, String relativeUriPath); + + /** + * adds a JAX-RS servlet class to serve REST requests + * + * @param servletPath + * @param restClass + * @throws IllegalArgumentException + * @throws IllegalStateException + */ + public void addServletClass(String servletPath, String restClass) + throws IllegalArgumentException, IllegalStateException; + + /** + * adds a package containing JAX-RS classes to serve REST requests + * + * @param servletPath + * @param restPackage + * @throws IllegalArgumentException + * @throws IllegalStateException + */ + public void addServletPackage(String servletPath, String restPackage) + throws IllegalArgumentException, IllegalStateException; + + /** + * blocking start of the http server + * + * @param maxWaitTime max time to wait for the start to take place + * @return true if start was successful + * + * @throws IllegalArgumentException if arguments are invalid + */ + public boolean waitedStart(long maxWaitTime) throws IllegalArgumentException; + + + /** + * factory for managing and tracking DMAAP sources + */ + public static HttpServletServerFactory factory = new IndexedHttpServletServerFactory(); +} diff --git a/policy-endpoints/src/main/java/org/openecomp/policy/drools/http/server/HttpServletServerFactory.java b/policy-endpoints/src/main/java/org/openecomp/policy/drools/http/server/HttpServletServerFactory.java new file mode 100644 index 00000000..bd5ae242 --- /dev/null +++ b/policy-endpoints/src/main/java/org/openecomp/policy/drools/http/server/HttpServletServerFactory.java @@ -0,0 +1,206 @@ +/*- + * ============LICENSE_START======================================================= + * policy-endpoints + * ================================================================================ + * 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.http.server; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Properties; + +import org.openecomp.policy.common.logging.flexlogger.FlexLogger; +import org.openecomp.policy.common.logging.flexlogger.Logger; +import org.openecomp.policy.drools.http.server.internal.JettyJerseyServer; +import org.openecomp.policy.drools.properties.PolicyProperties; + +/** + * Jetty Server Factory + */ +public interface HttpServletServerFactory { + + public HttpServletServer build(String name, String host, int port, String contextPath, boolean managed) + throws IllegalArgumentException; + + public ArrayList<HttpServletServer> build(Properties properties) throws IllegalArgumentException; + + public HttpServletServer get(int port); + public List<HttpServletServer> inventory(); + public void destroy(int port); + public void destroy(); +} + +class IndexedHttpServletServerFactory implements HttpServletServerFactory { + + protected static Logger logger = FlexLogger.getLogger(IndexedHttpServletServerFactory.class); + + protected HashMap<Integer, JettyJerseyServer> servers = new HashMap<Integer, JettyJerseyServer>(); + + @Override + public synchronized HttpServletServer build(String name, String host, int port, + String contextPath, boolean managed) + throws IllegalArgumentException { + + if (servers.containsKey(port)) + return servers.get(port); + + JettyJerseyServer server = new JettyJerseyServer(name, host, port, contextPath); + if (managed) + servers.put(port, server); + + return server; + } + + @Override + public synchronized ArrayList<HttpServletServer> build(Properties properties) + throws IllegalArgumentException { + + ArrayList<HttpServletServer> serviceList = new ArrayList<HttpServletServer>(); + + String serviceNames = properties.getProperty(PolicyProperties.PROPERTY_HTTP_SERVER_SERVICES); + if (serviceNames == null || serviceNames.isEmpty()) { + logger.warn("No topic for HTTP Service " + properties); + return serviceList; + } + + List<String> serviceNameList = + new ArrayList<String>(Arrays.asList(serviceNames.split("\\s*,\\s*"))); + + for (String serviceName : serviceNameList) { + String servicePortString = properties.getProperty(PolicyProperties.PROPERTY_HTTP_SERVER_SERVICES + "." + + serviceName + + PolicyProperties.PROPERTY_HTTP_PORT_SUFFIX); + + int servicePort; + try { + if (servicePortString == null || servicePortString.isEmpty()) { + if (logger.isWarnEnabled()) + logger.warn("No HTTP port for service in " + serviceName); + continue; + } + servicePort = Integer.parseInt(servicePortString); + } catch (NumberFormatException nfe) { + if (logger.isWarnEnabled()) + logger.warn("No HTTP port for service in " + serviceName); + continue; + } + + String hostName = properties.getProperty(PolicyProperties.PROPERTY_HTTP_SERVER_SERVICES + "." + + serviceName + + PolicyProperties.PROPERTY_HTTP_HOST_SUFFIX); + + String contextUriPath = properties.getProperty(PolicyProperties.PROPERTY_HTTP_SERVER_SERVICES + "." + + serviceName + + PolicyProperties.PROPERTY_HTTP_CONTEXT_URIPATH_SUFFIX); + + String userName = properties.getProperty(PolicyProperties.PROPERTY_HTTP_SERVER_SERVICES + "." + + serviceName + + PolicyProperties.PROPERTY_HTTP_AUTH_USERNAME_SUFFIX); + + String password = properties.getProperty(PolicyProperties.PROPERTY_HTTP_SERVER_SERVICES + "." + + serviceName + + PolicyProperties.PROPERTY_HTTP_AUTH_PASSWORD_SUFFIX); + + String authUriPath = properties.getProperty(PolicyProperties.PROPERTY_HTTP_SERVER_SERVICES + "." + + serviceName + + PolicyProperties.PROPERTY_HTTP_AUTH_URIPATH_SUFFIX); + + String restClasses = properties.getProperty(PolicyProperties.PROPERTY_HTTP_SERVER_SERVICES + "." + + serviceName + + PolicyProperties.PROPERTY_HTTP_REST_CLASSES_SUFFIX); + + String restPackages = properties.getProperty(PolicyProperties.PROPERTY_HTTP_SERVER_SERVICES + "." + + serviceName + + PolicyProperties.PROPERTY_HTTP_REST_PACKAGES_SUFFIX); + String restUriPath = properties.getProperty(PolicyProperties.PROPERTY_HTTP_SERVER_SERVICES + "." + + serviceName + + PolicyProperties.PROPERTY_HTTP_REST_URIPATH_SUFFIX); + + String managedString = properties.getProperty(PolicyProperties.PROPERTY_HTTP_SERVER_SERVICES + "." + + serviceName + + PolicyProperties.PROPERTY_MANAGED_SUFFIX); + boolean managed = true; + if (managedString != null && !managedString.isEmpty()) { + managed = Boolean.parseBoolean(managedString); + } + + HttpServletServer service = build(serviceName, hostName, servicePort, contextUriPath, managed); + if (userName != null && !userName.isEmpty() && password != null && !password.isEmpty()) { + service.setBasicAuthentication(userName, password, authUriPath); + } + + if (restClasses != null && !restClasses.isEmpty()) { + List<String> restClassesList = + new ArrayList<String>(Arrays.asList(restClasses.split("\\s*,\\s*"))); + for (String restClass : restClassesList) + service.addServletClass(restUriPath, restClass); + } + + if (restPackages != null && !restPackages.isEmpty()) { + List<String> restPackageList = + new ArrayList<String>(Arrays.asList(restPackages.split("\\s*,\\s*"))); + for (String restPackage : restPackageList) + service.addServletPackage(restUriPath, restPackage); + } + + serviceList.add(service); + } + + return serviceList; + } + + @Override + public synchronized HttpServletServer get(int port) throws IllegalArgumentException { + + if (servers.containsKey(port)) { + return servers.get(port); + } + + throw new IllegalArgumentException("Http Server for " + port + " not found"); + } + + @Override + public synchronized List<HttpServletServer> inventory() { + return new ArrayList<HttpServletServer>(this.servers.values()); + } + + @Override + public synchronized void destroy(int port) throws IllegalArgumentException, IllegalStateException { + + if (!servers.containsKey(port)) { + return; + } + + HttpServletServer server = servers.remove(port); + server.shutdown(); + } + + @Override + public synchronized void destroy() throws IllegalArgumentException, IllegalStateException { + List<HttpServletServer> servers = this.inventory(); + for (HttpServletServer server: servers) { + server.shutdown(); + } + + synchronized(this) { + this.servers.clear(); + } + } + +} diff --git a/policy-endpoints/src/main/java/org/openecomp/policy/drools/http/server/internal/JettyJerseyServer.java b/policy-endpoints/src/main/java/org/openecomp/policy/drools/http/server/internal/JettyJerseyServer.java new file mode 100644 index 00000000..4914a4cb --- /dev/null +++ b/policy-endpoints/src/main/java/org/openecomp/policy/drools/http/server/internal/JettyJerseyServer.java @@ -0,0 +1,130 @@ +/*- + * ============LICENSE_START======================================================= + * policy-endpoints + * ================================================================================ + * 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.http.server.internal; + +import java.util.ArrayList; +import java.util.HashMap; + +import org.eclipse.jetty.servlet.ServletHolder; + +import org.openecomp.policy.common.logging.flexlogger.FlexLogger; +import org.openecomp.policy.common.logging.flexlogger.Logger; + +/** + * REST Jetty Server using Jersey + */ +public class JettyJerseyServer extends JettyServletServer { + + protected static final String JERSEY_PACKAGES_PARAM = "jersey.config.server.provider.packages"; + protected static final String JERSEY_CLASSNAMES_PARAM = "jersey.config.server.provider.classnames"; + + protected static Logger logger = FlexLogger.getLogger(JettyJerseyServer.class); + + protected ArrayList<String> packages = new ArrayList<String>(); + protected HashMap<String, ServletHolder> servlets = + new HashMap<String, ServletHolder>(); + + public JettyJerseyServer(String name, String host, int port, String contextPath) + throws IllegalArgumentException { + super(name, host, port, contextPath); + } + + protected synchronized ServletHolder getServlet(String servletPath) + throws IllegalArgumentException { + + if (servletPath == null || servletPath.isEmpty()) + servletPath = "/*"; + + ServletHolder jerseyServlet = servlets.get(servletPath); + if (jerseyServlet == null) { + jerseyServlet = context.addServlet + (org.glassfish.jersey.servlet.ServletContainer.class, servletPath); + jerseyServlet.setInitOrder(0); + String initPackages = + jerseyServlet.getInitParameter(JERSEY_PACKAGES_PARAM); + if (initPackages == null) { + jerseyServlet.setInitParameter( + JERSEY_PACKAGES_PARAM, + "com.jersey.jaxb,com.fasterxml.jackson.jaxrs.json"); + } + this.servlets.put(servletPath, jerseyServlet); + } + + return jerseyServlet; + } + + @Override + public synchronized void addServletPackage(String servletPath, String restPackage) + throws IllegalArgumentException, IllegalStateException { + + if (restPackage == null || restPackage.isEmpty()) + throw new IllegalArgumentException("No discoverable REST package provided"); + + ServletHolder jerseyServlet = this.getServlet(servletPath); + if (jerseyServlet == null) + throw new IllegalStateException("Unexpected, no Jersey Servlet class"); + + String initPackages = + jerseyServlet.getInitParameter(JERSEY_PACKAGES_PARAM); + if (initPackages == null) + throw new IllegalStateException("Unexpected, no Init Parameters loaded"); + + jerseyServlet.setInitParameter( + JERSEY_PACKAGES_PARAM, + initPackages + "," + restPackage); + + if (logger.isDebugEnabled()) + logger.debug(this + "Added REST Package: " + jerseyServlet.dump()); + } + + @Override + public synchronized void addServletClass(String servletPath, String restClass) + throws IllegalArgumentException, IllegalStateException { + + if (restClass == null || restClass.isEmpty()) + throw new IllegalArgumentException("No discoverable REST class provided"); + + ServletHolder jerseyServlet = this.getServlet(servletPath); + if (jerseyServlet == null) + throw new IllegalStateException("Unexpected, no Jersey Servlet class"); + + String initClasses = + jerseyServlet.getInitParameter(JERSEY_CLASSNAMES_PARAM); + if (initClasses == null) + initClasses = restClass; + else + initClasses = initClasses + "," + restClass; + + jerseyServlet.setInitParameter( + JERSEY_CLASSNAMES_PARAM, + initClasses); + + if (logger.isDebugEnabled()) + logger.debug(this + "Added REST Class: " + jerseyServlet.dump()); + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("JerseyJettyServer [packages=").append(packages).append(", servlets=").append(servlets) + .append(", toString()=").append(super.toString()).append("]"); + return builder.toString(); + } +} diff --git a/policy-endpoints/src/main/java/org/openecomp/policy/drools/http/server/internal/JettyServletServer.java b/policy-endpoints/src/main/java/org/openecomp/policy/drools/http/server/internal/JettyServletServer.java new file mode 100644 index 00000000..74360e80 --- /dev/null +++ b/policy-endpoints/src/main/java/org/openecomp/policy/drools/http/server/internal/JettyServletServer.java @@ -0,0 +1,353 @@ +/*- + * ============LICENSE_START======================================================= + * policy-endpoints + * ================================================================================ + * 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.http.server.internal; + +import org.eclipse.jetty.security.ConstraintMapping; +import org.eclipse.jetty.security.ConstraintSecurityHandler; +import org.eclipse.jetty.security.HashLoginService; +import org.eclipse.jetty.security.authentication.BasicAuthenticator; +import org.eclipse.jetty.server.Server; +import org.eclipse.jetty.server.ServerConnector; +import org.eclipse.jetty.servlet.ServletContextHandler; +import org.eclipse.jetty.util.security.Constraint; +import org.eclipse.jetty.util.security.Credential; + +import org.openecomp.policy.common.logging.eelf.MessageCodes; +import org.openecomp.policy.common.logging.flexlogger.FlexLogger; +import org.openecomp.policy.common.logging.flexlogger.Logger; +import org.openecomp.policy.drools.http.server.HttpServletServer; + +import com.fasterxml.jackson.annotation.JsonIgnore; + +/** + * Http Server implementation using Embedded Jetty + */ +public abstract class JettyServletServer implements HttpServletServer, Runnable { + + private static Logger logger = FlexLogger.getLogger(JettyServletServer.class); + + protected final String name; + + protected final String host; + protected final int port; + + protected String user; + protected String password; + + protected final String contextPath; + + protected final Server jettyServer; + protected final ServletContextHandler context; + protected final ServerConnector connector; + + protected volatile Thread jettyThread; + + protected Object startCondition = new Object(); + + public JettyServletServer(String name, String host, int port, String contextPath) + throws IllegalArgumentException { + + if (name == null || name.isEmpty()) + name = "http-" + port; + + if (port <= 0 && port >= 65535) + throw new IllegalArgumentException("Invalid Port provided: " + port); + + if (host == null || host.isEmpty()) + host = "localhost"; + + if (contextPath == null || contextPath.isEmpty()) + contextPath = "/"; + + this.name = name; + + this.host = host; + this.port = port; + + this.contextPath = contextPath; + + this.context = new ServletContextHandler(ServletContextHandler.SESSIONS); + this.context.setContextPath(contextPath); + + this.jettyServer = new Server(); + + this.connector = new ServerConnector(this.jettyServer); + this.connector.setName(name); + this.connector.setReuseAddress(true); + this.connector.setPort(port); + this.connector.setHost(host); + + this.jettyServer.addConnector(this.connector); + this.jettyServer.setHandler(context); + } + + /** + * {@inheritDoc} + */ + @Override + public void setBasicAuthentication(String user, String password, String servletPath) { + if (user == null || user.isEmpty() || password == null || password.isEmpty()) + throw new IllegalArgumentException("Missing user and/or password"); + + if (servletPath == null || servletPath.isEmpty()) + servletPath = "/*"; + + HashLoginService hashLoginService = new HashLoginService(); + hashLoginService.putUser(user, + Credential.getCredential(password), + new String[] {"user"}); + hashLoginService.setName(this.connector.getName() + "-login-service"); + + Constraint constraint = new Constraint(); + constraint.setName(Constraint.__BASIC_AUTH); + constraint.setRoles(new String[]{"user"}); + constraint.setAuthenticate(true); + + ConstraintMapping constraintMapping = new ConstraintMapping(); + constraintMapping.setConstraint(constraint); + constraintMapping.setPathSpec(servletPath); + + ConstraintSecurityHandler securityHandler = new ConstraintSecurityHandler(); + securityHandler.setAuthenticator(new BasicAuthenticator()); + securityHandler.setRealmName(this.connector.getName() + "-realm"); + securityHandler.addConstraintMapping(constraintMapping); + securityHandler.setLoginService(hashLoginService); + + this.context.setSecurityHandler(securityHandler); + + this.user = user; + this.password = password; + } + + /** + * Jetty Server Execution + */ + @Override + public void run() { + try { + if (logger.isInfoEnabled()) + logger.info(this + " STARTING " + this.jettyServer.dump()); + + this.jettyServer.start(); + + synchronized(this.startCondition) { + this.startCondition.notifyAll(); + } + + this.jettyServer.join(); + } catch (Exception e) { + logger.warn(MessageCodes.EXCEPTION_ERROR, e, + "Error found while running management server", this.toString()); + } + } + + @Override + public boolean waitedStart(long maxWaitTime) throws IllegalArgumentException { + + if (maxWaitTime < 0) + throw new IllegalArgumentException("max-wait-time cannot be negative"); + + long pendingWaitTime = maxWaitTime; + + if (!this.start()) + return false; + + synchronized (this.startCondition) { + + while (!this.jettyServer.isRunning()) { + try { + long startTs = System.currentTimeMillis(); + + this.startCondition.wait(pendingWaitTime); + + if (maxWaitTime == 0) + /* spurious notification */ + continue; + + long endTs = System.currentTimeMillis(); + pendingWaitTime = pendingWaitTime - (endTs - startTs); + + if (logger.isInfoEnabled()) + logger.info(this + "Pending time is " + pendingWaitTime + + " ms."); + + if (pendingWaitTime <= 0) + return false; + + } catch (InterruptedException e) { + logger.warn("waited-start has been interrupted"); + return false; + } + } + + return (this.jettyServer.isRunning()); + } + } + + /** + * {@inheritDoc} + */ + @Override + public boolean start() throws IllegalStateException { + if (logger.isDebugEnabled()) + logger.debug(this + "START"); + + synchronized(this) { + if (jettyThread == null || + !this.jettyThread.isAlive()) { + + this.jettyThread = new Thread(this); + this.jettyThread.setName(this.name + "-" + this.port); + this.jettyThread.start(); + } + } + + return true; + } + + /** + * {@inheritDoc} + */ + @Override + public boolean stop() throws IllegalStateException { + logger.info(this + "STOP"); + + synchronized(this) { + if (jettyThread == null) { + return true; + } + + if (!jettyThread.isAlive()) { + this.jettyThread = null; + } + + try { + this.connector.stop(); + } catch (Exception e) { + logger.error(MessageCodes.EXCEPTION_ERROR, e, + "Error while stopping management server", this.toString()); + e.printStackTrace(); + } + + try { + this.jettyServer.stop(); + } catch (Exception e) { + logger.error(MessageCodes.EXCEPTION_ERROR, e, + "Error while stopping management server", this.toString()); + return false; + } + + Thread.yield(); + } + + return true; + } + + /** + * {@inheritDoc} + */ + @Override + public void shutdown() throws IllegalStateException { + logger.info(this + "SHUTDOWN"); + + this.stop(); + + if (this.jettyThread == null) + return; + + Thread jettyThreadCopy = this.jettyThread; + + if (jettyThreadCopy.isAlive()) { + try { + jettyThreadCopy.join(1000L); + } catch (InterruptedException e) { + logger.warn(MessageCodes.EXCEPTION_ERROR, e, + "Error while shutting down management server", this.toString()); + } + if (!jettyThreadCopy.isInterrupted()) { + try { + jettyThreadCopy.interrupt(); + } catch(Exception e) { + // do nothing + logger.warn("exception while shutting down (OK)"); + } + } + } + + this.jettyServer.destroy(); + } + + /** + * {@inheritDoc} + */ + @Override + public boolean isAlive() { + if (this.jettyThread != null) + return this.jettyThread.isAlive(); + + return false; + } + + @Override + public int getPort() { + return this.port; + } + + /** + * @return the name + */ + public String getName() { + return name; + } + + /** + * @return the host + */ + public String getHost() { + return host; + } + + /** + * @return the user + */ + public String getUser() { + return user; + } + + /** + * @return the password + */ + @JsonIgnore + public String getPassword() { + return password; + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("JettyServer [name=").append(name).append(", host=").append(host).append(", port=").append(port) + .append(", user=").append(user).append(", password=").append((password != null)).append(", contextPath=") + .append(contextPath).append(", jettyServer=").append(jettyServer).append(", context=").append(this.context) + .append(", connector=").append(connector).append(", jettyThread=").append(jettyThread) + .append("]"); + return builder.toString(); + } + +} diff --git a/policy-endpoints/src/main/resources/schema/pdpd-configuration.jsonschema b/policy-endpoints/src/main/resources/schema/pdpd-configuration.jsonschema new file mode 100644 index 00000000..34ee199a --- /dev/null +++ b/policy-endpoints/src/main/resources/schema/pdpd-configuration.jsonschema @@ -0,0 +1,61 @@ +{ + "title": "ENGINE-CONFIGURATION", + "type":"object", + "$schema": "http://json-schema.org/draft-03/schema", + "required":false, + "properties":{ + "requestID": { + "description": "Unique Transaction ID. This is an UUID.", + "type":"string", + "required":true + }, + "entity": { + "description": "Set of entities on which configuration can be performed: controller", + "type":"string", + "required":true + }, + "controllers": { + "description": "Controller Information, only applicable when the entity is set to controller", + "type":"array", + "required":false, + "items": { + "description": "Drools Related Information", + "type":"object", + "required":true, + "properties":{ + "name": { + "type":"string", + "required":true + }, + "operation": { + "description": "Set of operations that can be applied to a controller: create, lock", + "type":"string", + "required":true + }, + "drools": { + "description": "Maven Related Information", + "type":"object", + "required":false, + "properties":{ + "artifactId": { + "description": "Maven Artifact ID", + "type":"string", + "required":true + }, + "groupId": { + "description": "Maven Group ID", + "type":"string", + "required":true + }, + "version": { + "description": "Maven Version", + "type":"string", + "required":true + } + } + } + } + } + } + } +} diff --git a/policy-endpoints/src/test/java/org/openecomp/policy/drools/http/server/test/HttpClientTest.java b/policy-endpoints/src/test/java/org/openecomp/policy/drools/http/server/test/HttpClientTest.java new file mode 100644 index 00000000..ced3dcf4 --- /dev/null +++ b/policy-endpoints/src/test/java/org/openecomp/policy/drools/http/server/test/HttpClientTest.java @@ -0,0 +1,230 @@ +/*- + * ============LICENSE_START======================================================= + * policy-endpoints + * ================================================================================ + * 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.http.server.test; + +import static org.junit.Assert.assertTrue; + +import java.util.ArrayList; +import java.util.Properties; + +import javax.ws.rs.core.Response; + +import org.junit.Test; +import org.openecomp.policy.drools.http.client.HttpClient; +import org.openecomp.policy.drools.http.server.HttpServletServer; +import org.openecomp.policy.drools.properties.PolicyProperties; + +public class HttpClientTest { + + @Test + public void testHttpNoAuthClient() throws Exception { + System.out.println("-- testHttpNoAuthClient() --"); + + HttpServletServer server = HttpServletServer.factory.build("echo", "localhost", 6666, "/", true); + server.addServletPackage("/*", this.getClass().getPackage().getName()); + server.waitedStart(5000); + + HttpClient client = HttpClient.factory.build("testHttpNoAuthClient", false, false, + "localhost", 6666, "junit/echo", + null, null, true); + Response response = client.get("hello"); + String body = HttpClient.getBody(response, String.class); + + assertTrue(response.getStatus() == 200); + assertTrue(body.equals("hello")); + + HttpServletServer.factory.destroy(); + HttpClient.factory.destroy(); + } + + @Test + public void testHttpAuthClient() throws Exception { + System.out.println("-- testHttpAuthClient() --"); + + HttpServletServer server = HttpServletServer.factory.build("echo", "localhost", 6666, "/", true); + server.setBasicAuthentication("x", "y", null); + server.addServletPackage("/*", this.getClass().getPackage().getName()); + server.waitedStart(5000); + + HttpClient client = HttpClient.factory.build("testHttpAuthClient",false, false, + "localhost", 6666, "junit/echo", + "x", "y", true); + Response response = client.get("hello"); + String body = HttpClient.getBody(response, String.class); + + assertTrue(response.getStatus() == 200); + assertTrue(body.equals("hello")); + + HttpServletServer.factory.destroy(); + HttpClient.factory.destroy(); + } + + @Test + public void testHttpAuthClient401() throws Exception { + System.out.println("-- testHttpAuthClient401() --"); + + HttpServletServer server = HttpServletServer.factory.build("echo", "localhost", 6666, "/", true); + server.setBasicAuthentication("x", "y", null); + server.addServletPackage("/*", this.getClass().getPackage().getName()); + server.waitedStart(5000); + + HttpClient client = HttpClient.factory.build("testHttpAuthClient401",false, false, + "localhost", 6666, "junit/echo", + null, null, true); + Response response = client.get("hello"); + assertTrue(response.getStatus() == 401); + + HttpServletServer.factory.destroy(); + HttpClient.factory.destroy(); + } + + //@Test + public void testHttpAuthClientHttps() throws Exception { + System.out.println("-- testHttpAuthClientHttps() --"); + + HttpClient client = HttpClient.factory.build("testHttpAuthClientHttps", true, true, "somehost.somewhere.com", + 9091, "pap/test", "testpap", "alpha123", true); + Response response = client.get(); + assertTrue(response.getStatus() == 200); + + HttpClient client2 = HttpClient.factory.build("testHttpAuthClientHttps2", true, true, "somehost.somewhere.com", + 8081, "pdp", "testpdp", "alpha123", true); + Response response2 = client2.get("test"); + assertTrue(response2.getStatus() == 500); + + HttpServletServer.factory.destroy(); + HttpClient.factory.destroy(); + } + + @Test + public void testHttpAuthClientProps() throws Exception { + System.out.println("-- testHttpAuthClientProps() --"); + + Properties httpProperties = new Properties(); + + httpProperties.setProperty(PolicyProperties.PROPERTY_HTTP_SERVER_SERVICES, "PAP,PDP"); + httpProperties.setProperty + (PolicyProperties.PROPERTY_HTTP_SERVER_SERVICES + "." + "PAP" + PolicyProperties.PROPERTY_HTTP_HOST_SUFFIX, + "localhost"); + httpProperties.setProperty + (PolicyProperties.PROPERTY_HTTP_SERVER_SERVICES + "." + "PAP" + PolicyProperties.PROPERTY_HTTP_PORT_SUFFIX, + "9091"); + httpProperties.setProperty + (PolicyProperties.PROPERTY_HTTP_SERVER_SERVICES + "." + "PAP" + PolicyProperties.PROPERTY_HTTP_AUTH_USERNAME_SUFFIX, + "testpap"); + httpProperties.setProperty + (PolicyProperties.PROPERTY_HTTP_SERVER_SERVICES + "." + "PAP" + PolicyProperties.PROPERTY_HTTP_AUTH_PASSWORD_SUFFIX, + "alpha123"); + httpProperties.setProperty + (PolicyProperties.PROPERTY_HTTP_SERVER_SERVICES + "." + "PAP" + PolicyProperties.PROPERTY_HTTP_REST_CLASSES_SUFFIX, + "org.openecomp.policy.drools.http.server.test.RestMockHealthCheck"); + httpProperties.setProperty + (PolicyProperties.PROPERTY_HTTP_CLIENT_SERVICES + "." + "PAP" + PolicyProperties.PROPERTY_MANAGED_SUFFIX, + "true"); + + httpProperties.setProperty + (PolicyProperties.PROPERTY_HTTP_SERVER_SERVICES + "." + "PDP" + PolicyProperties.PROPERTY_HTTP_HOST_SUFFIX, + "localhost"); + httpProperties.setProperty + (PolicyProperties.PROPERTY_HTTP_SERVER_SERVICES + "." + "PDP" + PolicyProperties.PROPERTY_HTTP_PORT_SUFFIX, + "8081"); + httpProperties.setProperty + (PolicyProperties.PROPERTY_HTTP_SERVER_SERVICES + "." + "PDP" + PolicyProperties.PROPERTY_HTTP_AUTH_USERNAME_SUFFIX, + "testpdp"); + httpProperties.setProperty + (PolicyProperties.PROPERTY_HTTP_SERVER_SERVICES + "." + "PDP" + PolicyProperties.PROPERTY_HTTP_AUTH_PASSWORD_SUFFIX, + "alpha123"); + httpProperties.setProperty + (PolicyProperties.PROPERTY_HTTP_SERVER_SERVICES + "." + "PDP" + PolicyProperties.PROPERTY_HTTP_REST_CLASSES_SUFFIX, + "org.openecomp.policy.drools.http.server.test.RestMockHealthCheck"); + httpProperties.setProperty + (PolicyProperties.PROPERTY_HTTP_CLIENT_SERVICES + "." + "PAP" + PolicyProperties.PROPERTY_MANAGED_SUFFIX, + "true"); + + httpProperties.setProperty(PolicyProperties.PROPERTY_HTTP_CLIENT_SERVICES, "PAP,PDP"); + httpProperties.setProperty + (PolicyProperties.PROPERTY_HTTP_CLIENT_SERVICES + "." + "PAP" + PolicyProperties.PROPERTY_HTTP_HOST_SUFFIX, + "localhost"); + httpProperties.setProperty + (PolicyProperties.PROPERTY_HTTP_CLIENT_SERVICES + "." + "PAP" + PolicyProperties.PROPERTY_HTTP_PORT_SUFFIX, + "9091"); + httpProperties.setProperty + (PolicyProperties.PROPERTY_HTTP_CLIENT_SERVICES + "." + "PAP" + PolicyProperties.PROPERTY_HTTP_URL_SUFFIX, + "pap/test"); + httpProperties.setProperty + (PolicyProperties.PROPERTY_HTTP_CLIENT_SERVICES + "." + "PAP" + PolicyProperties.PROPERTY_HTTP_HTTPS_SUFFIX, + "false"); + httpProperties.setProperty + (PolicyProperties.PROPERTY_HTTP_CLIENT_SERVICES + "." + "PAP" + PolicyProperties.PROPERTY_HTTP_AUTH_USERNAME_SUFFIX, + "testpap"); + httpProperties.setProperty + (PolicyProperties.PROPERTY_HTTP_CLIENT_SERVICES + "." + "PAP" + PolicyProperties.PROPERTY_HTTP_AUTH_PASSWORD_SUFFIX, + "alpha123"); + httpProperties.setProperty + (PolicyProperties.PROPERTY_HTTP_CLIENT_SERVICES + "." + "PAP" + PolicyProperties.PROPERTY_MANAGED_SUFFIX, + "true"); + + httpProperties.setProperty + (PolicyProperties.PROPERTY_HTTP_CLIENT_SERVICES + "." + "PDP" + PolicyProperties.PROPERTY_HTTP_HOST_SUFFIX, + "localhost"); + httpProperties.setProperty + (PolicyProperties.PROPERTY_HTTP_CLIENT_SERVICES + "." + "PDP" + PolicyProperties.PROPERTY_HTTP_PORT_SUFFIX, + "8081"); + httpProperties.setProperty + (PolicyProperties.PROPERTY_HTTP_CLIENT_SERVICES + "." + "PDP" + PolicyProperties.PROPERTY_HTTP_URL_SUFFIX, + "pdp"); + httpProperties.setProperty + (PolicyProperties.PROPERTY_HTTP_CLIENT_SERVICES + "." + "PDP" + PolicyProperties.PROPERTY_HTTP_HTTPS_SUFFIX, + "false"); + httpProperties.setProperty + (PolicyProperties.PROPERTY_HTTP_CLIENT_SERVICES + "." + "PDP" + PolicyProperties.PROPERTY_HTTP_AUTH_USERNAME_SUFFIX, + "testpdp"); + httpProperties.setProperty + (PolicyProperties.PROPERTY_HTTP_CLIENT_SERVICES + "." + "PDP" + PolicyProperties.PROPERTY_HTTP_AUTH_PASSWORD_SUFFIX, + "alpha123"); + httpProperties.setProperty + (PolicyProperties.PROPERTY_HTTP_CLIENT_SERVICES + "." + "PDP" + PolicyProperties.PROPERTY_MANAGED_SUFFIX, + "true"); + + ArrayList<HttpServletServer> servers = HttpServletServer.factory.build(httpProperties); + assertTrue(servers.size() == 2); + + ArrayList<HttpClient> clients = HttpClient.factory.build(httpProperties); + assertTrue(clients.size() == 2); + + for (HttpServletServer server: servers) { + server.waitedStart(5000); + } + + HttpClient clientPAP = HttpClient.factory.get("PAP"); + Response response = clientPAP.get(); + assertTrue(response.getStatus() == 200); + + HttpClient clientPDP = HttpClient.factory.get("PDP"); + Response response2 = clientPDP.get("test"); + assertTrue(response2.getStatus() == 500); + + HttpServletServer.factory.destroy(); + HttpClient.factory.destroy(); + } + + +} diff --git a/policy-endpoints/src/test/java/org/openecomp/policy/drools/http/server/test/HttpServerTest.java b/policy-endpoints/src/test/java/org/openecomp/policy/drools/http/server/test/HttpServerTest.java new file mode 100644 index 00000000..94f29804 --- /dev/null +++ b/policy-endpoints/src/test/java/org/openecomp/policy/drools/http/server/test/HttpServerTest.java @@ -0,0 +1,181 @@ +/*- + * ============LICENSE_START======================================================= + * policy-endpoints + * ================================================================================ + * 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.http.server.test; + +import static org.junit.Assert.assertTrue; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.net.URL; +import java.util.UUID; + +import org.junit.Test; +import org.openecomp.policy.drools.http.server.HttpServletServer; + +/** + * + */ +public class HttpServerTest { + + @Test + public void testSingleServer() throws Exception { + System.out.println("-- testSingleServer() --"); + + HttpServletServer server = HttpServletServer.factory.build("echo", "localhost", 5678, "/", true); + server.addServletPackage("/*", this.getClass().getPackage().getName()); + server.waitedStart(5000); + + assertTrue(HttpServletServer.factory.get(5678).isAlive()); + + String echo = "hello"; + URL url = new URL("http://localhost:5678/junit/echo/" + echo); + String response = response(url); + System.out.println("Received .. " + response); + assertTrue(response.equals(echo)); + + HttpServletServer.factory.destroy(); + assertTrue(HttpServletServer.factory.inventory().size() == 0); + } + + @Test + public void testMultipleServers() throws Exception { + System.out.println("-- testMultipleServers() --"); + + HttpServletServer server1 = HttpServletServer.factory.build("echo-1", "localhost", 5678, "/", true); + server1.addServletPackage("/*", this.getClass().getPackage().getName()); + server1.waitedStart(5000); + + HttpServletServer server2 = HttpServletServer.factory.build("echo-2", "localhost", 5679, "/", true); + server2.addServletPackage("/*", this.getClass().getPackage().getName()); + server2.waitedStart(5000); + + assertTrue(HttpServletServer.factory.get(5678).isAlive()); + assertTrue(HttpServletServer.factory.get(5679).isAlive()); + + String echo = "hello"; + + URL url1 = new URL("http://localhost:5678/junit/echo/" + echo); + String response1 = response(url1); + System.out.println("Received .. " + response1); + assertTrue(response1.equals(echo)); + + URL url2 = new URL("http://localhost:5679/junit/echo/" + echo); + String response2 = response(url2); + System.out.println("Received .. " + response2); + assertTrue(response2.equals(echo)); + + HttpServletServer.factory.destroy(); + assertTrue(HttpServletServer.factory.inventory().size() == 0); + } + + @Test + public void testMultiServicePackage() throws Exception { + System.out.println("-- testMultiServicePackage() --"); + + String randomName = UUID.randomUUID().toString(); + + HttpServletServer server = HttpServletServer.factory.build(randomName, "localhost", 5678, "/", true); + server.addServletPackage("/*", this.getClass().getPackage().getName()); + server.waitedStart(5000); + + assertTrue(HttpServletServer.factory.get(5678).isAlive()); + + String echo = "hello"; + URL urlService1 = new URL("http://localhost:5678/junit/echo/" + echo); + String responseService1 = response(urlService1); + System.out.println("Received .. " + responseService1); + assertTrue(responseService1.equals(echo)); + + URL urlService2 = new URL("http://localhost:5678/junit/endpoints/http/servers"); + String responseService2 = response(urlService2); + System.out.println("Received .. " + responseService2); + assertTrue(responseService2.contains(randomName)); + + HttpServletServer.factory.destroy(); + assertTrue(HttpServletServer.factory.inventory().size() == 0); + } + + @Test + public void testServiceClass() throws Exception { + System.out.println("-- testServiceClass() --"); + String randomName = UUID.randomUUID().toString(); + + HttpServletServer server = HttpServletServer.factory.build(randomName, "localhost", 5678, "/", true); + server.addServletClass("/*", RestEchoService.class.getCanonicalName()); + server.waitedStart(5000); + + assertTrue(HttpServletServer.factory.get(5678).isAlive()); + + String echo = "hello"; + URL urlService1 = new URL("http://localhost:5678/junit/echo/" + echo); + String responseService1 = response(urlService1); + System.out.println("Received .. " + responseService1); + assertTrue(responseService1.equals(echo)); + + HttpServletServer.factory.destroy(); + assertTrue(HttpServletServer.factory.inventory().size() == 0); + } + + @Test + public void testMultiServiceClass() throws Exception { + System.out.println("-- testMultiServiceClass() --"); + + String randomName = UUID.randomUUID().toString(); + + HttpServletServer server = HttpServletServer.factory.build(randomName, "localhost", 5678, "/", true); + server.addServletClass("/*", RestEchoService.class.getCanonicalName()); + server.addServletClass("/*", RestEndpoints.class.getCanonicalName()); + server.waitedStart(5000); + + assertTrue(HttpServletServer.factory.get(5678).isAlive()); + + String echo = "hello"; + URL urlService1 = new URL("http://localhost:5678/junit/echo/" + echo); + String responseService1 = response(urlService1); + System.out.println("Received .. " + responseService1); + assertTrue(responseService1.equals(echo)); + + URL urlService2 = new URL("http://localhost:5678/junit/endpoints/http/servers"); + String responseService2 = response(urlService2); + System.out.println("Received .. " + responseService2); + assertTrue(responseService2.contains(randomName)); + + HttpServletServer.factory.destroy(); + assertTrue(HttpServletServer.factory.inventory().size() == 0); + } + + /** + * @param url + * @throws IOException + */ + protected String response(URL url) throws IOException { + BufferedReader ioReader = new BufferedReader(new InputStreamReader(url.openStream())); + String response = ""; + String line; + while ((line = ioReader.readLine()) != null) { + response += line; + } + return response; + } + + + +} diff --git a/policy-endpoints/src/test/java/org/openecomp/policy/drools/http/server/test/RestEchoService.java b/policy-endpoints/src/test/java/org/openecomp/policy/drools/http/server/test/RestEchoService.java new file mode 100644 index 00000000..a0320a09 --- /dev/null +++ b/policy-endpoints/src/test/java/org/openecomp/policy/drools/http/server/test/RestEchoService.java @@ -0,0 +1,19 @@ +package org.openecomp.policy.drools.http.server.test; + +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.core.MediaType; + +@Path("/junit/echo") +public class RestEchoService { + + @GET + @Path("{word}") + @Produces(MediaType.TEXT_PLAIN) + public String echo(@PathParam("word") String word) { + return word; + } + +} diff --git a/policy-endpoints/src/test/java/org/openecomp/policy/drools/http/server/test/RestEndpoints.java b/policy-endpoints/src/test/java/org/openecomp/policy/drools/http/server/test/RestEndpoints.java new file mode 100644 index 00000000..a00f2ffd --- /dev/null +++ b/policy-endpoints/src/test/java/org/openecomp/policy/drools/http/server/test/RestEndpoints.java @@ -0,0 +1,25 @@ +package org.openecomp.policy.drools.http.server.test; + +import java.util.List; + +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.Produces; +import javax.ws.rs.core.MediaType; + +import org.openecomp.policy.drools.http.server.HttpServletServer; + +@Path("/junit/endpoints") +public class RestEndpoints { + + @GET + @Path("http/servers") + @Produces(MediaType.TEXT_PLAIN) + public String httpServers() { + List<HttpServletServer> servers = + HttpServletServer.factory.inventory(); + return servers.toString(); + } + + +} diff --git a/policy-endpoints/src/test/java/org/openecomp/policy/drools/http/server/test/RestMockHealthCheck.java b/policy-endpoints/src/test/java/org/openecomp/policy/drools/http/server/test/RestMockHealthCheck.java new file mode 100644 index 00000000..ff1b4980 --- /dev/null +++ b/policy-endpoints/src/test/java/org/openecomp/policy/drools/http/server/test/RestMockHealthCheck.java @@ -0,0 +1,28 @@ +package org.openecomp.policy.drools.http.server.test; + +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.Produces; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.Response.Status; + +@Path("/") +public class RestMockHealthCheck { + + @GET + @Path("pap/test") + @Produces(MediaType.APPLICATION_JSON) + public Response papHealthCheck() { + return Response.status(Status.OK).entity("All Alive").build(); + } + + @GET + @Path("pdp/test") + @Produces(MediaType.APPLICATION_JSON) + public Response pdpHealthCheck() { + return Response.status(Status.INTERNAL_SERVER_ERROR).entity("At least some Dead").build(); + } + + +} diff --git a/policy-healthcheck/pom.xml b/policy-healthcheck/pom.xml new file mode 100644 index 00000000..c279cd1d --- /dev/null +++ b/policy-healthcheck/pom.xml @@ -0,0 +1,157 @@ +<!-- + ============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/xsd/maven-4.0.0.xsd"> + + <modelVersion>4.0.0</modelVersion> + + <parent> + <groupId>org.openecomp.policy.drools-pdp</groupId> + <artifactId>drools-pdp</artifactId> + <version>1.0.0-SNAPSHOT</version> + </parent> + + <artifactId>policy-healthcheck</artifactId> + + <name>policy-healthcheck</name> + <description>Separately loadable module with healthcheck code</description> + + <properties> + <maven.compiler.source>1.8</maven.compiler.source> + <maven.compiler.target>1.8</maven.compiler.target> + </properties> + + <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>org.openecomp.policy.drools-pdp</groupId> + <artifactId>policy-core</artifactId> + <version>1.0.0-SNAPSHOT</version> + </dependency> + <dependency> + <groupId>org.openecomp.policy.drools-pdp</groupId> + <artifactId>policy-endpoints</artifactId> + <version>1.0.0-SNAPSHOT</version> + </dependency> + <dependency> + <groupId>org.openecomp.policy.drools-pdp</groupId> + <artifactId>policy-management</artifactId> + <version>1.0.0-SNAPSHOT</version> + </dependency> + </dependencies> + +</project> diff --git a/policy-healthcheck/src/assembly/assemble_zip.xml b/policy-healthcheck/src/assembly/assemble_zip.xml new file mode 100644 index 00000000..266e1d0a --- /dev/null +++ b/policy-healthcheck/src/assembly/assemble_zip.xml @@ -0,0 +1,85 @@ +<!-- + ============LICENSE_START======================================================= + policy-persistence + ================================================================================ + 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/opt</outputDirectory> + <includes> + <include>policy-healthcheck-${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-healthcheck/src/main/java/org/openecomp/policy/drools/healthcheck/HealthCheck.java b/policy-healthcheck/src/main/java/org/openecomp/policy/drools/healthcheck/HealthCheck.java new file mode 100644 index 00000000..2ed2e075 --- /dev/null +++ b/policy-healthcheck/src/main/java/org/openecomp/policy/drools/healthcheck/HealthCheck.java @@ -0,0 +1,178 @@ +package org.openecomp.policy.drools.healthcheck; + +import java.util.ArrayList; +import java.util.Properties; + +import javax.ws.rs.core.Response; + +import org.openecomp.policy.drools.http.client.HttpClient; +import org.openecomp.policy.drools.http.server.HttpServletServer; +import org.openecomp.policy.drools.persistence.SystemPersistence; +import org.openecomp.policy.drools.properties.Startable; +import org.openecomp.policy.drools.system.PolicyEngine; + +public interface HealthCheck extends Startable { + + public static class Report { + public String name; + public String url; + public boolean healthy; + public int code; + public String message; + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("Report [name="); + builder.append(name); + builder.append(", url="); + builder.append(url); + builder.append(", healthy="); + builder.append(healthy); + builder.append(", code="); + builder.append(code); + builder.append(", message="); + builder.append(message); + builder.append("]"); + return builder.toString(); + } + } + + public static class Reports { + public boolean healthy; + public ArrayList<Report> details = new ArrayList<>(); + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("Reports [healthy="); + builder.append(healthy); + builder.append(", details="); + builder.append(details); + builder.append("]"); + return builder.toString(); + } + } + + public Reports healthCheck(); + + public static final HealthCheck monitor = new HealthCheckMonitor(); +} + +class HealthCheckMonitor implements HealthCheck { + + protected volatile ArrayList<HttpServletServer> servers = new ArrayList<>(); + protected volatile ArrayList<HttpClient> clients = new ArrayList<>(); + protected volatile Properties healthCheckProperties = null; + + public Reports healthCheck() { + Reports reports = new Reports(); + reports.healthy = PolicyEngine.manager.isAlive(); + + HealthCheck.Report engineReport = new Report(); + engineReport.healthy = PolicyEngine.manager.isAlive(); + engineReport.name = "PDP-D"; + engineReport.url = "self"; + engineReport.code = (PolicyEngine.manager.isAlive()) ? 200 : 500; + engineReport.message = (PolicyEngine.manager.isAlive()) ? "alive" : "not alive"; + reports.details.add(engineReport); + + for (HttpClient client : clients) { + HealthCheck.Report report = new Report(); + report.name = client.getName(); + report.url = client.getBaseUrl(); + report.healthy = true; + try { + Response response = client.get(); + report.code = response.getStatus(); + if (report.code != 200) { + report.healthy = false; + reports.healthy = false; + } + + try { + report.message = HttpClient.getBody(response, String.class); + } catch (Exception e) { + e.printStackTrace(); + } + } catch (Exception e) { + report.healthy = false; + reports.healthy = false; + } + reports.details.add(report); + } + return reports; + } + + @Override + public boolean start() throws IllegalStateException { + try { + this.healthCheckProperties = SystemPersistence.manager.getProperties(HealthCheckFeature.CONFIGURATION_PROPERTIES_NAME); + this.servers = HttpServletServer.factory.build(healthCheckProperties); + this.clients = HttpClient.factory.build(healthCheckProperties); + + for (HttpServletServer server : servers) { + try { + server.start(); + } catch (Exception e) { + e.printStackTrace(); + } + } + } catch (Exception e) { + return false; + } + + return true; + } + + @Override + public boolean stop() throws IllegalStateException { + for (HttpServletServer server : servers) { + try { + server.stop(); + } catch (Exception e) { + e.printStackTrace(); + } + } + + for (HttpClient client : clients) { + try { + client.stop(); + } catch (Exception e) { + e.printStackTrace(); + } + } + + return true; + } + + @Override + public void shutdown() throws IllegalStateException { + this.stop(); + } + + @Override + public synchronized boolean isAlive() { + return this.healthCheckProperties != null; + } + + public ArrayList<HttpServletServer> getServers() { + return this.servers; + } + + public ArrayList<HttpClient> getClients() { + return this.clients; + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("HealthCheckMonitor [servers="); + builder.append(servers); + builder.append(", clients="); + builder.append(clients); + builder.append("]"); + return builder.toString(); + } + +} diff --git a/policy-healthcheck/src/main/java/org/openecomp/policy/drools/healthcheck/HealthCheckFeature.java b/policy-healthcheck/src/main/java/org/openecomp/policy/drools/healthcheck/HealthCheckFeature.java new file mode 100644 index 00000000..ce1dd90b --- /dev/null +++ b/policy-healthcheck/src/main/java/org/openecomp/policy/drools/healthcheck/HealthCheckFeature.java @@ -0,0 +1,92 @@ +package org.openecomp.policy.drools.healthcheck; + +import java.util.Properties; + +import org.kie.api.runtime.KieSession; +import org.openecomp.policy.drools.core.FeatureAPI; +import org.openecomp.policy.drools.core.PolicyContainer; +import org.openecomp.policy.drools.core.PolicySession; + +public class HealthCheckFeature implements FeatureAPI { + + public static final String CONFIGURATION_PROPERTIES_NAME = "policy-healthcheck"; + + @Override + public int getSequenceNumber() { + return 2; + } + + @Override + public void globalInit(String[] args, String configDir) { + return; + } + + @Override + public KieSession activatePolicySession(PolicyContainer policyContainer, String name, String kieBaseName) { + return null; + } + + @Override + public void disposeKieSession(PolicySession policySession) { + return; + } + + @Override + public void destroyKieSession(PolicySession policySession) { + return; + } + + @Override + public void beforeStartEngine() throws IllegalStateException { + return; + } + + @Override + public void afterStartEngine() { + try { + HealthCheck.monitor.start(); + } catch (IllegalStateException e) { + e.printStackTrace(); + } + } + + @Override + public void beforeShutdownEngine() { + return; + } + + @Override + public void afterShutdownEngine() { + try { + HealthCheck.monitor.stop(); + } catch (IllegalStateException e) { + e.printStackTrace(); + } + } + + @Override + public void beforeCreateController(String name, Properties properties) { + return; + } + + @Override + public void afterCreateController(String name) { + return; + } + + @Override + public void beforeStartController(String name) { + return; + } + + @Override + public void afterStartController(String name) { + return; + } + + @Override + public boolean isPersistenceEnabled() { + return false; + } + +} diff --git a/policy-healthcheck/src/main/java/org/openecomp/policy/drools/healthcheck/RestHealthCheck.java b/policy-healthcheck/src/main/java/org/openecomp/policy/drools/healthcheck/RestHealthCheck.java new file mode 100644 index 00000000..e37e758a --- /dev/null +++ b/policy-healthcheck/src/main/java/org/openecomp/policy/drools/healthcheck/RestHealthCheck.java @@ -0,0 +1,27 @@ +package org.openecomp.policy.drools.healthcheck; + +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.Produces; +import javax.ws.rs.core.MediaType; + +import org.openecomp.policy.drools.healthcheck.HealthCheck.Reports; + +@Path("/") +public class RestHealthCheck { + + @GET + @Path("{a:healthcheck|test}") + @Produces(MediaType.APPLICATION_JSON) + public Reports healthcheck() { + Reports reports = HealthCheck.monitor.healthCheck(); + return reports; + } + + @GET + @Path("healthcheck/configuration") + @Produces(MediaType.APPLICATION_JSON) + public HealthCheck configuration() { + return HealthCheck.monitor; + } +} diff --git a/policy-healthcheck/src/main/resources/META-INF/services/org.openecomp.policy.drools.core.FeatureAPI b/policy-healthcheck/src/main/resources/META-INF/services/org.openecomp.policy.drools.core.FeatureAPI new file mode 100644 index 00000000..7e307d08 --- /dev/null +++ b/policy-healthcheck/src/main/resources/META-INF/services/org.openecomp.policy.drools.core.FeatureAPI @@ -0,0 +1 @@ +org.openecomp.policy.drools.healthcheck.HealthCheckFeature diff --git a/policy-management/config/policy-engine.properties b/policy-management/config/policy-engine.properties new file mode 100644 index 00000000..41456c27 --- /dev/null +++ b/policy-management/config/policy-engine.properties @@ -0,0 +1,26 @@ +# Policy Engine Configuration + +# Configuration Channel Settings: PDPD_CONFIGURATION + +ueb.source.topics=PDPD_CONFIGURATION +ueb.source.topics.PDPD_CONFIGURATION.servers= +ueb.source.topics.PDPD_CONFIGURATION.apiKey= +ueb.source.topics.PDPD_CONFIGURATION.apiSecret= +ueb.source.topics.PDPD_CONFIGURATION.consumerGroup= +ueb.source.topics.PDPD_CONFIGURATION.consumerInstance= +ueb.source.topics.PDPD_CONFIGURATION.managed=false + +ueb.sink.topics=PDPD_CONFIGURATION +ueb.sink.topics.PDPD_CONFIGURATION.servers= +ueb.sink.topics.PDPD_CONFIGURATION.apiKey= +ueb.sink.topics.PDPD_CONFIGURATION.apiSecret= +ueb.sink.topics.PDPD_CONFIGURATION.partitionKey= +ueb.sink.topics.PDPD_CONFIGURATION.managed=false + +http.server.services=CONFIG +http.server.services.CONFIG.host=localhost +http.server.services.CONFIG.port=9696 +http.server.services.CONFIG.userName=x +http.server.services.CONFIG.password=y +http.server.services.CONFIG.restPackages=org.openecomp.policy.drools.server.restful +http.server.services.CONFIG.managed=false diff --git a/policy-management/config/policyLogger.properties b/policy-management/config/policyLogger.properties new file mode 100644 index 00000000..f8f31d8f --- /dev/null +++ b/policy-management/config/policyLogger.properties @@ -0,0 +1,44 @@ +### +# ============LICENSE_START======================================================= +# policy-management +# ================================================================================ +# 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========================================================= +### + +################################### Set concurrentHashMap and timer info ####################### +#Timer initial delay and the delay between in milliseconds before task is to be execute. +timer.delay.time=1000 +#Timer scheduleAtFixedRate period - time in milliseconds between successive task executions. +check.interval= 30000 +#Longest time an event info can be stored in the concurrentHashMap for logging - in seconds. +event.expired.time=86400 +#Size of the concurrentHashMap which stores the event starting time, etc - when its size reaches this limit, the Timer gets executed +#to remove all expired records from this concurrentHashMap. +concurrentHashMap.limit=5000 +#Size of the concurrentHashMap - when its size drops to this point, stop the Timer +stop.check.point=2500 +################################### Set logging format ############################################# +# set EELF for EELF logging format, set LOG4J for using log4j, set SYSTEMOUT for using system.out.println +logger.type=EELF +#################################### Set level for EELF or SYSTEMOUT logging ################################## +# Set level for debug file. Set DEBUG to enable .info, .warn and .debug; set INFO for enable .info and .warn; set OFF to disable all +debugLogger.level=INFO +# Set level for metrics file. Set OFF to disable; set ON to enable +metricsLogger.level=ON +# Set level for error file. Set OFF to disable; set ON to enable +error.level=ON +# Set level for audit file. Set OFF to disable; set ON to enable +audit.level=ON diff --git a/policy-management/pom.xml b/policy-management/pom.xml new file mode 100644 index 00000000..2983f1f4 --- /dev/null +++ b/policy-management/pom.xml @@ -0,0 +1,259 @@ +<?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> + + <parent> + <groupId>org.openecomp.policy.drools-pdp</groupId> + <artifactId>drools-pdp</artifactId> + <version>1.0.0-SNAPSHOT</version> + </parent> + + <artifactId>policy-management</artifactId> + + <name>policy-management</name> + <description>Policy Management</description> + + <properties> + <maven.compiler.source>1.8</maven.compiler.source> + <maven.compiler.target>1.8</maven.compiler.target> + <jetty.version>9.3.8.v20160314</jetty.version> + <jersey.version>2.22.2</jersey.version> + <jackson.version>2.8.4</jackson.version> + <gson.version>2.8.0</gson.version> + </properties> + + + <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>org.openecomp.policy.drools-pdp</groupId> + <artifactId>policy-core</artifactId> + <version>1.0.0-SNAPSHOT</version> + </dependency> + + <dependency> + <groupId>org.openecomp.policy.drools-pdp</groupId> + <artifactId>policy-endpoints</artifactId> + <version>1.0.0-SNAPSHOT</version> + </dependency> + + <dependency> + <groupId>org.eclipse.jetty</groupId> + <artifactId>jetty-server</artifactId> + <version>${jetty.version}</version> + </dependency> + + <dependency> + <groupId>org.eclipse.jetty</groupId> + <artifactId>jetty-servlet</artifactId> + <version>${jetty.version}</version> + </dependency> + + <dependency> + <groupId>org.glassfish.jersey.core</groupId> + <artifactId>jersey-server</artifactId> + <version>${jersey.version}</version> + </dependency> + + <dependency> + <groupId>org.glassfish.jersey.containers</groupId> + <artifactId>jersey-container-servlet-core</artifactId> + <version>${jersey.version}</version> + </dependency> + + <dependency> + <groupId>org.glassfish.jersey.media</groupId> + <artifactId>jersey-media-json-jackson</artifactId> + <version>${jersey.version}</version> + </dependency> + + <dependency> + <groupId>org.glassfish.jersey.containers</groupId> + <artifactId>jersey-container-jetty-http</artifactId> + <version>${jersey.version}</version> + <exclusions> + <exclusion> + <groupId>org.eclipse.jetty</groupId> + <artifactId>jetty-util</artifactId> + </exclusion> + </exclusions> + </dependency> + + <dependency> + <groupId>com.fasterxml.jackson.core</groupId> + <artifactId>jackson-databind</artifactId> + <version>${jackson.version}</version> + </dependency> + + <dependency> + <groupId>com.fasterxml.jackson.datatype</groupId> + <artifactId>jackson-datatype-jsr310</artifactId> + <version>${jackson.version}</version> + </dependency> + + <dependency> + <groupId>com.fasterxml.jackson.core</groupId> + <artifactId>jackson-annotations</artifactId> + <version>${jackson.version}</version> + </dependency> + + <dependency> + <groupId>com.google.code.gson</groupId> + <artifactId>gson</artifactId> + <version>${gson.version}</version> + </dependency> + + <dependency> + <groupId>com.fatboyindustrial.gson-javatime-serialisers</groupId> + <artifactId>gson-javatime-serialisers</artifactId> + <version>1.1.1</version> + </dependency> + + <dependency> + <groupId>org.apache.commons</groupId> + <artifactId>commons-collections4</artifactId> + <version>4.1</version> + </dependency> + + <!-- This entry is necessary to support import "org.apache.commons.lang3.time.DateUtils" + reference in StandbyStateManagementTest.java --> + <dependency> + <groupId>org.apache.commons</groupId> + <artifactId>commons-lang3</artifactId> + <version>3.4</version> + </dependency> + + <dependency> + <groupId>log4j</groupId> + <artifactId>log4j</artifactId> + <version>1.2.17</version> + </dependency> + + <dependency> + <groupId>junit</groupId> + <artifactId>junit</artifactId> + <version>4.11</version> + <scope>test</scope> + </dependency> + + </dependencies> + +</project> diff --git a/policy-management/src/assembly/assemble_zip.xml b/policy-management/src/assembly/assemble_zip.xml new file mode 100644 index 00000000..85a1dbfa --- /dev/null +++ b/policy-management/src/assembly/assemble_zip.xml @@ -0,0 +1,85 @@ +<!-- + ============LICENSE_START======================================================= + policy-management + ================================================================================ + 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-management-${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-management/src/main/java/org/openecomp/policy/drools/controller/DroolsController.java b/policy-management/src/main/java/org/openecomp/policy/drools/controller/DroolsController.java new file mode 100644 index 00000000..72f8e0b2 --- /dev/null +++ b/policy-management/src/main/java/org/openecomp/policy/drools/controller/DroolsController.java @@ -0,0 +1,170 @@ +/*- + * ============LICENSE_START======================================================= + * policy-management + * ================================================================================ + * 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.controller; + +import java.util.List; + +import org.openecomp.policy.drools.event.comm.TopicSink; +import org.openecomp.policy.drools.properties.Lockable; +import org.openecomp.policy.drools.properties.Startable; +import org.openecomp.policy.drools.protocol.coders.TopicCoderFilterConfiguration; + +/** + * Drools Controller is the abstractions that wraps the + * drools layer (policy-core) + */ +public interface DroolsController extends Startable, Lockable { + + /** + * No Group ID identifier + */ + public static final String NO_GROUP_ID = "NO-GROUP-ID"; + + /** + * No Artifact ID identifier + */ + public static final String NO_ARTIFACT_ID = "NO-ARTIFACT-ID"; + + /** + * No version identifier + */ + public static final String NO_VERSION = "NO-VERSION"; + + /** + * get group id + * @return group id + */ + public String getGroupId(); + + /** + * get artifact id + * @return artifact id + */ + public String getArtifactId(); + + /** + * get version + * @return version + */ + public String getVersion(); + + + /** + * return the policy session names + * + * @return policy session + */ + public List<String> getSessionNames(); + + /** + * offers an event to this controller for processing + * + * @param topic topic associated with the event + * @param event the event + * + * @return true if the operation was successful + */ + public boolean offer(String topic, String event); + + /** + * delivers "event" to "sink" + * + * @param sink destination + * @param event + * @return true if successful, false if a failure has occurred. + * @throws IllegalArgumentException when invalid or insufficient + * properties are provided + * @throws IllegalStateException when the engine is in a state where + * this operation is not permitted (ie. locked or stopped). + * @throws UnsupportedOperationException when the engine cannot deliver due + * to the functionality missing (ie. communication infrastructure + * not supported. + */ + public boolean deliver(TopicSink sink, Object event) + throws IllegalArgumentException, IllegalStateException, + UnsupportedOperationException; + + /** + * + * @return the most recent received events + */ + public Object[] getRecentSourceEvents(); + + /** + * + * @return the most recent delivered events + */ + public String[] getRecentSinkEvents(); + + /** + * Supports this encoder? + * + * @param encodedObject + * @return + */ + public boolean ownsCoder(Class<? extends Object> coderClass, int modelHash) throws IllegalStateException; + + /** + * fetches a class from the model + * + * @param className the class to fetch + * @return the actual class object, or null if not found + */ + public Class<?> fetchModelClass(String className) throws IllegalArgumentException; + + /** + * is this controller Smart? + */ + public boolean isBrained(); + + /** + * update the new version of the maven jar rules file + * + * @param newGroupId - new group id + * @param newArtifactId - new artifact id + * @param newVersion - new version + * @param decoderConfigurations - decoder configurations + * @param encoderConfigurations - encoder configurations + * + * @throws Exception from within drools libraries + * @throws LinkageError from within drools libraries + * @throws ArgumentException bad parameter passed in + */ + public void updateToVersion(String newGroupId, String newArtifactId, String newVersion, + List<TopicCoderFilterConfiguration> decoderConfigurations, + List<TopicCoderFilterConfiguration> encoderConfigurations) + throws IllegalArgumentException, LinkageError, Exception; + + + /** + * halts and permanently releases all resources + * @throws IllegalStateException + */ + public void halt() throws IllegalStateException; + + /** + * Factory to track and manage drools controllers + */ + public static final DroolsControllerFactory factory = + new IndexedDroolsControllerFactory(); + + +} diff --git a/policy-management/src/main/java/org/openecomp/policy/drools/controller/DroolsControllerFactory.java b/policy-management/src/main/java/org/openecomp/policy/drools/controller/DroolsControllerFactory.java new file mode 100644 index 00000000..d94e773c --- /dev/null +++ b/policy-management/src/main/java/org/openecomp/policy/drools/controller/DroolsControllerFactory.java @@ -0,0 +1,540 @@ +/*- + * ============LICENSE_START======================================================= + * policy-management + * ================================================================================ + * 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.controller; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Properties; + +import org.openecomp.policy.drools.controller.internal.MavenDroolsController; +import org.openecomp.policy.drools.controller.internal.NullDroolsController; +import org.openecomp.policy.drools.event.comm.Topic; +import org.openecomp.policy.drools.event.comm.Topic.CommInfrastructure; +import org.openecomp.policy.common.logging.flexlogger.FlexLogger; +import org.openecomp.policy.common.logging.flexlogger.Logger; +import org.openecomp.policy.drools.event.comm.TopicSource; +import org.openecomp.policy.drools.event.comm.TopicSink; +import org.openecomp.policy.drools.properties.PolicyProperties; +import org.openecomp.policy.drools.protocol.coders.JsonProtocolFilter; +import org.openecomp.policy.drools.protocol.coders.TopicCoderFilterConfiguration; +import org.openecomp.policy.drools.protocol.coders.TopicCoderFilterConfiguration.CustomGsonCoder; +import org.openecomp.policy.drools.protocol.coders.TopicCoderFilterConfiguration.CustomJacksonCoder; +import org.openecomp.policy.drools.protocol.coders.TopicCoderFilterConfiguration.PotentialCoderFilter; +import org.openecomp.policy.drools.utils.Pair; + +/** + * Drools Controller Factory to manage controller creation, destruction, + * and retrieval for management interfaces + */ +public interface DroolsControllerFactory { + + /** + * Constructs a Drools Controller based on properties + * + * @param properties properties containing initialization parameters + * @param eventSources list of event sources + * @param eventSinks list of event sinks + * + * @return the instantiated Drools Controller + * @throws IllegalArgumentException with invalid parameters + * @throws LinkageError Failure to link rules and models in Drools Libraries + * @throws Exception Exception from Drools Libraries + */ + public DroolsController build(Properties properties, + List<? extends TopicSource> eventSources, + List<? extends TopicSink> eventSinks) + throws IllegalArgumentException, LinkageError, Exception; + + /** + * Explicit construction of a Drools Controller + * + * @param groupId maven group id of drools artifact + * @param artifactId maven artifact id of drools artifact + * @param version maven version id of drools artifact + * @param decoderConfigurations list of decoder configurations + * @param encoderConfigurations list of encoder configurations + * + * @return the instantiated Drools Controller + * @throws IllegalArgumentException with invalid parameters + * @throws LinkageError Failure to link rules and models in Drools Libraries + * @throws Exception Exception from Drools Libraries + */ + public DroolsController build(String groupId, + String artifactId, + String version, + List<TopicCoderFilterConfiguration> decoderConfigurations, + List<TopicCoderFilterConfiguration> encoderConfigurations) + throws IllegalArgumentException, LinkageError, Exception; + + /** + * Releases the Drools Controller from operation + * + * @param controller the Drools Controller to shut down + */ + public void shutdown(DroolsController controller); + + /** + * Disables all Drools Controllers from operation + */ + public void shutdown(); + + /** + * Destroys and releases resources for a Drools Controller + * + * @param controller the Drools Controller to destroy + */ + public void destroy(DroolsController controller); + + /** + * Destroys all Drools Controllers + */ + public void destroy(); + + /** + * Gets the Drools Controller associated with the maven group + * and artifact id + * + * @param groupId maven group id of drools artifact + * @param artifactId maven artifact id of drools artifact + * @param version maven version id of drools artifact + * + * @return the Drools Controller + * @throws IllegalArgumentException with invalid parameters + */ + public DroolsController get(String groupId, + String artifactId, + String version) + throws IllegalArgumentException; + + /** + * returns the current inventory of Drools Controllers + * + * @return a list of Drools Controllers + */ + public List<DroolsController> inventory(); +} + +/* ---------------- implementation -----------------*/ + +/** + * Factory of Drools Controllers indexed by the Maven coordinates + */ +class IndexedDroolsControllerFactory implements DroolsControllerFactory { + + /** + * logger + */ + private static Logger logger = FlexLogger.getLogger(MavenDroolsController.class); + + /** + * Policy Controller Name Index + */ + protected HashMap<String, DroolsController> droolsControllers = + new HashMap<String, DroolsController>(); + + /** + * Null Drools Controller + */ + protected NullDroolsController nullDroolsController = new NullDroolsController(); + + + public IndexedDroolsControllerFactory() { + + /* Add a NULL controller which will always be present in the hash */ + + DroolsController controller = new NullDroolsController(); + String controllerId = controller.getGroupId() + ":" + controller.getArtifactId(); + + synchronized(this) { + droolsControllers.put(controllerId, controller); + } + } + + /** + * {@inheritDoc} + */ + @Override + public DroolsController build(Properties properties, + List<? extends TopicSource> eventSources, + List<? extends TopicSink> eventSinks) + throws IllegalArgumentException, LinkageError, Exception { + + String groupId = properties.getProperty(PolicyProperties.RULES_GROUPID); + if (groupId == null || groupId.isEmpty()) + groupId = DroolsController.NO_GROUP_ID; + + String artifactId = properties.getProperty(PolicyProperties.RULES_ARTIFACTID); + if (artifactId == null || artifactId.isEmpty()) + artifactId = DroolsController.NO_ARTIFACT_ID; + + String version = properties.getProperty(PolicyProperties.RULES_VERSION); + if (version == null || version.isEmpty()) + version = DroolsController.NO_VERSION; + + List<TopicCoderFilterConfiguration> + topics2DecodedClasses2Filters = codersAndFilters(properties, eventSources); + + List<TopicCoderFilterConfiguration> + topics2EncodedClasses2Filters = codersAndFilters(properties, eventSinks); + + return this.build(groupId, artifactId, version, + topics2DecodedClasses2Filters, + topics2EncodedClasses2Filters); + } + + /** + * find out decoder classes and filters + * + * @param properties properties with information about decoders + * @param topicEntities topic sources + * @return list of topics, each with associated decoder classes, each + * with a list of associated filters + * @throws IllegalArgumentException invalid input data + */ + protected List<TopicCoderFilterConfiguration> codersAndFilters + (Properties properties, List<? extends Topic> topicEntities) + throws IllegalArgumentException { + + String PROPERTY_TOPIC_ENTITY_PREFIX; + + List<TopicCoderFilterConfiguration> + topics2DecodedClasses2Filters = + new ArrayList<TopicCoderFilterConfiguration>(); + + if (topicEntities.isEmpty()) + return topics2DecodedClasses2Filters; + + for (Topic topic: topicEntities) { + + /* source or sink ? ueb or dmaap? */ + boolean isSource = (topic instanceof TopicSource); + CommInfrastructure commInfra = topic.getTopicCommInfrastructure(); + if (commInfra == CommInfrastructure.UEB) { + if (isSource) { + PROPERTY_TOPIC_ENTITY_PREFIX = PolicyProperties.PROPERTY_UEB_SOURCE_TOPICS + "."; + } else { + PROPERTY_TOPIC_ENTITY_PREFIX = PolicyProperties.PROPERTY_UEB_SINK_TOPICS + "."; + } + } else if (commInfra == CommInfrastructure.DMAAP) { + if (isSource) { + PROPERTY_TOPIC_ENTITY_PREFIX = PolicyProperties.PROPERTY_DMAAP_SOURCE_TOPICS + "."; + } else { + PROPERTY_TOPIC_ENTITY_PREFIX = PolicyProperties.PROPERTY_DMAAP_SINK_TOPICS + "."; + } + } else { + throw new IllegalArgumentException("Invalid Communication Infrastructure: " + commInfra); + } + + // 1. first the topic + + String aTopic = topic.getTopic(); + + // 2. check if there is a custom decoder for this topic that the user prefers to use + // instead of the ones provided in the platform + + String customGson = properties.getProperty + (PROPERTY_TOPIC_ENTITY_PREFIX + + aTopic + + PolicyProperties.PROPERTY_TOPIC_EVENTS_CUSTOM_MODEL_CODER_GSON_SUFFIX); + + CustomGsonCoder customGsonCoder = null; + if (customGson != null && !customGson.isEmpty()) { + try { + customGsonCoder = new CustomGsonCoder(customGson); + } catch (IllegalArgumentException e) { + e.printStackTrace(); + } + } + + String customJackson = properties.getProperty + (PROPERTY_TOPIC_ENTITY_PREFIX + + aTopic + + PolicyProperties.PROPERTY_TOPIC_EVENTS_CUSTOM_MODEL_CODER_JACKSON_SUFFIX); + + CustomJacksonCoder customJacksonCoder = null; + if (customJackson != null && !customJackson.isEmpty()) { + try { + customJacksonCoder = new CustomJacksonCoder(customJackson); + } catch (IllegalArgumentException e) { + e.printStackTrace(); + } + } + + // 3. second the list of classes associated with each topic + + String eventClasses = + properties.getProperty(PROPERTY_TOPIC_ENTITY_PREFIX + aTopic + PolicyProperties.PROPERTY_TOPIC_EVENTS_SUFFIX); + + if (eventClasses == null || eventClasses.isEmpty()) { + // TODO warn + continue; + } + + List<PotentialCoderFilter> classes2Filters = new ArrayList<PotentialCoderFilter>(); + + List<String> aTopicClasses = + new ArrayList<String>(Arrays.asList(eventClasses.split("\\s*,\\s*"))); + + for (String aClass: aTopicClasses) { + + + // 4. third, for each coder class, get the list of field filters + + String filter = properties.getProperty + (PROPERTY_TOPIC_ENTITY_PREFIX + + aTopic + + PolicyProperties.PROPERTY_TOPIC_EVENTS_SUFFIX + + "." + aClass + + PolicyProperties.PROPERTY_TOPIC_EVENTS_FILTER_SUFFIX); + + List<Pair<String,String>> filters = new ArrayList<Pair<String,String>>(); + + if (filter == null || filter.isEmpty()) { + // 4. topic -> class -> with no filters + + JsonProtocolFilter protocolFilter = JsonProtocolFilter.fromRawFilters(filters); + PotentialCoderFilter class2Filters = + new PotentialCoderFilter(aClass, protocolFilter); + classes2Filters.add(class2Filters); + continue; + } + + // There are filters associated with the applicability of + // this class for decoding. + List<String> listOfFilters = + new ArrayList<String>(Arrays.asList(filter.split("\\s*,\\s*"))); + + for (String nameValue: listOfFilters) { + String fieldName; + String regexValue; + + String[] nameValueSplit = nameValue.split("\\s*=\\s*"); + if (nameValueSplit.length <= 0 || nameValueSplit.length > 2) { + // TODO warn + // skip + continue; + } + + if (nameValueSplit.length == 2) { + fieldName = nameValueSplit[0]; + regexValue = nameValueSplit[1]; + } else if (nameValueSplit.length == 1) { + fieldName = nameValueSplit[0]; + regexValue = null; + } else { + // unreachable + continue; + } + + filters.add(new Pair<String,String>(fieldName, regexValue)); + } + + JsonProtocolFilter protocolFilter = JsonProtocolFilter.fromRawFilters(filters); + PotentialCoderFilter class2Filters = + new PotentialCoderFilter(aClass, protocolFilter); + classes2Filters.add(class2Filters); + } + + TopicCoderFilterConfiguration topic2Classes2Filters = + new TopicCoderFilterConfiguration(aTopic,classes2Filters, customGsonCoder, customJacksonCoder); + topics2DecodedClasses2Filters.add(topic2Classes2Filters); + } + + return topics2DecodedClasses2Filters; + } + + /** + * {@inheritDoc} + * @param decoderConfiguration + */ + @Override + public DroolsController build(String newGroupId, + String newArtifactId, + String newVersion, + List<TopicCoderFilterConfiguration> decoderConfigurations, + List<TopicCoderFilterConfiguration> encoderConfigurations) + throws IllegalArgumentException, LinkageError, Exception { + + if (newGroupId == null || newArtifactId == null || newVersion == null || + newGroupId.isEmpty() || newArtifactId.isEmpty() || newVersion.isEmpty()) { + throw new IllegalArgumentException("Missing maven coordinates: " + + newGroupId + ":" + newArtifactId + ":" + + newVersion); + } + + String controllerId = newGroupId + ":" + newArtifactId; + DroolsController controllerCopy = null; + synchronized (this) { + /* + * The Null Drools Controller for no maven coordinates is always here + * so when no coordinates present, this is the return point + * + * assert (controllerCopy instanceof NullDroolsController) + */ + if (droolsControllers.containsKey(controllerId)) { + controllerCopy = droolsControllers.get(controllerId); + if (controllerCopy.getVersion().equalsIgnoreCase(newVersion)) { + return controllerCopy; + } + } + } + + if (controllerCopy != null) { + /* + * a controller keyed by group id + artifact id exists + * but with different version => version upgrade/downgrade + */ + + controllerCopy.updateToVersion(newGroupId, newArtifactId, newVersion, + decoderConfigurations, encoderConfigurations); + + return controllerCopy; + } + + /* new drools controller */ + + DroolsController controller = new MavenDroolsController + (newGroupId, newArtifactId, newVersion, + decoderConfigurations, + encoderConfigurations); + + synchronized(this) { + droolsControllers.put(controllerId, controller); + } + + return controller; + } + + /** + * {@inheritDoc} + */ + @Override + public void destroy(DroolsController controller) throws IllegalArgumentException { + unmanage(controller); + controller.halt(); + } + + /** + * {@inheritDoc} + */ + @Override + public void destroy() { + List<DroolsController> controllers = this.inventory(); + for (DroolsController controller: controllers) { + controller.halt(); + } + + synchronized(this) { + this.droolsControllers.clear(); + } + } + + /** + * unmanage the drools controller + * + * @param controller + * @return + * @throws IllegalArgumentException + */ + protected void unmanage(DroolsController controller) throws IllegalArgumentException { + if (controller == null) { + throw new IllegalArgumentException("No controller provided"); + } + + if (!controller.isBrained()) { + logger.info("Drools Controller is NOT OPERATIONAL - nothing to destroy"); + return; + } + + String controllerId = controller.getGroupId() + ":" + controller.getArtifactId(); + synchronized(this) { + if (!this.droolsControllers.containsKey(controllerId)) { + return; + } + + droolsControllers.remove(controllerId); + } + } + + /** + * {@inheritDoc} + */ + @Override + public void shutdown(DroolsController controller) throws IllegalArgumentException { + this.unmanage(controller); + controller.shutdown(); + } + + /** + * {@inheritDoc} + */ + @Override + public void shutdown() { + List<DroolsController> controllers = this.inventory(); + for (DroolsController controller: controllers) { + controller.shutdown(); + } + + synchronized(this) { + this.droolsControllers.clear(); + } + } + + /** + * {@inheritDoc} + */ + @Override + public DroolsController get(String groupId, + String artifactId, + String version) + throws IllegalArgumentException, IllegalStateException { + + if (groupId == null || artifactId == null || + groupId.isEmpty() || artifactId.isEmpty()) { + throw new IllegalArgumentException("Missing maven coordinates: " + + groupId + ":" + artifactId); + } + + String controllerId = groupId + ":" + artifactId; + + synchronized(this) { + if (this.droolsControllers.containsKey(controllerId)) { + return droolsControllers.get(controllerId); + } else { + throw new IllegalStateException("DroolController for " + + controllerId + " not found"); + } + } + } + + /** + * {@inheritDoc} + */ + @Override + public List<DroolsController> inventory() { + List<DroolsController> controllers = + new ArrayList<DroolsController>(this.droolsControllers.values()); + return controllers; + } + +} 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 new file mode 100644 index 00000000..2c5708d3 --- /dev/null +++ b/policy-management/src/main/java/org/openecomp/policy/drools/controller/internal/MavenDroolsController.java @@ -0,0 +1,718 @@ +/*- + * ============LICENSE_START======================================================= + * policy-management + * ================================================================================ + * 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.controller.internal; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.commons.collections4.queue.CircularFifoQueue; + +import org.openecomp.policy.common.logging.eelf.MessageCodes; +import org.openecomp.policy.common.logging.flexlogger.FlexLogger; +import org.openecomp.policy.common.logging.flexlogger.Logger; +import org.openecomp.policy.drools.controller.DroolsController; +import org.openecomp.policy.drools.core.PolicyContainer; +import org.openecomp.policy.drools.core.PolicySession; +import org.openecomp.policy.drools.core.jmx.PdpJmx; +import org.openecomp.policy.drools.event.comm.TopicSink; +import org.openecomp.policy.drools.protocol.coders.EventProtocolCoder; +import org.openecomp.policy.drools.protocol.coders.JsonProtocolFilter; +import org.openecomp.policy.drools.protocol.coders.TopicCoderFilterConfiguration; +import org.openecomp.policy.drools.protocol.coders.TopicCoderFilterConfiguration.CustomGsonCoder; +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; + +/** + * Maven-based Drools Controller that interacts with the + * policy-core PolicyContainer and PolicySession to manage + * Drools containers instantiated using Maven. + */ +public class MavenDroolsController implements DroolsController { + + /** + * logger + */ + private static Logger logger = FlexLogger.getLogger(MavenDroolsController.class); + + /** + * Policy Container, the access object to the policy-core layer + */ + @JsonIgnore + protected final PolicyContainer policyContainer; + + /** + * alive status of this drools controller, + * reflects invocation of start()/stop() only + */ + protected volatile boolean alive = false; + + /** + * locked status of this drools controller, + * reflects if i/o drools related operations are permitted, + * more specifically: offer() and deliver(). + * It does not affect the ability to start and stop + * underlying drools infrastructure + */ + protected volatile boolean locked = false; + + /** + * list of topics, each with associated decoder classes, each + * with a list of associated filters. + */ + protected List<TopicCoderFilterConfiguration> decoderConfigurations; + + /** + * list of topics, each with associated encoder classes, each + * with a list of associated filters. + */ + protected List<TopicCoderFilterConfiguration> encoderConfigurations; + + /** + * recent source events processed + */ + protected final CircularFifoQueue<Object> recentSourceEvents = new CircularFifoQueue<Object>(10); + + /** + * recent sink events processed + */ + protected final CircularFifoQueue<String> recentSinkEvents = new CircularFifoQueue<String>(10); + + /** + * original Drools Model/Rules classloader hash + */ + protected int modelClassLoaderHash; + + /** + * Expanded version of the constructor + * + * @param groupId maven group id + * @param artifactId maven artifact id + * @param version maven version + * @param decoderConfiguration list of topic -> decoders -> filters mapping + * @param encoderConfiguration list of topic -> encoders -> filters mapping + * + * @throws IllegalArgumentException invalid arguments passed in + */ + public MavenDroolsController(String groupId, + String artifactId, + String version, + List<TopicCoderFilterConfiguration> decoderConfigurations, + List<TopicCoderFilterConfiguration> encoderConfigurations) + throws IllegalArgumentException { + + if (logger.isInfoEnabled()) + logger.info("DROOLS CONTROLLER: instantiation " + this + + " -> {" + groupId + ":" + artifactId + ":" + version + "}"); + + if (groupId == null || artifactId == null || version == null || + groupId.isEmpty() || artifactId.isEmpty() || version.isEmpty()) { + throw new IllegalArgumentException("Missing maven coordinates: " + + groupId + ":" + artifactId + ":" + + version); + } + + this.policyContainer= new PolicyContainer(groupId, artifactId, version); + this.init(decoderConfigurations, encoderConfigurations); + + if (logger.isInfoEnabled()) + logger.info("DROOLS CONTROLLER: instantiation completed " + this); + } + + /** + * init encoding/decoding configuration + * @param decoderConfiguration list of topic -> decoders -> filters mapping + * @param encoderConfiguration list of topic -> encoders -> filters mapping + */ + protected void init(List<TopicCoderFilterConfiguration> decoderConfigurations, + List<TopicCoderFilterConfiguration> encoderConfigurations) { + + this.decoderConfigurations = decoderConfigurations; + this.encoderConfigurations = encoderConfigurations; + + this.initCoders(decoderConfigurations, true); + this.initCoders(encoderConfigurations, false); + + this.modelClassLoaderHash = this.policyContainer.getClassLoader().hashCode(); + } + + /** + * {@inheritDoc} + */ + @Override + public void updateToVersion(String newGroupId, String newArtifactId, String newVersion, + List<TopicCoderFilterConfiguration> decoderConfigurations, + List<TopicCoderFilterConfiguration> encoderConfigurations) + throws IllegalArgumentException, LinkageError, Exception { + + if (logger.isInfoEnabled()) + logger.info("UPDATE-TO-VERSION: " + this + " -> {" + newGroupId + ":" + newArtifactId + ":" + newVersion + "}"); + + if (newGroupId == null || newArtifactId == null || newVersion == null || + newGroupId.isEmpty() || newArtifactId.isEmpty() || newVersion.isEmpty()) { + throw new IllegalArgumentException("Missing maven coordinates: " + + newGroupId + ":" + newArtifactId + ":" + + newVersion); + } + + if (newGroupId.equalsIgnoreCase(DroolsController.NO_GROUP_ID) || + newArtifactId.equalsIgnoreCase(DroolsController.NO_ARTIFACT_ID) || + newVersion.equalsIgnoreCase(DroolsController.NO_VERSION)) { + throw new IllegalArgumentException("BRAINLESS maven coordinates provided: " + + newGroupId + ":" + newArtifactId + ":" + + newVersion); + } + + if (newGroupId.equalsIgnoreCase(this.getGroupId()) && + newArtifactId.equalsIgnoreCase(this.getArtifactId()) && + newVersion.equalsIgnoreCase(this.getVersion())) { + logger.warn("Al in the right version: " + newGroupId + ":" + + newArtifactId + ":" + newVersion + " vs. " + this); + return; + } + + if (!newGroupId.equalsIgnoreCase(this.getGroupId()) || + !newArtifactId.equalsIgnoreCase(this.getArtifactId())) { + throw new IllegalArgumentException("Group ID and Artifact ID maven coordinates must be identical for the upgrade: " + + newGroupId + ":" + newArtifactId + ":" + + newVersion + " vs. " + this); + } + + /* upgrade */ + String messages = this.policyContainer.updateToVersion(newVersion); + if (logger.isWarnEnabled()) + logger.warn(this + "UPGRADE results: " + messages); + + /* + * If all sucessful (can load new container), now we can remove all coders from previous sessions + */ + this.removeCoders(); + + /* + * add the new coders + */ + this.init(decoderConfigurations, encoderConfigurations); + + if (logger.isInfoEnabled()) + logger.info("UPDATE-TO-VERSION: completed " + this); + } + + /** + * initialize decoders for all the topics supported by this controller + * Note this is critical to be done after the Policy Container is + * instantiated to be able to fetch the corresponding classes. + * + * @param decoderConfiguration list of topic -> decoders -> filters mapping + */ + protected void initCoders(List<TopicCoderFilterConfiguration> coderConfigurations, + boolean decoder) + throws IllegalArgumentException { + + if (logger.isInfoEnabled()) + logger.info("INIT-CODERS: " + this); + + if (coderConfigurations == null) { + return; + } + + + for (TopicCoderFilterConfiguration coderConfig: coderConfigurations) { + String topic = coderConfig.getTopic(); + + CustomGsonCoder customGsonCoder = coderConfig.getCustomGsonCoder(); + if (coderConfig.getCustomGsonCoder() != null && + coderConfig.getCustomGsonCoder().getClassContainer() != null && + !coderConfig.getCustomGsonCoder().getClassContainer().isEmpty()) { + + String customGsonCoderClass = coderConfig.getCustomGsonCoder().getClassContainer(); + if (!ReflectionUtil.isClass(this.policyContainer.getClassLoader(), + customGsonCoderClass)) { + logger.error(customGsonCoderClass + " cannot be retrieved"); + throw new IllegalArgumentException(customGsonCoderClass + " cannot be retrieved"); + } else { + if (logger.isInfoEnabled()) + logger.info("CLASS FETCHED " + customGsonCoderClass); + } + } + + CustomJacksonCoder customJacksonCoder = coderConfig.getCustomJacksonCoder(); + if (coderConfig.getCustomJacksonCoder() != null && + coderConfig.getCustomJacksonCoder().getClassContainer() != null && + !coderConfig.getCustomJacksonCoder().getClassContainer().isEmpty()) { + + String customJacksonCoderClass = coderConfig.getCustomJacksonCoder().getClassContainer(); + if (!ReflectionUtil.isClass(this.policyContainer.getClassLoader(), + customJacksonCoderClass)) { + logger.error(customJacksonCoderClass + " cannot be retrieved"); + throw new IllegalArgumentException(customJacksonCoderClass + " cannot be retrieved"); + } else { + if (logger.isInfoEnabled()) + logger.info("CLASS FETCHED " + customJacksonCoderClass); + } + } + + List<PotentialCoderFilter> coderFilters = coderConfig.getCoderFilters(); + if (coderFilters == null || coderFilters.isEmpty()) { + continue; + } + + for (PotentialCoderFilter coderFilter : coderFilters) { + String potentialCodedClass = coderFilter.getCodedClass(); + JsonProtocolFilter protocolFilter = coderFilter.getFilter(); + + if (!ReflectionUtil.isClass(this.policyContainer.getClassLoader(), + potentialCodedClass)) { + logger.error(potentialCodedClass + " cannot be retrieved"); + throw new IllegalArgumentException(potentialCodedClass + " cannot be retrieved"); + } else { + if (logger.isInfoEnabled()) + logger.info("CLASS FETCHED " + potentialCodedClass); + } + + if (decoder) + EventProtocolCoder.manager.addDecoder(this.getGroupId(), this.getArtifactId(), + topic, potentialCodedClass, protocolFilter, + customGsonCoder, + customJacksonCoder, + this.policyContainer.getClassLoader().hashCode()); + else + EventProtocolCoder.manager.addEncoder(this.getGroupId(), this.getArtifactId(), + topic, potentialCodedClass, protocolFilter, + customGsonCoder, + customJacksonCoder, + this.policyContainer.getClassLoader().hashCode()); + } + } + } + + + /** + * remove decoders. + */ + protected void removeDecoders() + throws IllegalArgumentException { + if (logger.isInfoEnabled()) + logger.info("REMOVE-DECODERS: " + this); + + if (this.decoderConfigurations == null) { + return; + } + + + for (TopicCoderFilterConfiguration coderConfig: decoderConfigurations) { + String topic = coderConfig.getTopic(); + EventProtocolCoder.manager.removeDecoders + (this.getGroupId(), this.getArtifactId(), topic); + } + } + + /** + * remove decoders. + */ + protected void removeEncoders() + throws IllegalArgumentException { + + if (logger.isInfoEnabled()) + logger.info("REMOVE-ENCODERS: " + this); + + if (this.encoderConfigurations == null) + return; + + + for (TopicCoderFilterConfiguration coderConfig: encoderConfigurations) { + String topic = coderConfig.getTopic(); + EventProtocolCoder.manager.removeEncoders + (this.getGroupId(), this.getArtifactId(), topic); + } + } + + + /** + * {@inheritDoc} + */ + @Override + public boolean ownsCoder(Class<? extends Object> coderClass, int modelHash) throws IllegalStateException { + if (!ReflectionUtil.isClass + (this.policyContainer.getClassLoader(), coderClass.getCanonicalName())) { + logger.error(this + coderClass.getCanonicalName() + " cannot be retrieved. "); + return false; + } + + if (modelHash == this.modelClassLoaderHash) { + if (logger.isInfoEnabled()) + logger.info(coderClass.getCanonicalName() + + this + " class loader matches original drools controller rules classloader " + + coderClass.getClassLoader()); + return true; + } else { + if (logger.isWarnEnabled()) + logger.warn(this + coderClass.getCanonicalName() + " class loaders don't match " + + coderClass.getClassLoader() + " vs " + + this.policyContainer.getClassLoader()); + return false; + } + } + + /** + * {@inheritDoc} + */ + @Override + public boolean start() { + + if (logger.isInfoEnabled()) + logger.info("START: " + this); + + synchronized (this) { + if (this.alive) + return true; + + this.alive = true; + } + + return this.policyContainer.start(); + } + + /** + * {@inheritDoc} + */ + @Override + public boolean stop() { + + logger.info("STOP: " + this); + + synchronized (this) { + if (!this.alive) + return true; + + this.alive = false; + } + + return this.policyContainer.stop(); + } + + + /** + * {@inheritDoc} + */ + @Override + public void shutdown() throws IllegalStateException { + + if (logger.isInfoEnabled()) + logger.info(this + "SHUTDOWN"); + + try { + this.stop(); + this.removeCoders(); + } catch (Exception e) { + logger.error(MessageCodes.EXCEPTION_ERROR, e, "stop", this.toString()); + } finally { + this.policyContainer.shutdown(); + } + + } + + + /** + * {@inheritDoc} + */ + @Override + public void halt() throws IllegalStateException { + if (logger.isInfoEnabled()) + logger.info(this + "SHUTDOWN"); + + try { + this.stop(); + this.removeCoders(); + } catch (Exception e) { + logger.error(MessageCodes.EXCEPTION_ERROR, e, "halt", this.toString()); + } finally { + this.policyContainer.destroy(); + } + } + + /** + * removes this drools controllers and encoders and decoders from operation + */ + protected void removeCoders() { + + if (logger.isInfoEnabled()) + logger.info(this + "REMOVE-CODERS"); + + try { + this.removeDecoders(); + } catch (IllegalArgumentException e) { + logger.error(MessageCodes.EXCEPTION_ERROR, e, "removeDecoders", this.toString()); + } + + try { + this.removeEncoders(); + } catch (IllegalArgumentException e) { + logger.error(MessageCodes.EXCEPTION_ERROR, e, "removeEncoders", this.toString()); + } + } + + /** + * {@inheritDoc} + */ + @Override + public boolean isAlive() { + return this.alive; + } + + /** + * {@inheritDoc} + */ + @Override + public boolean offer(String topic, String event) { + + if (logger.isInfoEnabled()) + logger.info("OFFER: " + topic + ":" + event + " INTO " + this); + + if (this.locked) + return true; + + if (!this.alive) + return true; + + // 0. Check if the policy container has any sessions + + if (this.policyContainer.getPolicySessions().size() <= 0) { + // no sessions + return true; + } + + // 1. Now, check if this topic has a decoder: + + if (!EventProtocolCoder.manager.isDecodingSupported(this.getGroupId(), + this.getArtifactId(), + topic)) { + + logger.warn("DECODING-UNSUPPORTED: " + ":" + this.getGroupId() + + ":" + this.getArtifactId() + ":" + topic + " IN " + this); + return true; + } + + // 2. Decode + + Object anEvent; + try { + anEvent = EventProtocolCoder.manager.decode(this.getGroupId(), + this.getArtifactId(), + topic, + event); + } catch (Exception e) { + logger.error(MessageCodes.EXCEPTION_ERROR, e, + "DECODE:"+ this.getGroupId() + ":" + + this.getArtifactId() + ":" + topic + ":" + event, + this.toString()); + return true; + } + + synchronized(this.recentSourceEvents) { + this.recentSourceEvents.add(anEvent); + } + + // increment event count for Nagios monitoring + PdpJmx.getInstance().updateOccured(); + + // Broadcast + + if (logger.isInfoEnabled()) + logger.info(this + "BROADCAST-INJECT of " + event + " FROM " + topic + " INTO " + this.policyContainer.getName()); + + if (!this.policyContainer.insertAll(anEvent)) + logger.warn(this + "Failed to inject into PolicyContainer " + this.getSessionNames()); + + return true; + } + + /** + * {@inheritDoc} + */ + @Override + public boolean deliver(TopicSink sink, Object event) + throws IllegalArgumentException, + IllegalStateException, + UnsupportedOperationException { + + if (logger.isInfoEnabled()) + logger.info(this + "DELIVER: " + event + " FROM " + this + " TO " + sink); + + if (sink == null) + throw new IllegalArgumentException + (this + " invalid sink"); + + if (event == null) + throw new IllegalArgumentException + (this + " invalid event"); + + if (this.locked) + throw new IllegalStateException + (this + " is locked"); + + if (!this.alive) + throw new IllegalStateException + (this + " is stopped"); + + String json = + EventProtocolCoder.manager.encode(sink.getTopic(), event, this); + + synchronized(this.recentSinkEvents) { + this.recentSinkEvents.add(json); + } + + return sink.send(json); + + } + + /** + * {@inheritDoc} + */ + @Override + public String getVersion() { + return this.policyContainer.getVersion(); + } + + /** + * {@inheritDoc} + */ + @Override + public String getArtifactId() { + return this.policyContainer.getArtifactId(); + } + + /** + * {@inheritDoc} + */ + @Override + public String getGroupId() { + return this.policyContainer.getGroupId(); + } + + /** + * @return the modelClassLoaderHash + */ + public int getModelClassLoaderHash() { + return modelClassLoaderHash; + } + + /** + * {@inheritDoc} + */ + @Override + public synchronized boolean lock() { + logger.info("LOCK: " + this); + + this.locked = true; + return true; + } + + /** + * {@inheritDoc} + */ + @Override + public synchronized boolean unlock() { + logger.info("UNLOCK: " + this); + + this.locked = false; + return true; + } + + /** + * {@inheritDoc} + */ + @Override + public boolean isLocked() { + return this.locked; + } + + @Override + public List<String> getSessionNames() { + List<String> sessionNames = new ArrayList<String>(); + try { + for (PolicySession session: this.policyContainer.getPolicySessions()) { + sessionNames.add(session.getFullName()); + } + } catch (Exception e) { + logger.warn(MessageCodes.EXCEPTION_ERROR, e, + "Can't retrieve POLICY-CORE sessions: " + e.getMessage(), + this.toString()); + sessionNames.add(e.getMessage()); + } + return sessionNames; + } + + /** + * {@inheritDoc} + */ + @Override + public Class<?> fetchModelClass(String className) throws IllegalStateException { + Class<?> modelClass = + ReflectionUtil.fetchClass(this.policyContainer.getClassLoader(), className); + return modelClass; + } + + /** + * @return the recentSourceEvents + */ + @Override + public Object[] getRecentSourceEvents() { + synchronized(this.recentSourceEvents) { + Object[] events = new Object[recentSourceEvents.size()]; + return recentSourceEvents.toArray(events); + } + } + + /** + * @return the recentSinkEvents + */ + @Override + public String[] getRecentSinkEvents() { + synchronized(this.recentSinkEvents) { + String[] events = new String[recentSinkEvents.size()]; + return recentSinkEvents.toArray(events); + } + } + + + /** + * {@inheritDoc} + */ + @Override + public boolean isBrained() { + return true; + } + + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("MavenDroolsController [policyContainer=") + .append((policyContainer != null) ? policyContainer.getName() : "NULL").append(":") + .append(", alive=") + .append(alive).append(", locked=").append(locked).append(", decoderConfigurations=") + .append(decoderConfigurations).append(", encoderConfigurations=").append(encoderConfigurations) + .append(", modelClassLoaderHash=").append(modelClassLoaderHash).append("]"); + return builder.toString(); + } + +} 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 new file mode 100644 index 00000000..f0c0f474 --- /dev/null +++ b/policy-management/src/main/java/org/openecomp/policy/drools/controller/internal/NullDroolsController.java @@ -0,0 +1,219 @@ +/*- + * ============LICENSE_START======================================================= + * policy-management + * ================================================================================ + * 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.controller.internal; + +import java.util.ArrayList; +import java.util.List; + +import org.openecomp.policy.drools.controller.DroolsController; +import org.openecomp.policy.drools.event.comm.TopicSink; +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<String> emptySessionNames = new ArrayList<String>(); + + /** + * {@inheritDoc} + */ + @Override + public boolean start() throws IllegalStateException { + return false; + } + + /** + * {@inheritDoc} + */ + @Override + public boolean stop() throws IllegalStateException { + return false; + } + + /** + * {@inheritDoc} + */ + @Override + public void shutdown() throws IllegalStateException { + return; + } + + /** + * {@inheritDoc} + */ + @Override + public void halt() throws IllegalStateException { + return; + } + + /** + * {@inheritDoc} + */ + @Override + public boolean isAlive() { + return false; + } + + /** + * {@inheritDoc} + */ + @Override + public boolean lock() { + return false; + } + + /** + * {@inheritDoc} + */ + @Override + public boolean unlock() { + return false; + } + + /** + * {@inheritDoc} + */ + @Override + public boolean isLocked() { + return false; + } + + /** + * {@inheritDoc} + */ + @Override + public String getGroupId() { + return NO_GROUP_ID; + } + + /** + * {@inheritDoc} + */ + @Override + public String getArtifactId() { + return NO_ARTIFACT_ID; + } + + /** + * {@inheritDoc} + */ + @Override + public String getVersion() { + return NO_VERSION; + } + + /** + * {@inheritDoc} + */ + @Override + public List<String> getSessionNames() { + return new ArrayList<String>(); + } + + /** + * {@inheritDoc} + */ + @Override + public boolean offer(String topic, String event) { + return false; + } + + /** + * {@inheritDoc} + */ + @Override + public boolean deliver(TopicSink sink, Object event) + throws IllegalArgumentException, IllegalStateException, UnsupportedOperationException { + throw new IllegalArgumentException(this.getClass().getCanonicalName() + " invoked"); + } + + /** + * {@inheritDoc} + */ + @Override + public Object[] getRecentSourceEvents() { + return NullDroolsController.emptyRecentEvents; + } + + /** + * {@inheritDoc} + */ + @Override + public String[] getRecentSinkEvents() { + return NullDroolsController.emptyRecentEvents; + } + + /** + * {@inheritDoc} + */ + @Override + public boolean ownsCoder(Class<? extends Object> coderClass, int modelHash) throws IllegalStateException { + throw new IllegalArgumentException(this.getClass().getCanonicalName() + " invoked"); + } + + /** + * {@inheritDoc} + */ + @Override + public Class<?> fetchModelClass(String className) throws IllegalArgumentException { + throw new IllegalArgumentException(this.getClass().getCanonicalName() + " invoked"); + } + + /** + * {@inheritDoc} + */ + @Override + public boolean isBrained() { + return false; + } + + /** + * {@inheritDoc} + */ + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("NullDroolsController []"); + return builder.toString(); + } + + /** + * {@inheritDoc} + */ + @Override + public void updateToVersion(String newGroupId, String newArtifactId, String newVersion, + List<TopicCoderFilterConfiguration> decoderConfigurations, + List<TopicCoderFilterConfiguration> encoderConfigurations) + throws IllegalArgumentException, LinkageError, Exception { + throw new IllegalArgumentException(this.getClass().getCanonicalName() + " invoked"); + } + +} diff --git a/policy-management/src/main/java/org/openecomp/policy/drools/persistence/SystemPersistence.java b/policy-management/src/main/java/org/openecomp/policy/drools/persistence/SystemPersistence.java new file mode 100644 index 00000000..6bb1185d --- /dev/null +++ b/policy-management/src/main/java/org/openecomp/policy/drools/persistence/SystemPersistence.java @@ -0,0 +1,255 @@ +/*- + * ============LICENSE_START======================================================= + * policy-management + * ================================================================================ + * 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.persistence; + +import java.io.File; +import java.io.FileWriter; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.nio.file.StandardCopyOption; +import java.util.Properties; + +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.drools.utils.PropertyUtil; + +public interface SystemPersistence { + + /** + * configuration directory + */ + public static String CONFIG_DIR_NAME = "config"; + + /** + * policy controllers suffix + */ + public final static String CONTROLLER_SUFFIX_IDENTIFIER = "-controller"; + + /** + * policy controller properties file suffix + */ + public final static String PROPERTIES_FILE_CONTROLLER_SUFFIX = + CONTROLLER_SUFFIX_IDENTIFIER + ".properties"; + + /** + * policy engine properties file name + */ + public final static String PROPERTIES_FILE_ENGINE = "policy-engine.properties"; + + + /** + * backs up a controller configuration. + * + * @param controllerName the controller name + * @return true if the configuration is backed up + */ + public boolean backupController(String controllerName); + + /** + * persists controller configuration + * + * @param controllerName the controller name + * @param configuration object containing the configuration + * @return true if storage is succesful, false otherwise + * @throws IllegalArgumentException if the configuration cannot be handled by the persistence manager + */ + public boolean storeController(String controllerName, Object configuration) + throws IllegalArgumentException; + + /** + * delete controller configuration + * + * @param controllerName the controller name + * @return true if storage is succesful, false otherwise + */ + public boolean deleteController(String controllerName); + + /** + * get controller properties + * + * @param controllerName controller name + * @return properties for this controller + * @throws IllegalArgumentException if the controller name does not lead to a properties configuration + */ + public Properties getControllerProperties(String controllerName) + throws IllegalArgumentException; + + /** + * get properties by name + * + * @param name + * @return properties + * @throws IllegalArgumentException if the name does not lead to a properties configuration + */ + public Properties getProperties(String name) throws IllegalArgumentException; + + /** + * Persistence Manager. For now it is a file-based properties management, + * In the future, it will probably be DB based, so manager implementation + * will change. + */ + public static final SystemPersistence manager = new SystemPropertiesPersistence(); +} + +/** + * Properties based Persistence + */ +class SystemPropertiesPersistence implements SystemPersistence { + + /** + * logger + */ + private static Logger logger = FlexLogger.getLogger(SystemPropertiesPersistence.class); + + /** + * backs up the properties-based controller configuration + * @param controllerName the controller name + * @return true if the configuration is backed up in disk or back up does not apply, false otherwise. + */ + @Override + public boolean backupController(String controllerName) { + Path controllerPropertiesPath = + Paths.get(CONFIG_DIR_NAME, controllerName + PROPERTIES_FILE_CONTROLLER_SUFFIX); + + if (Files.exists(controllerPropertiesPath)) { + try { + logger.warn("There is an existing configuration file at " + + controllerPropertiesPath.toString() + + " with contents: " + Files.readAllBytes(controllerPropertiesPath)); + Path controllerPropertiesBakPath = + Paths.get(CONFIG_DIR_NAME, controllerName + + PROPERTIES_FILE_CONTROLLER_SUFFIX + ".bak"); + Files.copy(controllerPropertiesPath, + controllerPropertiesBakPath, StandardCopyOption.REPLACE_EXISTING); + } catch (Exception e) { + logger.warn(MessageCodes.EXCEPTION_ERROR, e, + controllerName, "SystemPersistenceProperties"); + return false; + } + } + + return true; + } + + /** + * persists properties-based controller configuration and makes a backup if necessary + * @param controllerName the controller name + * @return true if the properties has been stored in disk, false otherwise + */ + @Override + public boolean storeController(String controllerName, Object configuration) { + if (!(configuration instanceof Properties)) { + throw new IllegalArgumentException("configuration must be of type properties to be handled by this manager"); + } + + Properties properties = (Properties) configuration; + + Path controllerPropertiesPath = + Paths.get(CONFIG_DIR_NAME, controllerName + PROPERTIES_FILE_CONTROLLER_SUFFIX); + if (Files.exists(controllerPropertiesPath)) { + try { + Properties oldProperties = PropertyUtil.getProperties(controllerPropertiesPath.toFile()); + if (oldProperties.equals(properties)) { + logger.info("A properties file with the same contents already exists for controller " + + controllerName + + ". No action is taken"); + return true; + } else { + this.backupController(controllerName); + } + } catch (Exception e) { + logger.info("No existing Properties"); + // continue + } + } + + try { + File controllerPropertiesFile = controllerPropertiesPath.toFile(); + FileWriter writer = new FileWriter(controllerPropertiesFile); + properties.store(writer, "Machine created Policy Controller Configuration"); + } catch (Exception e) { + logger.warn(MessageCodes.EXCEPTION_ERROR, e, + controllerName, "SystemPersistenceProperties"); + return false; + } + + return true; + } + + /** + * deletes properties-based controller configuration + * @param controllerName the controller name + * @return true if the properties has been deleted from disk, false otherwise + */ + @Override + public boolean deleteController(String controllerName) { + + Path controllerPropertiesPath = + Paths.get(CONFIG_DIR_NAME, + controllerName + PROPERTIES_FILE_CONTROLLER_SUFFIX); + + if (Files.exists(controllerPropertiesPath)) { + try { + Path controllerPropertiesBakPath = + Paths.get(CONFIG_DIR_NAME, controllerName + + PROPERTIES_FILE_CONTROLLER_SUFFIX + ".bak"); + Files.move(controllerPropertiesPath, + controllerPropertiesBakPath, + StandardCopyOption.REPLACE_EXISTING); + } catch (Exception e) { + logger.warn(MessageCodes.EXCEPTION_ERROR, e, + controllerName, "SystemPersistenceProperties"); + return false; + } + } + + return true; + } + + @Override + public Properties getControllerProperties(String controllerName) throws IllegalArgumentException { + return this.getProperties(controllerName + CONTROLLER_SUFFIX_IDENTIFIER); + } + + @Override + public Properties getProperties(String name) throws IllegalArgumentException { + Path propertiesPath = + Paths.get(CONFIG_DIR_NAME, name + ".properties"); + + if (!Files.exists(propertiesPath)) { + throw new IllegalArgumentException("properties for " + name + " are not persisted."); + } + + try { + return PropertyUtil.getProperties(propertiesPath.toFile()); + } catch (Exception e) { + logger.warn(MessageCodes.EXCEPTION_ERROR, e, + name, "SystemPersistenceProperties can't retrieved properties for " + + propertiesPath); + e.printStackTrace(); + throw new IllegalArgumentException("can't read properties for " + + name + " @ " + + propertiesPath); + } + } +} 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 new file mode 100644 index 00000000..8f8a4ba7 --- /dev/null +++ b/policy-management/src/main/java/org/openecomp/policy/drools/protocol/coders/EventProtocolCoder.java @@ -0,0 +1,1451 @@ +/*- + * ============LICENSE_START======================================================= + * policy-management + * ================================================================================ + * 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.protocol.coders; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import org.openecomp.policy.common.logging.eelf.MessageCodes; +import org.openecomp.policy.common.logging.flexlogger.FlexLogger; +import org.openecomp.policy.common.logging.flexlogger.Logger; +import org.openecomp.policy.drools.controller.DroolsController; +import org.openecomp.policy.drools.protocol.coders.EventProtocolCoder.CoderFilters; +import org.openecomp.policy.drools.protocol.coders.TopicCoderFilterConfiguration.CustomGsonCoder; +import org.openecomp.policy.drools.protocol.coders.TopicCoderFilterConfiguration.CustomJacksonCoder; +import org.openecomp.policy.drools.utils.Pair; + +/** + * Coder (Encoder/Decoder) of Events. + */ +public interface EventProtocolCoder { + + public static class CoderFilters { + + /** + * coder class + */ + protected String factClass; + + /** + * filters to apply to the selection of the decodedClass; + */ + protected JsonProtocolFilter filter; + + /** + * classloader hash + */ + protected int modelClassLoaderHash; + + + /** + * constructor + * + * @param codedClass coder class + * @param filter filters to apply + */ + public CoderFilters(String codedClass, JsonProtocolFilter filter, int modelClassLoaderHash) { + this.factClass = codedClass; + this.filter = filter; + this.modelClassLoaderHash = modelClassLoaderHash; + } + + /** + * @return the codedClass + */ + public String getCodedClass() { + return factClass; + } + + /** + * @param codedClass the decodedClass to set + */ + public void setCodedClass(String codedClass) { + this.factClass = codedClass; + } + + /** + * @return the filter + */ + public synchronized JsonProtocolFilter getFilter() { + return filter; + } + + /** + * @param filter the filter to set + */ + public synchronized void setFilter(JsonProtocolFilter filter) { + this.filter = filter; + } + + public int getModelClassLoaderHash() { + return modelClassLoaderHash; + } + + public void setFromClassLoaderHash(int fromClassLoaderHash) { + this.modelClassLoaderHash = fromClassLoaderHash; + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("CoderFilters [factClass=").append(factClass).append(", filter=").append(filter) + .append(", modelClassLoaderHash=").append(modelClassLoaderHash).append("]"); + return builder.toString(); + } + + } + + /** + * Adds a Decoder class to decode the protocol over this topic + * + * @param groupId of the controller + * @param artifactId of the controller + * @param topic the topic + * @param eventClass the event class + * @param protocolFilter filters to selectively choose a particular decoder + * when there are multiples + * + * @throw IllegalArgumentException if an invalid parameter is passed + */ + public void addDecoder(String groupId, String artifactId, + String topic, + String eventClass, + JsonProtocolFilter protocolFilter, + CustomGsonCoder customGsonCoder, + CustomJacksonCoder customJacksonCoder, + int modelClassLoaderHash) + throws IllegalArgumentException; + + /** + * removes all decoders associated with the controller id + * @param groupId of the controller + * @param artifactId of the controller + * @param topic of the controller + * + * @throws IllegalArgumentException if invalid arguments have been provided + */ + void removeEncoders(String groupId, String artifactId, String topic) throws IllegalArgumentException; + + /** + * removes decoders associated with the controller id and topic + * @param groupId of the controller + * @param artifactId of the controller + * @param topic the topic + * + * @throws IllegalArgumentException if invalid arguments have been provided + */ + public void removeDecoders(String groupId, String artifactId, String topic) throws IllegalArgumentException; + + /** + * Given a controller id and a topic, it gives back its filters + * + * @param groupId of the controller + * @param artifactId of the controller + * @param topic the topic + * + * return list of decoders + * + * @throw IllegalArgumentException if an invalid parameter is passed + */ + public List<CoderFilters> getDecoderFilters(String groupId, String artifactId, String topic) + throws IllegalArgumentException; + + + /** + * Given a controller id and a topic, it gives back the decoding configuration + * + * @param groupId of the controller + * @param artifactId of the controller + * @param topic the topic + * + * return decoding toolset + * + * @throw IllegalArgumentException if an invalid parameter is passed + */ + public ProtocolCoderToolset getDecoders(String groupId, String artifactId, String topic) + throws IllegalArgumentException; + + /** + * Given a controller id and a topic, it gives back all the decoding configurations + * + * @param groupId of the controller + * @param artifactId of the controller + * @param topic the topic + * + * return decoding toolset + * + * @throw IllegalArgumentException if an invalid parameter is passed + */ + public List<ProtocolCoderToolset> getDecoders(String groupId, String artifactId) + throws IllegalArgumentException; + + + /** + * gets all decoders associated with the group and artifact ids + * @param groupId of the controller + * @param artifactId of the controller + * + * @throws IllegalArgumentException if invalid arguments have been provided + */ + public List<CoderFilters> getDecoderFilters(String groupId, String artifactId) throws IllegalArgumentException; + + + /** + * Given a controller id and a topic, it gives back the classes that implements the encoding + * + * @param groupId of the controller + * @param artifactId of the controller + * @param topic the topic + * + * return list of decoders + * + * @throw IllegalArgumentException if an invalid parameter is passed + */ + public List<CoderFilters> getEncoderFilters(String groupId, String artifactId, String topic) + throws IllegalArgumentException; + + /** + * gets all encoders associated with the group and artifact ids + * @param groupId of the controller + * @param artifactId of the controller + * + * @throws IllegalArgumentException if invalid arguments have been provided + */ + public List<CoderFilters> getEncoderFilters(String groupId, String artifactId) throws IllegalArgumentException; + + /** + * Given a controller id, a topic, and a classname, it gives back the classes that implements the decoding + * + * @param groupId of the controller + * @param artifactId of the controller + * @param topic the topic + * @param classname classname + * + * return list of decoders + * + * @throw IllegalArgumentException if an invalid parameter is passed + */ + public CoderFilters getDecoderFilters(String groupId, String artifactId, String topic, String classname) + throws IllegalArgumentException; + + /** + * is there a decoder supported for the controller id and topic + * + * @param groupId of the controller + * @param artifactId of the controller + * @param topic protocol + * @return true if supported + */ + public boolean isDecodingSupported(String groupId, String artifactId, String topic); + + /** + * Adds a Encoder class to encode the protocol over this topic + * + * @param groupId of the controller + * @param artifactId of the controller + * @param topic the topic + * @param eventClass the event class + * @param protocolFilter filters to selectively choose a particular decoder + * when there are multiples + * + * @throw IllegalArgumentException if an invalid parameter is passed + */ + public void addEncoder(String groupId, String artifactId, String topic, + String eventClass, + JsonProtocolFilter protocolFilter, + CustomGsonCoder customGsonCoder, + CustomJacksonCoder customJacksonCoder, + int modelClassLoaderHash) + throws IllegalArgumentException; + + /** + * is there an encoder supported for the controller id and topic + * + * @param groupId of the controller + * @param artifactId of the controller + * @param topic protocol + * @return true if supported + */ + public boolean isEncodingSupported(String groupId, String artifactId, String topic); + + /** + * get encoder based on coordinates and classname + * + * @param groupId of the controller + * @param artifactId of the controller + * @param topic protocol + * @param json event string + * @return + * @throws IllegalArgumentException invalid arguments passed in + */ + public CoderFilters getEncoderFilters(String groupId, String artifactId, String topic, String classname) + throws IllegalArgumentException; + + /** + * get encoder based on topic and encoded class + * + * @param topic topic + * @param encodedClass encoded class + * @return + * @throws IllegalArgumentException invalid arguments passed in + */ + public List<CoderFilters> getReverseEncoderFilters(String topic, String encodedClass) + throws IllegalArgumentException; + + /** + * gets the identifier of the creator of the encoder + * + * @param topic topic + * @param encodedClass encoded class + * @return a drools controller + * @throws IllegalArgumentException invalid arguments passed in + */ + public DroolsController getDroolsController(String topic, Object encodedClass) + throws IllegalArgumentException; + + /** + * gets the identifier of the creator of the encoder + * + * @param topic topic + * @param encodedClass encoded class + * @return list of drools controllers + * @throws IllegalArgumentException invalid arguments passed in + */ + public List<DroolsController> getDroolsControllers(String topic, Object encodedClass) + throws IllegalArgumentException; + + /** + * decode topic's stringified event (json) to corresponding Event Object. + * + * @param groupId of the controller + * @param artifactId of the controller + * @param topic protocol + * @param json event string + * @return + * @throws IllegalArgumentException invalid arguments passed in + * @throws UnsupportedOperationException if the operation is not supported + * @throws IllegalStateException if the system is in an illegal state + */ + public Object decode(String groupId, String artifactId, String topic, String json) + throws IllegalArgumentException, UnsupportedOperationException, IllegalStateException; + + /** + * encodes topic's stringified event (json) to corresponding Event Object. + * + * @param groupId of the controller + * @param artifactId of the controller + * @param topic protocol + * @param event Object + * + * @throws IllegalArgumentException invalid arguments passed in + */ + public String encode(String groupId, String artifactId, String topic, Object event) + throws IllegalArgumentException, IllegalStateException, UnsupportedOperationException; + + /** + * encodes topic's stringified event (json) to corresponding Event Object. + * + * @param topic topic + * @param event event object + * + * @throws IllegalArgumentException invalid arguments passed in + * @throws UnsupportedOperationException operation cannot be performed + */ + public String encode(String topic, Object event) + throws IllegalArgumentException, IllegalStateException, UnsupportedOperationException; + + /** + * encodes topic's stringified event (json) to corresponding Event Object. + * + * @param topic topic + * @param event event object + * @param droolsController + * + * @throws IllegalArgumentException invalid arguments passed in + * @throws UnsupportedOperationException operation cannot be performed + */ + public String encode(String topic, Object event, DroolsController droolsController) + throws IllegalArgumentException, IllegalStateException, UnsupportedOperationException; + + /** + * singleton reference to the global event protocol coder + */ + public static EventProtocolCoder manager = new MultiplexorEventProtocolCoder(); +} + +/** + * Protocol Coder that does its best attempt to decode/encode, selecting the best + * class and best fitted json parsing tools. + */ +class MultiplexorEventProtocolCoder implements EventProtocolCoder { + // get an instance of logger + private static Logger logger = FlexLogger.getLogger(MultiplexorEventProtocolCoder.class); + /** + * Decoders + */ + protected EventProtocolDecoder decoders = new EventProtocolDecoder(); + + /** + * Encoders + */ + protected EventProtocolEncoder encoders = new EventProtocolEncoder(); + + + /** + * {@inheritDoc} + */ + @Override + public void addDecoder(String groupId, String artifactId, String topic, + String eventClass, + JsonProtocolFilter protocolFilter, + CustomGsonCoder customGsonCoder, + CustomJacksonCoder customJacksonCoder, + int modelClassLoaderHash) + throws IllegalArgumentException { + logger.info("ADD-DECODER: " + groupId + ":" + artifactId + ":" + + topic + ":" + eventClass + ":" + + protocolFilter + ":" + customGsonCoder + + ":" + customJacksonCoder + ":" + modelClassLoaderHash + + " INTO " + this); + this.decoders.add(groupId, artifactId, topic, eventClass, protocolFilter, + customGsonCoder, customJacksonCoder, modelClassLoaderHash); + } + + /** + * {@inheritDoc} + */ + @Override + public void addEncoder(String groupId, String artifactId, String topic, + String eventClass, + JsonProtocolFilter protocolFilter, + CustomGsonCoder customGsonCoder, + CustomJacksonCoder customJacksonCoder, + int modelClassLoaderHash) + throws IllegalArgumentException { + logger.info("ADD-ENCODER: " + groupId + ":" + artifactId + ":" + + topic + ":" + eventClass + ":" + + protocolFilter + ":" + customGsonCoder + + ":" + customJacksonCoder + ":" + modelClassLoaderHash + + " INTO " + this); + this.encoders.add(groupId, artifactId, topic, eventClass, protocolFilter, + customGsonCoder, customJacksonCoder, modelClassLoaderHash); + } + + /** + * {@inheritDoc} + */ + @Override + public void removeDecoders(String groupId, String artifactId, String topic) + throws IllegalArgumentException { + logger.info("REMOVE-DECODER: " + groupId + ":" + artifactId + ":" + + topic + " FROM " + this); + this.decoders.remove(groupId, artifactId, topic); + } + + /** + * {@inheritDoc} + */ + @Override + public void removeEncoders(String groupId, String artifactId, String topic) + throws IllegalArgumentException { + logger.info("REMOVE-ENCODER: " + groupId + ":" + artifactId + ":" + + topic + " FROM " + this); + this.encoders.remove(groupId, artifactId, topic); + } + + /** + * {@inheritDoc} + */ + @Override + public boolean isDecodingSupported(String groupId, String artifactId, String topic) { + return this.decoders.isCodingSupported(groupId, artifactId, topic); + } + + /** + * {@inheritDoc} + */ + @Override + public boolean isEncodingSupported(String groupId, String artifactId, String topic) { + return this.encoders.isCodingSupported(groupId, artifactId, topic); + } + + /** + * {@inheritDoc} + */ + @Override + public Object decode(String groupId, String artifactId, String topic, String json) + throws IllegalArgumentException, UnsupportedOperationException, IllegalStateException { + logger.info("DECODE: " + groupId + ":" + artifactId + ":" + + topic + ":" + json + " WITH " + this); + return this.decoders.decode(groupId, artifactId, topic, json); + } + + /** + * {@inheritDoc} + */ + @Override + public String encode(String groupId, String artifactId, String topic, Object event) + throws IllegalArgumentException, IllegalStateException, UnsupportedOperationException { + logger.info("ENCODE: " + groupId + ":" + artifactId + ":" + + topic + ":" + event + " WITH " + this); + return this.encoders.encode(groupId, artifactId, topic, event); + } + + /** + * {@inheritDoc} + */ + @Override + public String encode(String topic, Object event) + throws IllegalArgumentException, IllegalStateException, UnsupportedOperationException { + logger.info("ENCODE: " + topic + ":" + event + " WITH " + this); + return this.encoders.encode(topic, event); + } + + /** + * {@inheritDoc} + */ + @Override + public String encode(String topic, Object event, DroolsController droolsController) + throws IllegalArgumentException, IllegalStateException, UnsupportedOperationException { + logger.info("ENCODE: " + topic + ":" + event + ":" + droolsController + " WITH " + this); + return this.encoders.encode(topic, event, droolsController); + } + + /** + * {@inheritDoc} + */ + @Override + public List<CoderFilters> getDecoderFilters(String groupId, String artifactId, String topic) + throws IllegalArgumentException { + + return this.decoders.getFilters(groupId, artifactId, topic); + } + + /** + * {@inheritDoc} + */ + @Override + public ProtocolCoderToolset getDecoders(String groupId, String artifactId, String topic) + throws IllegalArgumentException { + + Pair<ProtocolCoderToolset,ProtocolCoderToolset> decoderToolsets = this.decoders.getCoders(groupId, artifactId, topic); + if (decoderToolsets == null) + throw new IllegalArgumentException("Decoders not found for " + groupId + ":" + artifactId + ":" + topic); + + return decoderToolsets.first(); + } + + /** + * {@inheritDoc} + */ + @Override + public List<CoderFilters> getEncoderFilters(String groupId, String artifactId, String topic) + throws IllegalArgumentException { + + return this.encoders.getFilters(groupId, artifactId, topic); + } + + /** + * {@inheritDoc} + */ + @Override + public CoderFilters getDecoderFilters(String groupId, String artifactId, String topic, String classname) + throws IllegalArgumentException { + + return this.decoders.getFilters(groupId, artifactId, topic, classname); + } + + /** + * {@inheritDoc} + */ + @Override + public CoderFilters getEncoderFilters(String groupId, String artifactId, String topic, String classname) + throws IllegalArgumentException { + + return this.encoders.getFilters(groupId, artifactId, topic, classname); + } + + /** + * {@inheritDoc} + */ + @Override + public List<CoderFilters> getReverseEncoderFilters(String topic, String encodedClass) throws IllegalArgumentException { + return this.encoders.getReverseFilters(topic, encodedClass); + } + + /** + * get all deocders by maven coordinates and topic + * + * @param groupId group id + * @param artifactId artifact id + * + * @return list of decoders + * @throws IllegalArgumentException if invalid input + */ + @Override + public List<ProtocolCoderToolset> getDecoders(String groupId, String artifactId) + throws IllegalArgumentException { + + List<Pair<ProtocolCoderToolset,ProtocolCoderToolset>> decoderToolsets = this.decoders.getCoders(groupId, artifactId); + if (decoderToolsets == null) + throw new IllegalArgumentException("Decoders not found for " + groupId + ":" + artifactId); + + List<ProtocolCoderToolset> parser1CoderToolset = new ArrayList<>(); + for (Pair<ProtocolCoderToolset,ProtocolCoderToolset> coderToolsetPair : decoderToolsets) { + parser1CoderToolset.add(coderToolsetPair.first()); + } + + return parser1CoderToolset; + } + + /** + * {@inheritDoc} + */ + @Override + public List<CoderFilters> getDecoderFilters(String groupId, String artifactId) throws IllegalArgumentException { + return this.decoders.getFilters(groupId, artifactId); + + } + + /** + * {@inheritDoc} + */ + @Override + public List<CoderFilters> getEncoderFilters(String groupId, String artifactId) throws IllegalArgumentException { + return this.encoders.getFilters(groupId, artifactId); + } + + /** + * {@inheritDoc} + */ + @Override + public DroolsController getDroolsController(String topic, Object encodedClass) throws IllegalArgumentException { + return this.encoders.getDroolsController(topic, encodedClass); + } + + /** + * {@inheritDoc} + */ + @Override + public List<DroolsController> getDroolsControllers(String topic, Object encodedClass) throws IllegalArgumentException { + return this.encoders.getDroolsControllers(topic, encodedClass); + } + + /** + * {@inheritDoc} + */ + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("MultiplexorEventProtocolCoder [decoders=").append(decoders).append(", encoders=") + .append(encoders).append("]"); + return builder.toString(); + } +} + +/** + * This protocol Coder that does its best attempt to decode/encode, selecting the best + * class and best fitted json parsing tools. + */ +abstract class GenericEventProtocolCoder { + private static Logger logger = FlexLogger.getLogger(GenericEventProtocolCoder.class); + + /** + * Mapping topic:controller-id -> <protocol-decoder-toolset-pair> + * where protocol-coder-toolset-pair contains both a jackson-protocol-coder-toolset + * and a gson-protocol-coder-toolset. The first value of the pair will the + * protocol coder toolset most likely to be successful with the encoding or decoding, + * and consequently the second value will be the less likely. + */ + protected final HashMap<String, Pair<ProtocolCoderToolset,ProtocolCoderToolset>> coders = + new HashMap<String, Pair<ProtocolCoderToolset,ProtocolCoderToolset>>(); + + /** + * Mapping topic + classname -> Protocol Set + */ + protected final HashMap<String, List<Pair<ProtocolCoderToolset,ProtocolCoderToolset>>> reverseCoders = + new HashMap<String, List<Pair<ProtocolCoderToolset,ProtocolCoderToolset>>>(); + + protected boolean multipleToolsetRetries = false; + + GenericEventProtocolCoder(boolean multipleToolsetRetries) { + this.multipleToolsetRetries = multipleToolsetRetries; + } + + /** + * Index a new coder + * + * @param groupId of the controller + * @param artifactId of the controller + * @param topic the topic + * @param eventClass the event class + * @param protocolFilter filters to selectively choose a particular decoder + * when there are multiples + * + * @throw IllegalArgumentException if an invalid parameter is passed + */ + public void add(String groupId, String artifactId, + String topic, + String eventClass, + JsonProtocolFilter protocolFilter, + CustomGsonCoder customGsonCoder, + CustomJacksonCoder customJacksonCoder, + int modelClassLoaderHash) + throws IllegalArgumentException { + if (groupId == null || groupId.isEmpty()) { + throw new IllegalArgumentException("Invalid group id"); + } + + if (artifactId == null || artifactId.isEmpty()) { + throw new IllegalArgumentException("Invalid artifact id"); + } + + if (topic == null || topic.isEmpty()) { + throw new IllegalArgumentException("Invalid Topic"); + } + + if (eventClass == null) { + throw new IllegalArgumentException("Invalid Event Class"); + } + + String key = this.codersKey(groupId, artifactId, topic); + String reverseKey = this.reverseCodersKey(topic, eventClass); + + synchronized(this) { + if (coders.containsKey(key)) { + Pair<ProtocolCoderToolset, ProtocolCoderToolset> toolsets = coders.get(key); + + if (logger.isInfoEnabled()) + logger.info("ADDING CODER TO EXISTING: " + toolsets + " for " + key); + + toolsets.first().addCoder(eventClass, protocolFilter, modelClassLoaderHash); + toolsets.second().addCoder(eventClass, protocolFilter, modelClassLoaderHash); + + if (!reverseCoders.containsKey(reverseKey)) { + if (logger.isInfoEnabled()) + logger.info("Multiple coder classes case: " + toolsets.first() + + " for " + reverseKey + " - " + key); + + List<Pair<ProtocolCoderToolset,ProtocolCoderToolset>> reverseMappings = + new ArrayList<Pair<ProtocolCoderToolset,ProtocolCoderToolset>>(); + reverseMappings.add(toolsets); + reverseCoders.put(reverseKey, reverseMappings); + } + return; + } + + GsonProtocolCoderToolset gsonCoderTools = + new GsonProtocolCoderToolset + (topic, key, + groupId, artifactId, + eventClass, protocolFilter, + customGsonCoder, + modelClassLoaderHash); + + JacksonProtocolCoderToolset jacksonCoderTools = + new JacksonProtocolCoderToolset + (topic, key, + groupId, artifactId, + eventClass, protocolFilter, + customJacksonCoder, + modelClassLoaderHash); + + // Use Gson as the first priority encoding/decoding toolset, and Jackson + // as second. This is because it has been observed that they can diverge + // somewhat in the encoding/decoding data types, which can produce json + // that may result incompatible with what some network elements are + // expecting. As decoding takes place, this element will reconfigure + // itself to set the jackson one as the favoured one first, if errors + // are detected in the gson encoding + + Pair<ProtocolCoderToolset,ProtocolCoderToolset> coderTools = + new Pair<ProtocolCoderToolset,ProtocolCoderToolset>(gsonCoderTools, + jacksonCoderTools); + + logger.info("ADDED TOOLSET: " + key + " : " + + coderTools + ":" + this); + + coders.put(key, coderTools); + + if (reverseCoders.containsKey(reverseKey)) { + // There is another controller (different group id/artifact id/topic) + // that shares the class and the topic. + + List<Pair<ProtocolCoderToolset,ProtocolCoderToolset>> toolsets = + reverseCoders.get(reverseKey); + boolean present = false; + for (Pair<ProtocolCoderToolset,ProtocolCoderToolset> parserSet: toolsets) { + // just doublecheck + present = parserSet.first().getControllerId().equals(key); + if (present) { + /* anomaly */ + logger.error("UNEXPECTED TOOLSET REVERSE MAPPING FOUND: " + parserSet.first() + + " for " + reverseKey + " - " + key); + } + } + + if (present) { + return; + } else { + logger.info("ADDING TOOLSET REVERSE MAPPING: " + reverseKey + " : " + + toolsets + ":" + coderTools + ":" + this); + toolsets.add(coderTools); + } + } else { + List<Pair<ProtocolCoderToolset,ProtocolCoderToolset>> toolsets = + new ArrayList<Pair<ProtocolCoderToolset,ProtocolCoderToolset>>(); + logger.info("ADDING TOOLSET REVERSE MAPPING: " + reverseKey + " : " + + toolsets + ":" + coderTools + ":" + this); + toolsets.add(coderTools); + reverseCoders.put(reverseKey, toolsets); + } + + } + } + + /** + * produces key for indexing toolset entries + * + * @param group group id + * @param artifactId artifact id + * @param topic topic + * @return index key + */ + protected String codersKey(String groupId, String artifactId, String topic) { + return groupId + ":" + artifactId + ":" + topic; + } + + /** + * produces a key for the reverse index + * + * @param topic topic + * @param eventClass coded class + * @return reverse index key + */ + protected String reverseCodersKey(String topic, String eventClass) { + return topic + ":" + eventClass; + } + + /** + * remove coder + * + * @param groupId group id + * @param artifactId artifact id + * @param topic topic + * @throws IllegalArgumentException if invalid input + */ + public void remove(String groupId, String artifactId, String topic) + throws IllegalArgumentException { + + if (groupId == null || groupId.isEmpty()) { + throw new IllegalArgumentException("Invalid group id"); + } + + if (artifactId == null || artifactId.isEmpty()) { + throw new IllegalArgumentException("Invalid artifact id"); + } + + if (topic == null || topic.isEmpty()) { + throw new IllegalArgumentException("Invalid Topic"); + } + + String key = this.codersKey(groupId, artifactId, topic); + + synchronized(this) { + if (coders.containsKey(key)) { + Pair<ProtocolCoderToolset, ProtocolCoderToolset> p = coders.remove(key); + logger.info("REMOVED TOOLSET: " + key + " : " + p + " FROM " + + coders + " : " + this); + + for (CoderFilters codeFilter : p.first().getCoders()) { + String className = codeFilter.getCodedClass(); + String reverseKey = this.reverseCodersKey(topic, className); + if (this.reverseCoders.containsKey(reverseKey) ) { + List<Pair<ProtocolCoderToolset, ProtocolCoderToolset>> toolsets = + this.reverseCoders.get(reverseKey); + Iterator<Pair<ProtocolCoderToolset, ProtocolCoderToolset>> toolsetsIter = + toolsets.iterator(); + while (toolsetsIter.hasNext()) { + Pair<ProtocolCoderToolset, ProtocolCoderToolset> toolset = toolsetsIter.next(); + if (toolset.first().getControllerId().equals(key)) { + logger.info("REMOVED CODER FROM REVERSE MAPPING of TOOLSET: " + reverseKey + " : " + toolset + " FROM " + + reverseCoders); + toolsetsIter.remove(); + } + } + + if (this.reverseCoders.get(reverseKey).isEmpty()) { + logger.info("REMOVE FULL REVERSE MAPPING of TOOLSET: " + reverseKey + " FROM " + + reverseCoders); + this.reverseCoders.remove(reverseKey); + } + } + } + } + } + } + + /** + * does it support coding? + * + * @param groupId group id + * @param artifactId artifact id + * @param topic topic + * @return true if its is codable + */ + public boolean isCodingSupported(String groupId, String artifactId, String topic) { + + if (groupId == null || groupId.isEmpty()) { + throw new IllegalArgumentException("Invalid group id"); + } + + if (artifactId == null || artifactId.isEmpty()) { + throw new IllegalArgumentException("Invalid artifact id"); + } + + if (topic == null || topic.isEmpty()) + return false; + + String key = this.codersKey(groupId, artifactId, topic); + synchronized(this) { + return (coders.containsKey(key)); + } + } + + /** + * decode a json string into an Object + * + * @param groupId group id + * @param artifactId artifact id + * @param topic topic + * @param json json string to convert to object + * @return the decoded object + * @throws IllegalArgumentException if invalid argument is provided + * @throws UnsupportedOperationException if the operation cannot be performed + */ + public Object decode(String groupId, String artifactId, String topic, String json) + throws IllegalArgumentException, UnsupportedOperationException, IllegalStateException { + + if (!isCodingSupported(groupId, artifactId, topic)) { + throw new IllegalArgumentException("Unsupported:" + codersKey(groupId, artifactId, topic) + " for encoding"); + } + + String key = this.codersKey(groupId, artifactId, topic); + Pair<ProtocolCoderToolset,ProtocolCoderToolset> coderTools = coders.get(key); + try { + Object event = coderTools.first().decode(json); + if (event != null) + return event; + } catch (Exception e) { + // TODO Auto-generated catch block + logger.warn("Can't decode @ " + this); + } + + if (multipleToolsetRetries) { + // try the less favored toolset + try { + Object event = coderTools.second().decode(json); + if (event != null) { + // change the priority of the toolset + synchronized(this) { + ProtocolCoderToolset first = coderTools.first(); + ProtocolCoderToolset second = coderTools.second(); + coderTools.first(second); + coderTools.second(first); + } + + return event; + } + } catch (Exception e2) { + // TODO Auto-generated catch block + e2.printStackTrace(); + throw new UnsupportedOperationException(e2); + } + } + + throw new UnsupportedOperationException("Cannot decode neither with gson or jackson"); + } + + /** + * encode an object into a json string + * + * @param groupId group id + * @param artifactId artifact id + * @param topic topic + * @param event object to convert to string + * @return the json string + * @throws IllegalArgumentException if invalid argument is provided + * @throws UnsupportedOperationException if the operation cannot be performed + */ + public String encode(String groupId, String artifactId, String topic, Object event) + throws IllegalArgumentException, UnsupportedOperationException { + + if (!isCodingSupported(groupId, artifactId, topic)) { + throw new IllegalArgumentException + ("Unsupported:" + codersKey(groupId, artifactId, topic)); + } + + if (event == null) { + throw new IllegalArgumentException("Unsupported topic:" + topic); + } + + // reuse the decoder set, since there must be affinity in the model + String key = this.codersKey(groupId, artifactId, topic); + return this.encodeInternal(key, event); + } + + /** + * encode an object into a json string + * + * @param key identifier + * @param event object to convert to string + * @return the json string + * @throws IllegalArgumentException if invalid argument is provided + * @throws UnsupportedOperationException if the operation cannot be performed + */ + protected String encodeInternal(String key, Object event) + throws IllegalArgumentException, UnsupportedOperationException { + + logger.debug("ENCODE: " + key + ":" + event + this); + + Pair<ProtocolCoderToolset,ProtocolCoderToolset> coderTools = coders.get(key); + try { + String json = coderTools.first().encode(event); + if (json != null && !json.isEmpty()) + return json; + } catch (Exception e) { + logger.error(MessageCodes.EXCEPTION_ERROR, e, "FIRST-ENCODE-INTERNAL: " + + key + ":" + event, this.toString()); + } + + if (multipleToolsetRetries) { + // try the less favored toolset + try { + String json = coderTools.second().encode(event); + if (json != null) { + // change the priority of the toolset + synchronized(this) { + ProtocolCoderToolset first = coderTools.first(); + ProtocolCoderToolset second = coderTools.second(); + coderTools.first(second); + coderTools.second(first); + } + + return json; + } + } catch (Exception e2) { + // TODO Auto-generated catch block + logger.error(MessageCodes.EXCEPTION_ERROR, e2, "SECOND-ENCODE-INTERNAL: " + + key + ":" + event, this.toString()); + throw new UnsupportedOperationException(e2); + } + } + + throw new UnsupportedOperationException("Cannot decode neither with gson or jackson"); + } + + /** + * encode an object into a json string + * + * @param topic topic + * @param encodedClass object to convert to string + * @return the json string + * @throws IllegalArgumentException if invalid argument is provided + * @throws UnsupportedOperationException if the operation cannot be performed + */ + public String encode(String topic, Object encodedClass) + throws IllegalArgumentException, IllegalArgumentException, UnsupportedOperationException { + + if (encodedClass == null) { + throw new IllegalArgumentException("Invalid encoded class"); + } + + if (topic == null || topic.isEmpty()) { + throw new IllegalArgumentException("Invalid topic"); + } + + logger.info("ENCODE: " + topic + ":" + + encodedClass.getClass().getCanonicalName() + ":" + + encodedClass); + + List<DroolsController> droolsControllers = droolsCreators(topic, encodedClass); + if (droolsControllers.size() > 1) { + // unexpected + logger.warn("MULTIPLE DROOLS CONTROLLERS FOUND for: " + topic + ":" + + encodedClass.getClass().getCanonicalName() + ":" + + droolsControllers + " IN " + this); + // continue + } + + String key = codersKey(droolsControllers.get(0).getGroupId(), droolsControllers.get(0).getArtifactId(), topic); + return this.encodeInternal(key, encodedClass); + } + + /** + * encode an object into a json string + * + * @param topic topic + * @param encodedClass object to convert to string + * @return the json string + * @throws IllegalArgumentException if invalid argument is provided + * @throws UnsupportedOperationException if the operation cannot be performed + */ + public String encode(String topic, Object encodedClass, DroolsController droolsController) + throws IllegalArgumentException, IllegalArgumentException, UnsupportedOperationException { + + if (encodedClass == null) { + throw new IllegalArgumentException("Invalid encoded class"); + } + + if (topic == null || topic.isEmpty()) { + throw new IllegalArgumentException("Invalid topic"); + } + + logger.info("ENCODE: " + topic + ":" + + encodedClass.getClass().getCanonicalName() + ":" + + encodedClass + ":" + droolsController); + + String key = codersKey(droolsController.getGroupId(), droolsController.getArtifactId(), topic); + return this.encodeInternal(key, encodedClass); + } + + /** + * @param topic + * @param encodedClass + * @param reverseKey + * @return + * @throws IllegalStateException + * @throws IllegalArgumentException + */ + protected List<DroolsController> droolsCreators(String topic, Object encodedClass) + throws IllegalStateException, IllegalArgumentException { + + List<DroolsController> droolsControllers = new ArrayList<DroolsController>(); + + String reverseKey = this.reverseCodersKey(topic, encodedClass.getClass().getCanonicalName()); + if (!this.reverseCoders.containsKey(reverseKey)) { + logger.warn("NO MAPPING for REVERSE KEY: " + topic + ":" + + encodedClass.getClass().getCanonicalName() + ":" + + encodedClass + ":" + reverseKey + " : " + this); + return droolsControllers; + } + + List<Pair<ProtocolCoderToolset, ProtocolCoderToolset>> + toolsets = this.reverseCoders.get(reverseKey); + + // There must be multiple toolset pairs associated with <topic,classname> reverseKey + // case 2 different controllers use the same models and register the same encoder for + // the same topic. This is assumed not to occur often but for the purpose of encoding + // but there should be no side-effects. Ownership is crosscheck against classname and + // classloader reference. + + if (toolsets == null || toolsets.isEmpty()) { + logger.warn("ENCODE: " + topic + ":" + + encodedClass.getClass().getCanonicalName() + ":" + + encodedClass + " ENCODER NOT FOUND"); + throw new IllegalStateException("No Encoders toolsets available for topic "+ topic + + " encoder " + encodedClass.getClass().getCanonicalName()); + } + + for (Pair<ProtocolCoderToolset, ProtocolCoderToolset> encoderSet : toolsets) { + // figure out the right toolset + String groupId = encoderSet.first().getGroupId(); + String artifactId = encoderSet.first().getArtifactId(); + List<CoderFilters> coders = encoderSet.first().getCoders(); + for (CoderFilters coder : coders) { + if (coder.getCodedClass().equals(encodedClass.getClass().getCanonicalName())) { + DroolsController droolsController = + DroolsController.factory.get(groupId, artifactId, ""); + if (droolsController.ownsCoder(encodedClass.getClass(), coder.getModelClassLoaderHash())) { + droolsControllers.add(droolsController); + } + } + } + } + + if (droolsControllers.isEmpty()) { + throw new IllegalStateException("No Encoders toolsets available for topic "+ topic + + " : encoder " + encodedClass.getClass().getCanonicalName()); + } + return droolsControllers; + } + + + /** + * get all filters by maven coordinates and topic + * + * @param groupId group id + * @param artifactId artifact id + * @param topic topic + * @return list of coders + * @throws IllegalArgumentException if invalid input + */ + public List<CoderFilters> getFilters(String groupId, String artifactId, String topic) + throws IllegalArgumentException { + + if (!isCodingSupported(groupId, artifactId, topic)) { + throw new IllegalArgumentException("Unsupported:" + codersKey(groupId, artifactId, topic)); + } + + String key = this.codersKey(groupId, artifactId, topic); + Pair<ProtocolCoderToolset,ProtocolCoderToolset> coderTools = coders.get(key); + return coderTools.first().getCoders(); + } + + /** + * get all coders by maven coordinates and topic + * + * @param groupId group id + * @param artifactId artifact id + * @param topic topic + * @return list of coders + * @throws IllegalArgumentException if invalid input + */ + public Pair<ProtocolCoderToolset,ProtocolCoderToolset> getCoders(String groupId, String artifactId, String topic) + throws IllegalArgumentException { + + if (!isCodingSupported(groupId, artifactId, topic)) { + throw new IllegalArgumentException("Unsupported:" + codersKey(groupId, artifactId, topic)); + } + + String key = this.codersKey(groupId, artifactId, topic); + Pair<ProtocolCoderToolset,ProtocolCoderToolset> coderTools = coders.get(key); + return coderTools; + } + + /** + * get all coders by maven coordinates and topic + * + * @param groupId group id + * @param artifactId artifact id + * @return list of coders + * @throws IllegalArgumentException if invalid input + */ + public List<CoderFilters> getFilters(String groupId, String artifactId) + throws IllegalArgumentException { + + if (groupId == null || groupId.isEmpty()) { + throw new IllegalArgumentException("Invalid group id"); + } + + if (artifactId == null || artifactId.isEmpty()) { + throw new IllegalArgumentException("Invalid artifact id"); + } + + String key = this.codersKey(groupId, artifactId, ""); + + List<CoderFilters> codersFilters = new ArrayList<CoderFilters>(); + for (Map.Entry<String, Pair<ProtocolCoderToolset,ProtocolCoderToolset>> entry : coders.entrySet()) { + if (entry.getKey().startsWith(key)) { + codersFilters.addAll(entry.getValue().first().getCoders()); + } + } + + return codersFilters; + } + + /** + * get all coders by maven coordinates and topic + * + * @param groupId group id + * @param artifactId artifact id + * @return list of coders + * @throws IllegalArgumentException if invalid input + */ + public List<Pair<ProtocolCoderToolset,ProtocolCoderToolset>> getCoders(String groupId, String artifactId) + throws IllegalArgumentException { + + if (groupId == null || groupId.isEmpty()) { + throw new IllegalArgumentException("Invalid group id"); + } + + if (artifactId == null || artifactId.isEmpty()) { + throw new IllegalArgumentException("Invalid artifact id"); + } + + String key = this.codersKey(groupId, artifactId, ""); + + List<Pair<ProtocolCoderToolset,ProtocolCoderToolset>> coderToolset = new ArrayList<Pair<ProtocolCoderToolset,ProtocolCoderToolset>>(); + for (Map.Entry<String, Pair<ProtocolCoderToolset,ProtocolCoderToolset>> entry : coders.entrySet()) { + if (entry.getKey().startsWith(key)) { + coderToolset.add(entry.getValue()); + } + } + + return coderToolset; + } + + + /** + * get all filters by maven coordinates, topic, and classname + * + * @param groupId group id + * @param artifactId artifact id + * @param topic topic + * @param classname + * @return list of coders + * @throws IllegalArgumentException if invalid input + */ + public CoderFilters getFilters(String groupId, String artifactId, String topic, String classname) + throws IllegalArgumentException { + + if (!isCodingSupported(groupId, artifactId, topic)) { + throw new IllegalArgumentException("Unsupported:" + codersKey(groupId, artifactId, topic)); + } + + if (classname == null || classname.isEmpty()) { + throw new IllegalArgumentException("classname must be provided"); + } + + String key = this.codersKey(groupId, artifactId, topic); + Pair<ProtocolCoderToolset,ProtocolCoderToolset> coderTools = coders.get(key); + return coderTools.first().getCoder(classname); + } + + /** + * get coded based on class and topic + * + * @param topic + * @param codedClass + * @return + * @throws IllegalArgumentException + */ + public List<CoderFilters> getReverseFilters(String topic, String codedClass) + throws IllegalArgumentException { + + if (topic == null || topic.isEmpty()) { + throw new IllegalArgumentException("Unsupported"); + } + + if (codedClass == null) { + throw new IllegalArgumentException("class must be provided"); + } + + String key = this.reverseCodersKey(topic, codedClass); + List<Pair<ProtocolCoderToolset,ProtocolCoderToolset>> toolsets = this.reverseCoders.get(key); + if (toolsets == null) + throw new IllegalArgumentException("No Coder found for " + key); + + + List<CoderFilters> coders = new ArrayList<CoderFilters>(); + for (Pair<ProtocolCoderToolset,ProtocolCoderToolset> toolset: toolsets) { + coders.addAll(toolset.first().getCoders()); + } + + return coders; + } + + /** + * returns group and artifact id of the creator of the encoder + * + * @param topic + * @param fact + * @return + * @throws IllegalArgumentException + */ + DroolsController getDroolsController(String topic, Object fact) + throws IllegalArgumentException { + + if (topic == null || topic.isEmpty()) { + throw new IllegalArgumentException("Unsupported"); + } + + if (fact == null) { + throw new IllegalArgumentException("class must be provided"); + } + + List<DroolsController> droolsControllers = droolsCreators(topic, fact); + if (droolsControllers.size() > 1) { + // unexpected + logger.warn("MULTIPLE DROOLS CONTROLLERS FOUND for: " + topic + ":" + + fact.getClass().getCanonicalName() + ":" + + droolsControllers + " IN " + this); + // continue + } + return droolsControllers.get(0); + } + + /** + * returns group and artifact id of the creator of the encoder + * + * @param topic + * @param fact + * @return + * @throws IllegalArgumentException + */ + List<DroolsController> getDroolsControllers(String topic, Object fact) + throws IllegalArgumentException { + + if (topic == null || topic.isEmpty()) { + throw new IllegalArgumentException("Unsupported"); + } + + if (fact == null) { + throw new IllegalArgumentException("class must be provided"); + } + + List<DroolsController> droolsControllers = droolsCreators(topic, fact); + if (droolsControllers.size() > 1) { + // unexpected + logger.warn("MULTIPLE DROOLS CONTROLLERS FOUND for: " + topic + ":" + + fact.getClass().getCanonicalName() + ":" + + droolsControllers + " IN " + this); + // continue + } + return droolsControllers; + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("GenericEventProtocolCoder [coders=").append(coders.keySet()).append(", reverseCoders=") + .append(reverseCoders.keySet()).append("]"); + return builder.toString(); + } +} + +class EventProtocolDecoder extends GenericEventProtocolCoder { + + public EventProtocolDecoder(){super(false);} + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("EventProtocolDecoder [toString()=").append(super.toString()).append("]"); + return builder.toString(); + } + +} + +class EventProtocolEncoder extends GenericEventProtocolCoder { + + public EventProtocolEncoder(){super(false);} + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("EventProtocolEncoder [toString()=").append(super.toString()).append("]"); + return builder.toString(); + } +}
\ No newline at end of file diff --git a/policy-management/src/main/java/org/openecomp/policy/drools/protocol/coders/JsonProtocolFilter.java b/policy-management/src/main/java/org/openecomp/policy/drools/protocol/coders/JsonProtocolFilter.java new file mode 100644 index 00000000..a2ce3123 --- /dev/null +++ b/policy-management/src/main/java/org/openecomp/policy/drools/protocol/coders/JsonProtocolFilter.java @@ -0,0 +1,304 @@ +/*- + * ============LICENSE_START======================================================= + * policy-management + * ================================================================================ + * 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.protocol.coders; + +import java.util.ArrayList; +import java.util.List; + +import org.openecomp.policy.drools.utils.Pair; + +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; + +/** + * JSON Protocol Filter. Evaluates an JSON string and evaluates if it + * passes its filters. + */ +public class JsonProtocolFilter { + + /** + * Helper class to collect Filter information + */ + public static class FilterRule { + /** + * Field name + */ + protected String name; + + /** + * Field Value regex + */ + protected String regex; + + /** + * Filter Constructor + * + * @param name field name + * @param regex field regex value + */ + public FilterRule(String name, String regex) { + this.name = name; + this.regex = regex; + } + + /** + * Default constructor (for serialization only) + */ + public FilterRule() { + super(); + } + + /** + * gets name + * + * @return + */ + public String getName() { + return name; + } + + /** + * gets regex + * + * @return + */ + public String getRegex() { + return regex; + } + + /** + * sets field name + * @param name field name + */ + public void setName(String name) { + this.name = name; + } + + /** + * sets regex name + * @param regex + */ + public void setRegex(String regex) { + this.regex = regex; + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("Filter [name=").append(name).append(", regex=").append(regex).append("]"); + return builder.toString(); + } + } + + /** + * all the filters to be applied + */ + protected List<FilterRule> rules = new ArrayList<FilterRule>(); + + /** + * + * @param rawFilters raw filter initialization + * + * @throws IllegalArgumentException an invalid input has been provided + */ + public static JsonProtocolFilter fromRawFilters(List<Pair<String, String>> rawFilters) + throws IllegalArgumentException { + + if (rawFilters == null) { + throw new IllegalArgumentException("No raw filters provided"); + } + + List<FilterRule> filters = new ArrayList<FilterRule>(); + for (Pair<String, String> filterPair: rawFilters) { + if (filterPair.first() == null || filterPair.first().isEmpty()) { + // TODO: warn + continue; + } + + filters.add(new FilterRule(filterPair.first(), filterPair.second())); + } + return new JsonProtocolFilter(filters); + } + + /** + * Create a Protocol Filter + * + * @throws IllegalArgumentException an invalid input has been provided + */ + public JsonProtocolFilter() throws IllegalArgumentException {} + + /** + * + * @param rawFilters raw filter initialization + * + * @throws IllegalArgumentException an invalid input has been provided + */ + public JsonProtocolFilter(List<FilterRule> filters) throws IllegalArgumentException { + this.rules = filters; + } + + /** + * are there any filters? + * + * @return true if there are filters, false otherwise + */ + public boolean isRules() { + return !this.rules.isEmpty(); + } + + /** + * accept a JSON string as conformant it if passes all filters + * + * @param json json is a JSON object + * @return true if json string is conformant + * + * @throws IllegalArgumentException an invalid input has been provided + */ + public synchronized boolean accept(JsonElement json) throws IllegalArgumentException { + if (json == null) { + throw new IllegalArgumentException("no JSON provided"); + } + + if (rules.isEmpty()) { + return true; + } + + try { + if (json == null || !json.isJsonObject()) { + return false; + } + + JsonObject event = json.getAsJsonObject(); + for (FilterRule filter: rules) { + if (filter.regex == null || + filter.regex.isEmpty() || + filter.regex.equals(".*")) { + + // Only check for presence + if (!event.has(filter.name)) { + return false; + } + } else { + JsonElement field = event.get(filter.name); + if (field == null) { + return false; + } + + String fieldValue = field.getAsString(); + if (!fieldValue.matches(filter.regex)) { + return false; + } + } + } + return true; + } catch (Exception e) { + // TODO Auto-generated catch block + e.printStackTrace(); + throw new IllegalArgumentException(e); + } + } + + /** + * accept a JSON string as conformant it if passes all filters + * + * @param json json string + * @return true if json string is conformant + * + * @throws IllegalArgumentException an invalid input has been provided + */ + public synchronized boolean accept(String json) throws IllegalArgumentException { + if (json == null || json.isEmpty()) { + throw new IllegalArgumentException("no JSON provided"); + } + + if (rules.isEmpty()) { + return true; + } + + try { + JsonElement element = new JsonParser().parse(json); + if (element == null || !element.isJsonObject()) { + return false; + } + + return this.accept(element.getAsJsonObject()); + } catch (IllegalArgumentException ile) { + throw ile; + } catch (Exception e) { + // TODO Auto-generated catch block + e.printStackTrace(); + throw new IllegalArgumentException(e); + } + } + + public List<FilterRule> getRules() { + return rules; + } + + public synchronized void setRules(List<FilterRule> rulesFilters) { + this.rules = rulesFilters; + } + + public synchronized void deleteRules(String name) { + for (FilterRule rule : new ArrayList<>(this.rules)) { + if (rule.name.equals(name)) { + this.rules.remove(rule); + } + } + } + + public List<FilterRule> getRules(String name) { + ArrayList<FilterRule> temp = new ArrayList<>(); + for (FilterRule rule : new ArrayList<>(this.rules)) { + if (rule.name.equals(name)) { + temp.add(rule); + } + } + return temp; + } + + public synchronized void deleteRule(String name, String regex) { + for (FilterRule rule : new ArrayList<>(this.rules)) { + if (rule.name.equals(name) && rule.regex.equals(regex)) { + this.rules.remove(rule); + } + } + } + + public synchronized void addRule(String name, String regex) { + for (FilterRule rule : new ArrayList<>(this.rules)) { + if (rule.name.equals(name) && rule.regex.equals(regex)) { + return; + } + } + + this.rules.add(new FilterRule(name,regex)); + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("JsonProtocolFilter [rules=").append(rules).append("]"); + return builder.toString(); + } + +} diff --git a/policy-management/src/main/java/org/openecomp/policy/drools/protocol/coders/ProtocolCoderToolset.java b/policy-management/src/main/java/org/openecomp/policy/drools/protocol/coders/ProtocolCoderToolset.java new file mode 100644 index 00000000..9e079ff5 --- /dev/null +++ b/policy-management/src/main/java/org/openecomp/policy/drools/protocol/coders/ProtocolCoderToolset.java @@ -0,0 +1,668 @@ +package org.openecomp.policy.drools.protocol.coders; + +import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.lang.reflect.Type; +import java.time.Instant; +import java.time.ZonedDateTime; +import java.time.format.DateTimeFormatter; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import org.openecomp.policy.common.logging.eelf.MessageCodes; +import org.openecomp.policy.common.logging.flexlogger.FlexLogger; +import org.openecomp.policy.common.logging.flexlogger.Logger; +import org.openecomp.policy.drools.controller.DroolsController; +import org.openecomp.policy.drools.protocol.coders.EventProtocolCoder.CoderFilters; +import org.openecomp.policy.drools.protocol.coders.TopicCoderFilterConfiguration.CustomCoder; +import org.openecomp.policy.drools.protocol.coders.TopicCoderFilterConfiguration.CustomGsonCoder; +import org.openecomp.policy.drools.protocol.coders.TopicCoderFilterConfiguration.CustomJacksonCoder; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.JsonDeserializationContext; +import com.google.gson.JsonDeserializer; +import com.google.gson.JsonElement; +import com.google.gson.JsonParseException; +import com.google.gson.JsonParser; +import com.google.gson.JsonPrimitive; +import com.google.gson.JsonSerializationContext; +import com.google.gson.JsonSerializer; + +/** + * Protocol Coding/Decoding Toolset + */ +public abstract class ProtocolCoderToolset { + + /** + * topic + */ + protected final String topic; + + /** + * controller id + */ + protected final String controllerId; + + /** + * group id + */ + protected final String groupId; + + /** + * artifact id + */ + protected final String artifactId; + + /** + * Protocols and associated Filters + */ + protected final List<CoderFilters> coders = new ArrayList<CoderFilters>(); + + /** + * Tree model (instead of class model) generic parsing to be able to inspect elements + */ + protected JsonParser filteringParser = new JsonParser(); + + /** + * custom coder + */ + protected CustomCoder customCoder; + + /** + * Constructor + * + * @param topic the topic + * @param controllerId the controller id + * @param codedClass the decoded class + * @param filters list of filters that apply to the + * selection of this decodedClass in case of multiplicity + * @throws IllegalArgumentException if invalid data has been passed in + */ + public ProtocolCoderToolset(String topic, + String controllerId, + String groupId, + String artifactId, + String codedClass, + JsonProtocolFilter filters, + CustomCoder customCoder, + int modelClassLoaderHash) + throws IllegalArgumentException { + + if (topic == null || controllerId == null || + groupId == null || artifactId == null || + codedClass == null || filters == null || + topic.isEmpty() || controllerId.isEmpty()) { + // TODO + throw new IllegalArgumentException("Invalid input"); + } + + this.topic = topic; + this.controllerId = controllerId; + this.groupId = groupId; + this.artifactId = artifactId; + this.coders.add(new CoderFilters(codedClass, filters, modelClassLoaderHash)); + this.customCoder = customCoder; + } + + /** + * gets the coder + filters associated with this class name + * + * @param classname class name + * @return the decoder filters or null if not found + */ + public CoderFilters getCoder(String classname) { + for (CoderFilters decoder: this.coders) { + if (decoder.factClass.equals(classname)) { + return decoder; + } + } + return null; + } + + /** + * get all coder filters in use + * + * @return coder filters + */ + public List<CoderFilters> getCoders() { + return this.coders; + } + + /** + * add coder or replace it exists + * + * @param eventClass decoder + * @param filter filter + */ + public void addCoder(String eventClass, JsonProtocolFilter filter, int modelClassLoaderHash) { + synchronized(this) { + for (CoderFilters coder: this.coders) { + if (coder.factClass.equals(eventClass)) { + // this is a better check than checking pointers, just + // in case classloader is different and this is just an update + coder.factClass = eventClass; + coder.filter = filter; + coder.modelClassLoaderHash = modelClassLoaderHash; + return; + } + } + } + + this.coders.add(new CoderFilters(eventClass, filter, modelClassLoaderHash)); + } + + /** + * remove coder + * + * @param eventClass decoder + * @param filter filter + */ + public void removeCoders(String eventClass) { + synchronized(this) { + Iterator<CoderFilters> codersIt = this.coders.iterator(); + while (codersIt.hasNext()) { + CoderFilters coder = codersIt.next(); + if (coder.factClass.equals(eventClass)) { + codersIt.remove(); + } + } + } + } + + /** + * gets the topic + * + * @return the topic + */ + public String getTopic() {return topic;} + + /** + * gets the controller id + * + * @return the controller id + */ + public String getControllerId() {return controllerId;} + + /** + * @return the groupId + */ + public String getGroupId() { + return groupId; + } + + /** + * @return the artifactId + */ + public String getArtifactId() { + return artifactId; + } + + /** + * @return the customCoder + */ + public CustomCoder getCustomCoder() { + return customCoder; + } + + /** + * @param customCoder the customCoder to set + */ + public void setCustomCoder(CustomCoder customCoder) { + this.customCoder = customCoder; + } + + /** + * performs filtering on a json string + * + * @param json json string + * @return the decoder that passes the filter, otherwise null + * @throws UnsupportedOperationException can't filter + * @throws IllegalArgumentException invalid input + */ + protected CoderFilters filter(String json) + throws UnsupportedOperationException, IllegalArgumentException, IllegalStateException { + + + // 1. Get list of decoding classes for this controller Id and topic + // 2. If there are no classes, return error + // 3. Otherwise, from the available classes for decoding, pick the first one that + // passes the filters + + // Don't parse if it is not necessary + + if (this.coders.isEmpty()) { + // TODO this is an error + throw new IllegalStateException("No coders available"); + } + + if (this.coders.size() == 1) { + JsonProtocolFilter filter = this.coders.get(0).getFilter(); + if (!filter.isRules()) { + return this.coders.get(0); + } + } + + JsonElement event; + try { + event = this.filteringParser.parse(json); + } catch (Exception e) { + // TODO Auto-generated catch block + e.printStackTrace(); + throw new UnsupportedOperationException(e); + } + + for (CoderFilters decoder: this.coders) { + try { + boolean accepted = decoder.getFilter().accept(event); + if (accepted) { + return decoder; + } + } catch (Exception e) { + // TODO: handle exception + e.printStackTrace(); + } + } + + return null; + } + + /** + * Decode json into a POJO object + * @param json json string + * + * @return a POJO object for the json string + * @throws IllegalArgumentException if an invalid parameter has been received + * @throws UnsupportedOperationException if parsing into POJO is not possible + */ + public abstract Object decode(String json) + throws IllegalArgumentException, UnsupportedOperationException, IllegalStateException; + + /** + * Encodes a POJO object into a JSON String + * + * @param event JSON POJO event to be converted to String + * @return JSON string version of POJO object + * @throws IllegalArgumentException if an invalid parameter has been received + * @throws UnsupportedOperationException if parsing into POJO is not possible + */ + public abstract String encode(Object event) + throws IllegalArgumentException, UnsupportedOperationException; + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("ProtocolCoderToolset [topic=").append(topic).append(", controllerId=").append(controllerId) + .append(", groupId=").append(groupId).append(", artifactId=").append(artifactId).append(", coders=") + .append(coders).append(", filteringParser=").append(filteringParser).append(", customCoder=") + .append(customCoder).append("]"); + return builder.toString(); + } +} + +/** + * Tools used for encoding/decoding using Jackson + */ +class JacksonProtocolCoderToolset extends ProtocolCoderToolset { + private static Logger logger = FlexLogger.getLogger(JacksonProtocolCoderToolset.class); + /** + * decoder + */ + @JsonIgnore + protected final ObjectMapper decoder = new ObjectMapper(); + + /** + * encoder + */ + @JsonIgnore + protected final ObjectMapper encoder = new ObjectMapper(); + + /** + * Toolset to encode/decode tools associated with a topic + * + * @param topic topic + * @param decodedClass decoded class of an event + * @param filter + */ + public JacksonProtocolCoderToolset(String topic, String controllerId, + String groupId, String artifactId, + String decodedClass, + JsonProtocolFilter filter, + CustomJacksonCoder customJacksonCoder, + int modelClassLoaderHash) { + super(topic, controllerId, groupId, artifactId, decodedClass, filter, customJacksonCoder, modelClassLoaderHash); + decoder.registerModule(new JavaTimeModule()); + decoder.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, + false); + } + + /** + * gets the Jackson decoder + * + * @return the Jackson decoder + */ + @JsonIgnore + protected ObjectMapper getDecoder() {return decoder;} + + /** + * gets the Jackson encoder + * + * @return the Jackson encoder + */ + @JsonIgnore + protected ObjectMapper getEncoder() {return encoder;} + + /** + * {@inheritDoc} + */ + @Override + public Object decode(String json) + throws IllegalArgumentException, UnsupportedOperationException, IllegalStateException { + + // 0. Use custom coder if available + + if (this.customCoder != null) { + throw new UnsupportedOperationException + ("Jackon Custom Decoder is not supported at this time"); + } + + DroolsController droolsController = + DroolsController.factory.get(groupId, artifactId, ""); + if (droolsController == null) { + String error = "NO-DROOLS-CONTROLLER for: " + json + " IN " + this; + logger.warn(error); + throw new IllegalStateException(error); + } + + CoderFilters decoderFilter = filter(json); + if (decoderFilter == null) { + String error = "NO-DECODER for: " + json + " IN " + this; + logger.warn(error); + throw new UnsupportedOperationException(error); + } + + Class<?> decoderClass; + try { + decoderClass = + droolsController.fetchModelClass(decoderFilter.getCodedClass()); + if (decoderClass == null) { + String error = "DECODE-ERROR FETCHING MODEL CLASS: " + ":" + json + ":" + this; + logger.error(error); + throw new IllegalStateException(error); + } + } catch (Exception e) { + String error = "DECODE-ERROR FETCHING MODEL CLASS: "+ e.getMessage() + ":" + json + ":" + this; + logger.warn(MessageCodes.EXCEPTION_ERROR, e, error); + throw new UnsupportedOperationException(error, e); + } + + + try { + Object fact = this.decoder.readValue(json, decoderClass); + return fact; + } catch (Exception e) { + String error = "DECODE-ERROR FROM PDP-D FRAMEWORK: "+ json + ":" + e.getMessage() + ":" + this; + logger.error(MessageCodes.EXCEPTION_ERROR, e, error); + throw new UnsupportedOperationException(error, e); + } + } + + /** + * {@inheritDoc} + */ + @Override + public String encode(Object event) + throws IllegalArgumentException, UnsupportedOperationException { + + // 0. Use custom coder if available + + if (this.customCoder != null) { + throw new UnsupportedOperationException + ("Jackon Custom Encoder is not supported at this time"); + } + + try { + String encodedEvent = this.encoder.writeValueAsString(event); + return encodedEvent; + } catch (JsonProcessingException e) { + String error = "ENCODE-ERROR: "+ event + " IN " + this; + logger.error(MessageCodes.EXCEPTION_ERROR, e, error); + throw new UnsupportedOperationException(error, e); + } + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("JacksonProtocolCoderToolset [toString()=").append(super.toString()).append("]"); + return builder.toString(); + } + +} + +/** + * Tools used for encoding/decoding using Jackson + */ +class GsonProtocolCoderToolset extends ProtocolCoderToolset { + + private static Logger logger = FlexLogger.getLogger(GsonProtocolCoderToolset.class); + /** + * Formatter for JSON encoding/decoding + */ + @JsonIgnore + public static DateTimeFormatter format = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSSSSSxxx"); + + @JsonIgnore + public static DateTimeFormatter zuluFormat = DateTimeFormatter.ISO_INSTANT; + + /** + * Adapter for ZonedDateTime + */ + + public static class GsonUTCAdapter implements JsonSerializer<ZonedDateTime>, JsonDeserializer<ZonedDateTime> { + + public ZonedDateTime deserialize(JsonElement element, Type type, JsonDeserializationContext context) + throws JsonParseException { + try { + return ZonedDateTime.parse(element.getAsString(), format); + } catch (Exception e) { + System.err.println(e); + } + return null; + } + + public JsonElement serialize(ZonedDateTime datetime, Type type, JsonSerializationContext context) { + return new JsonPrimitive(datetime.format(format)); + } + } + + public static class GsonInstantAdapter implements JsonSerializer<Instant>, JsonDeserializer<Instant> { + + @Override + public Instant deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) + throws JsonParseException { + return Instant.ofEpochMilli(json.getAsLong()); + } + + @Override + public JsonElement serialize(Instant src, Type typeOfSrc, JsonSerializationContext context) { + return new JsonPrimitive(src.toEpochMilli()); + } + + } + + + /** + * decoder + */ + @JsonIgnore + protected final Gson decoder = new GsonBuilder().disableHtmlEscaping(). + registerTypeAdapter(ZonedDateTime.class, new GsonUTCAdapter()). + create(); + + /** + * encoder + */ + @JsonIgnore + protected final Gson encoder = new GsonBuilder().disableHtmlEscaping(). + registerTypeAdapter(ZonedDateTime.class, new GsonUTCAdapter()). + create(); + + /** + * Toolset to encode/decode tools associated with a topic + * + * @param topic topic + * @param decodedClass decoded class of an event + * @param filter + */ + public GsonProtocolCoderToolset(String topic, String controllerId, + String groupId, String artifactId, + String decodedClass, + JsonProtocolFilter filter, + CustomGsonCoder customGsonCoder, + int modelClassLoaderHash) { + super(topic, controllerId, groupId, artifactId, decodedClass, filter, customGsonCoder, modelClassLoaderHash); + } + + /** + * gets the Gson decoder + * + * @return the Gson decoder + */ + @JsonIgnore + protected Gson getDecoder() {return decoder;} + + /** + * gets the Gson encoder + * + * @return the Gson encoder + */ + @JsonIgnore + protected Gson getEncoder() {return encoder;} + + /** + * {@inheritDoc} + */ + @Override + public Object decode(String json) + throws IllegalArgumentException, UnsupportedOperationException, IllegalStateException { + + DroolsController droolsController = + DroolsController.factory.get(groupId, artifactId, ""); + if (droolsController == null) { + String error = "NO-DROOLS-CONTROLLER for: " + json + " IN " + this; + logger.warn(error); + throw new IllegalStateException(error); + } + + CoderFilters decoderFilter = filter(json); + if (decoderFilter == null) { + String error = "NO-DECODER for: " + json + " IN " + this; + logger.warn(error); + throw new UnsupportedOperationException(error); + } + + Class<?> decoderClass; + try { + decoderClass = + droolsController.fetchModelClass(decoderFilter.getCodedClass()); + if (decoderClass == null) { + String error = "DECODE-ERROR FETCHING MODEL CLASS: " + ":" + json + ":" + this; + logger.error(error); + throw new IllegalStateException(error); + } + } catch (Exception e) { + String error = "DECODE-ERROR FETCHING MODEL CLASS: "+ e.getMessage() + ":" + json + ":" + this; + logger.warn(MessageCodes.EXCEPTION_ERROR, e, error); + throw new UnsupportedOperationException(error, e); + } + + if (this.customCoder != null) { + try { + Class<?> gsonClassContainer = + droolsController.fetchModelClass(this.customCoder.getClassContainer()); + Field gsonField = gsonClassContainer.getField(this.customCoder.staticCoderField); + Object gsonObject = gsonField.get(null); + Method fromJsonMethod = gsonObject.getClass(). + getDeclaredMethod + ("fromJson", new Class[]{String.class, Class.class}); + Object fact = fromJsonMethod.invoke(gsonObject, json, decoderClass); + return fact; + } catch (NoSuchFieldException | SecurityException | IllegalAccessException | + NoSuchMethodException | InvocationTargetException e) { + String error = "DECODE-ERROR-FROM-CUSTOM-CODER: " + e.getMessage() + ":" + json + ":" + this; + logger.error(MessageCodes.EXCEPTION_ERROR, e, error); + throw new UnsupportedOperationException(error, e); + } + } else { + try { + Object fact = this.decoder.fromJson(json, decoderClass); + return fact; + } catch (Exception e) { + String error = "DECODE-ERROR FROM PDP-D FRAMEWORK: "+ json + ":" + e.getMessage() + ":" + this; + logger.error(MessageCodes.EXCEPTION_ERROR, e, error); + throw new UnsupportedOperationException(error, e); + } + } + } + + + + /** + * {@inheritDoc} + */ + @Override + public String encode(Object event) + throws IllegalArgumentException, UnsupportedOperationException { + + DroolsController droolsController = + DroolsController.factory.get(groupId, artifactId, ""); + if (droolsController == null) { + String error = "NO-DROOLS-CONTROLLER for: " + event + " IN " + this; + logger.warn(error); + throw new IllegalStateException(error); + } + + if (this.customCoder != null) { + try { + Class<?> gsonClassContainer = + droolsController.fetchModelClass(this.customCoder.getClassContainer()); + Field gsonField = gsonClassContainer.getField(this.customCoder.staticCoderField); + Object gsonObject = gsonField.get(null); + Method toJsonMethod = gsonObject.getClass(). + getDeclaredMethod + ("toJson", new Class[]{Object.class}); + String encodedJson = (String) toJsonMethod.invoke(gsonObject, event); + return encodedJson; + } catch (NoSuchFieldException | SecurityException | IllegalAccessException | + NoSuchMethodException | InvocationTargetException e) { + String error = "DECODE-ERROR-FROM-CUSTOM-CODER: " + e.getMessage() + ":" + event + ":" + this; + logger.error(MessageCodes.EXCEPTION_ERROR, e, error); + throw new UnsupportedOperationException(error, e); + } + } else { + try { + String encodedEvent = this.encoder.toJson(event); + return encodedEvent; + } catch (Exception e) { + String error = "ENCODE-ERROR: "+ event + " IN " + this; + logger.error(MessageCodes.EXCEPTION_ERROR, e, error); + throw new UnsupportedOperationException(error, e); + } + } + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("GsonProtocolCoderToolset [toString()=").append(super.toString()).append("]"); + return builder.toString(); + } +} diff --git a/policy-management/src/main/java/org/openecomp/policy/drools/protocol/coders/TopicCoderFilterConfiguration.java b/policy-management/src/main/java/org/openecomp/policy/drools/protocol/coders/TopicCoderFilterConfiguration.java new file mode 100644 index 00000000..3c112573 --- /dev/null +++ b/policy-management/src/main/java/org/openecomp/policy/drools/protocol/coders/TopicCoderFilterConfiguration.java @@ -0,0 +1,309 @@ +/*- + * ============LICENSE_START======================================================= + * policy-management + * ================================================================================ + * 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.protocol.coders; + +import java.util.List; + +public class TopicCoderFilterConfiguration { + + /** + * Custom coder, contains class and static field to access parser that the controller + * desires to use instead of the framework provided parser + */ + public static abstract class CustomCoder { + protected String className; + protected String staticCoderField; + + /** + * create custom coder from raw string in the following format + * (typically embedded in a property file): + * + * Note this is to support decoding/encoding of partial structures that are + * only known by the model. + * + * @param rawCustomCoder with format: <class-containing-custom-coder>,<static-coder-field> + */ + public CustomCoder(String rawCustomCoder) throws IllegalArgumentException { + if (rawCustomCoder != null && !rawCustomCoder.isEmpty()) { + + this.className = rawCustomCoder.substring(0,rawCustomCoder.indexOf(",")); + if (this.className == null || this.className.isEmpty()) { + throw new IllegalArgumentException("No classname to create CustomCoder cannot be created"); + } + + this.staticCoderField = rawCustomCoder.substring(rawCustomCoder.indexOf(",")+1); + if (this.staticCoderField == null || this.staticCoderField.isEmpty()) { + throw new IllegalArgumentException + ("No staticCoderField to create CustomCoder cannot be created for class " + + className); + } + + } + } + /** + * @param classContainer + * @param staticCoderField + */ + public CustomCoder(String className, String staticCoderField) throws IllegalArgumentException { + if (className == null || className.isEmpty()) { + throw new IllegalArgumentException("No classname to create CustomCoder cannot be created"); + } + + if (staticCoderField == null || staticCoderField.isEmpty()) { + throw new IllegalArgumentException + ("No staticCoderField to create CustomCoder cannot be created for class " + + className); + } + + this.className = className; + this.staticCoderField = staticCoderField; + } + + /** + * @return the className + */ + public String getClassContainer() { + return className; + } + + /** + * @param className the className to set + */ + public void setClassContainer(String className) { + this.className = className; + } + + /** + * @return the staticCoderField + */ + public String getStaticCoderField() { + return staticCoderField; + } + + /** + * @param staticCoderField the staticGson to set + */ + public void setStaticCoderField(String staticCoderField) { + this.staticCoderField = staticCoderField; + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("CustomCoder [className=").append(className).append(", staticCoderField=") + .append(staticCoderField).append("]"); + return builder.toString(); + } + } + + public static class CustomGsonCoder extends CustomCoder { + + public CustomGsonCoder(String className, String staticCoderField) { + super(className, staticCoderField); + } + + public CustomGsonCoder(String customGson) throws IllegalArgumentException { + super(customGson); + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("CustomGsonCoder [toString()=").append(super.toString()).append("]"); + return builder.toString(); + } + + } + + public static class CustomJacksonCoder extends CustomCoder { + + public CustomJacksonCoder(String className, String staticCoderField) { + super(className, staticCoderField); + } + + public CustomJacksonCoder(String customJackson) throws IllegalArgumentException { + super(customJackson); + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("CustomJacksonCoder [toString()=").append(super.toString()).append("]"); + return builder.toString(); + } + + } + + /** + * Coder/Decoder class and Filter container. The decoder class is potential, + * in order to be operational needs to be fetched from an available + * class loader. + * + */ + public static class PotentialCoderFilter { + + /** + * decoder class (pending from being able to be fetched and found + * in some class loader) + */ + protected String codedClass; + + /** + * filters to apply to the selection of the decodedClass; + */ + protected JsonProtocolFilter filter; + + /** + * constructor + * + * @param codedClass decoder class + * @param filter filters to apply + */ + public PotentialCoderFilter(String codedClass, JsonProtocolFilter filter) { + this.codedClass = codedClass; + this.filter = filter; + } + + /** + * @return the decodedClass + */ + public String getCodedClass() { + return codedClass; + } + + /** + * @param decodedClass the decodedClass to set + */ + public void setCodedClass(String decodedClass) { + this.codedClass = decodedClass; + } + + /** + * @return the filter + */ + public JsonProtocolFilter getFilter() { + return filter; + } + + /** + * @param filter the filter to set + */ + public void setFilter(JsonProtocolFilter filter) { + this.filter = filter; + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("PotentialCoderFilter [codedClass=").append(codedClass).append(", filter=").append(filter) + .append("]"); + return builder.toString(); + } + } + + /** + * the source topic + */ + protected final String topic; + + /** + * List of decoder -> filters + */ + protected final List<PotentialCoderFilter> coderFilters; + + /** + * custom gson coder that this controller prefers to use instead of the framework ones + */ + protected CustomGsonCoder customGsonCoder; + + /** + * custom jackson coder that this controller prefers to use instead of the framework ones + */ + protected CustomJacksonCoder customJacksonCoder; + + /** + * Constructor + * + * @param decoderFilters list of decoders and associated filters + * @param topic the topic + */ + public TopicCoderFilterConfiguration(String topic, List<PotentialCoderFilter> decoderFilters, + CustomGsonCoder customGsonCoder, + CustomJacksonCoder customJacksonCoder) { + this.coderFilters = decoderFilters; + this.topic = topic; + this.customGsonCoder = customGsonCoder; + this.customJacksonCoder = customJacksonCoder; + } + + /** + * @return the topic + */ + public String getTopic() { + return topic; + } + + /** + * @return the decoderFilters + */ + public List<PotentialCoderFilter> getCoderFilters() { + return coderFilters; + } + + /** + * @return the customGsonCoder + */ + public CustomGsonCoder getCustomGsonCoder() { + return customGsonCoder; + } + + /** + * @param customGsonCoder the customGsonCoder to set + */ + public void setCustomGsonCoder(CustomGsonCoder customGsonCoder) { + this.customGsonCoder = customGsonCoder; + } + + /** + * @return the customJacksonCoder + */ + public CustomJacksonCoder getCustomJacksonCoder() { + return customJacksonCoder; + } + + /** + * @param customJacksonCoder the customJacksonCoder to set + */ + public void setCustomJacksonCoder(CustomJacksonCoder customJacksonCoder) { + this.customJacksonCoder = customJacksonCoder; + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("TopicCoderFilterConfiguration [topic=").append(topic).append(", coderFilters=") + .append(coderFilters).append(", customGsonCoder=").append(customGsonCoder) + .append(", customJacksonCoder=").append(customJacksonCoder).append("]"); + return builder.toString(); + } + + +} diff --git a/policy-management/src/main/java/org/openecomp/policy/drools/protocol/configuration/ControllerConfiguration.java b/policy-management/src/main/java/org/openecomp/policy/drools/protocol/configuration/ControllerConfiguration.java new file mode 100644 index 00000000..98af02ee --- /dev/null +++ b/policy-management/src/main/java/org/openecomp/policy/drools/protocol/configuration/ControllerConfiguration.java @@ -0,0 +1,280 @@ +/*- + * ============LICENSE_START======================================================= + * policy-management + * ================================================================================ + * 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.protocol.configuration; + +import java.util.HashMap; +import java.util.Map; + +import org.apache.commons.lang3.builder.EqualsBuilder; +import org.apache.commons.lang3.builder.HashCodeBuilder; +import org.apache.commons.lang3.builder.ToStringBuilder; + +import com.fasterxml.jackson.annotation.JsonAnyGetter; +import com.fasterxml.jackson.annotation.JsonAnySetter; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + + +/** + * Drools Related Information + * + */ +@JsonInclude(JsonInclude.Include.NON_NULL) +public class ControllerConfiguration { + + public static final String CONFIG_CONTROLLER_OPERATION_CREATE = "create"; + public static final String CONFIG_CONTROLLER_OPERATION_UPDATE = "update"; + public static final String CONFIG_CONTROLLER_OPERATION_LOCK = "lock"; + public static final String CONFIG_CONTROLLER_OPERATION_UNLOCK = "unlock"; + + /** + * + * (Required) + * + */ + @JsonProperty("name") + private String name; + /** + * Set of operations that can be applied to a controller: create, lock + * (Required) + * + */ + @JsonProperty("operation") + private String operation; + /** + * Maven Related Information + * + */ + @JsonProperty("drools") + private DroolsConfiguration drools; + @JsonIgnore + private Map<String, Object> additionalProperties = new HashMap<String, Object>(); + protected final static Object NOT_FOUND_VALUE = new Object(); + + /** + * No args constructor for use in serialization + * + */ + public ControllerConfiguration() { + } + + /** + * + * @param name + * @param drools + * @param operation + */ + public ControllerConfiguration(String name, String operation, DroolsConfiguration drools) { + this.name = name; + this.operation = operation; + this.drools = drools; + } + + /** + * + * (Required) + * + * @return + * The name + */ + @JsonProperty("name") + public String getName() { + return name; + } + + /** + * + * (Required) + * + * @param name + * The name + */ + @JsonProperty("name") + public void setName(String name) { + this.name = name; + } + + public ControllerConfiguration withName(String name) { + this.name = name; + return this; + } + + /** + * Set of operations that can be applied to a controller: create, lock + * (Required) + * + * @return + * The operation + */ + @JsonProperty("operation") + public String getOperation() { + return operation; + } + + /** + * Set of operations that can be applied to a controller: create, lock + * (Required) + * + * @param operation + * The operation + */ + @JsonProperty("operation") + public void setOperation(String operation) { + this.operation = operation; + } + + public ControllerConfiguration withOperation(String operation) { + this.operation = operation; + return this; + } + + /** + * Maven Related Information + * + * @return + * The drools + */ + @JsonProperty("drools") + public DroolsConfiguration getDrools() { + return drools; + } + + /** + * Maven Related Information + * + * @param drools + * The drools + */ + @JsonProperty("drools") + public void setDrools(DroolsConfiguration drools) { + this.drools = drools; + } + + public ControllerConfiguration withDrools(DroolsConfiguration drools) { + this.drools = drools; + return this; + } + + @Override + public String toString() { + return ToStringBuilder.reflectionToString(this); + } + + @JsonAnyGetter + public Map<String, Object> getAdditionalProperties() { + return this.additionalProperties; + } + + @JsonAnySetter + public void setAdditionalProperty(String name, Object value) { + this.additionalProperties.put(name, value); + } + + public ControllerConfiguration withAdditionalProperty(String name, Object value) { + this.additionalProperties.put(name, value); + return this; + } + + protected boolean declaredProperty(String name, Object value) { + switch (name) { + case "name": + if (value instanceof String) { + setName(((String) value)); + } else { + throw new IllegalArgumentException(("property \"name\" is of type \"java.lang.String\", but got "+ value.getClass().toString())); + } + return true; + case "operation": + if (value instanceof String) { + setOperation(((String) value)); + } else { + throw new IllegalArgumentException(("property \"operation\" is of type \"java.lang.String\", but got "+ value.getClass().toString())); + } + return true; + case "drools": + if (value instanceof DroolsConfiguration) { + setDrools(((DroolsConfiguration) value)); + } else { + throw new IllegalArgumentException(("property \"drools\" is of type \"org.openecomp.policy.drools.protocol.configuration.Drools\", but got "+ value.getClass().toString())); + } + return true; + default: + return false; + } + } + + protected Object declaredPropertyOrNotFound(String name, Object notFoundValue) { + switch (name) { + case "name": + return getName(); + case "operation": + return getOperation(); + case "drools": + return getDrools(); + default: + return notFoundValue; + } + } + + @SuppressWarnings({ + "unchecked" + }) + public<T >T get(String name) { + Object value = declaredPropertyOrNotFound(name, ControllerConfiguration.NOT_FOUND_VALUE); + if (ControllerConfiguration.NOT_FOUND_VALUE!= value) { + return ((T) value); + } else { + return ((T) getAdditionalProperties().get(name)); + } + } + + public void set(String name, Object value) { + if (!declaredProperty(name, value)) { + getAdditionalProperties().put(name, ((Object) value)); + } + } + + public ControllerConfiguration with(String name, Object value) { + if (!declaredProperty(name, value)) { + getAdditionalProperties().put(name, ((Object) value)); + } + return this; + } + + @Override + public int hashCode() { + return new HashCodeBuilder().append(name).append(operation).append(drools).append(additionalProperties).toHashCode(); + } + + @Override + public boolean equals(Object other) { + if (other == this) { + return true; + } + if ((other instanceof ControllerConfiguration) == false) { + return false; + } + ControllerConfiguration rhs = ((ControllerConfiguration) other); + return new EqualsBuilder().append(name, rhs.name).append(operation, rhs.operation).append(drools, rhs.drools).append(additionalProperties, rhs.additionalProperties).isEquals(); + } + +} diff --git a/policy-management/src/main/java/org/openecomp/policy/drools/protocol/configuration/DroolsConfiguration.java b/policy-management/src/main/java/org/openecomp/policy/drools/protocol/configuration/DroolsConfiguration.java new file mode 100644 index 00000000..87cf2348 --- /dev/null +++ b/policy-management/src/main/java/org/openecomp/policy/drools/protocol/configuration/DroolsConfiguration.java @@ -0,0 +1,278 @@ +/*- + * ============LICENSE_START======================================================= + * policy-management + * ================================================================================ + * 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.protocol.configuration; + +import java.util.HashMap; +import java.util.Map; + +import org.apache.commons.lang3.builder.EqualsBuilder; +import org.apache.commons.lang3.builder.HashCodeBuilder; +import org.apache.commons.lang3.builder.ToStringBuilder; + +import com.fasterxml.jackson.annotation.JsonAnyGetter; +import com.fasterxml.jackson.annotation.JsonAnySetter; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + + +/** + * Maven Related Information + * + */ +@JsonInclude(JsonInclude.Include.NON_NULL) +public class DroolsConfiguration { + + /** + * Maven Artifact ID + * (Required) + * + */ + @JsonProperty("artifactId") + private String artifactId; + /** + * Maven Group ID + * (Required) + * + */ + @JsonProperty("groupId") + private String groupId; + /** + * Maven Version + * (Required) + * + */ + @JsonProperty("version") + private String version; + @JsonIgnore + private Map<String, Object> additionalProperties = new HashMap<String, Object>(); + protected final static Object NOT_FOUND_VALUE = new Object(); + + /** + * No args constructor for use in serialization + * + */ + public DroolsConfiguration() { + } + + /** + * + * @param groupId + * @param artifactId + * @param version + */ + public DroolsConfiguration(String artifactId, String groupId, String version) { + this.artifactId = artifactId; + this.groupId = groupId; + this.version = version; + } + + /** + * Maven Artifact ID + * (Required) + * + * @return + * The artifactId + */ + @JsonProperty("artifactId") + public String getArtifactId() { + return artifactId; + } + + /** + * Maven Artifact ID + * (Required) + * + * @param artifactId + * The artifactId + */ + @JsonProperty("artifactId") + public void setArtifactId(String artifactId) { + this.artifactId = artifactId; + } + + public DroolsConfiguration withArtifactId(String artifactId) { + this.artifactId = artifactId; + return this; + } + + /** + * Maven Group ID + * (Required) + * + * @return + * The groupId + */ + @JsonProperty("groupId") + public String getGroupId() { + return groupId; + } + + /** + * Maven Group ID + * (Required) + * + * @param groupId + * The groupId + */ + @JsonProperty("groupId") + public void setGroupId(String groupId) { + this.groupId = groupId; + } + + public DroolsConfiguration withGroupId(String groupId) { + this.groupId = groupId; + return this; + } + + /** + * Maven Version + * (Required) + * + * @return + * The version + */ + @JsonProperty("version") + public String getVersion() { + return version; + } + + /** + * Maven Version + * (Required) + * + * @param version + * The version + */ + @JsonProperty("version") + public void setVersion(String version) { + this.version = version; + } + + public DroolsConfiguration withVersion(String version) { + this.version = version; + return this; + } + + @Override + public String toString() { + return ToStringBuilder.reflectionToString(this); + } + + @JsonAnyGetter + public Map<String, Object> getAdditionalProperties() { + return this.additionalProperties; + } + + @JsonAnySetter + public void setAdditionalProperty(String name, Object value) { + this.additionalProperties.put(name, value); + } + + public DroolsConfiguration withAdditionalProperty(String name, Object value) { + this.additionalProperties.put(name, value); + return this; + } + + protected boolean declaredProperty(String name, Object value) { + switch (name) { + case "artifactId": + if (value instanceof String) { + setArtifactId(((String) value)); + } else { + throw new IllegalArgumentException(("property \"artifactId\" is of type \"java.lang.String\", but got "+ value.getClass().toString())); + } + return true; + case "groupId": + if (value instanceof String) { + setGroupId(((String) value)); + } else { + throw new IllegalArgumentException(("property \"groupId\" is of type \"java.lang.String\", but got "+ value.getClass().toString())); + } + return true; + case "version": + if (value instanceof String) { + setVersion(((String) value)); + } else { + throw new IllegalArgumentException(("property \"version\" is of type \"java.lang.String\", but got "+ value.getClass().toString())); + } + return true; + default: + return false; + } + } + + protected Object declaredPropertyOrNotFound(String name, Object notFoundValue) { + switch (name) { + case "artifactId": + return getArtifactId(); + case "groupId": + return getGroupId(); + case "version": + return getVersion(); + default: + return notFoundValue; + } + } + + @SuppressWarnings({ + "unchecked" + }) + public<T >T get(String name) { + Object value = declaredPropertyOrNotFound(name, DroolsConfiguration.NOT_FOUND_VALUE); + if (DroolsConfiguration.NOT_FOUND_VALUE!= value) { + return ((T) value); + } else { + return ((T) getAdditionalProperties().get(name)); + } + } + + public void set(String name, Object value) { + if (!declaredProperty(name, value)) { + getAdditionalProperties().put(name, ((Object) value)); + } + } + + public DroolsConfiguration with(String name, Object value) { + if (!declaredProperty(name, value)) { + getAdditionalProperties().put(name, ((Object) value)); + } + return this; + } + + @Override + public int hashCode() { + return new HashCodeBuilder().append(artifactId).append(groupId).append(version).append(additionalProperties).toHashCode(); + } + + @Override + public boolean equals(Object other) { + if (other == this) { + return true; + } + if ((other instanceof DroolsConfiguration) == false) { + return false; + } + DroolsConfiguration rhs = ((DroolsConfiguration) other); + return new EqualsBuilder().append(artifactId, rhs.artifactId).append(groupId, rhs.groupId).append(version, rhs.version).append(additionalProperties, rhs.additionalProperties).isEquals(); + } + +} diff --git a/policy-management/src/main/java/org/openecomp/policy/drools/protocol/configuration/PdpdConfiguration.java b/policy-management/src/main/java/org/openecomp/policy/drools/protocol/configuration/PdpdConfiguration.java new file mode 100644 index 00000000..65de6656 --- /dev/null +++ b/policy-management/src/main/java/org/openecomp/policy/drools/protocol/configuration/PdpdConfiguration.java @@ -0,0 +1,283 @@ +/*- + * ============LICENSE_START======================================================= + * policy-management + * ================================================================================ + * 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.protocol.configuration; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import com.fasterxml.jackson.annotation.JsonAnyGetter; +import com.fasterxml.jackson.annotation.JsonAnySetter; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import org.apache.commons.lang3.builder.EqualsBuilder; +import org.apache.commons.lang3.builder.HashCodeBuilder; +import org.apache.commons.lang3.builder.ToStringBuilder; + + +/** + * ENGINE-CONFIGURATION + * <p> + * + * + */ +@JsonInclude(JsonInclude.Include.NON_NULL) +public class PdpdConfiguration { + + /** + * Controller Entity ID + */ + public static final String CONFIG_ENTITY_CONTROLLER = "controller"; + + /** + * Unique Transaction ID. This is an UUID. + * (Required) + * + */ + @JsonProperty("requestID") + private String requestID; + /** + * Set of entities on which configuration can be performed: controller + * (Required) + * + */ + @JsonProperty("entity") + private String entity; + /** + * Controller Information, only applicable when the entity is set to controller + * + */ + @JsonProperty("controllers") + private List<ControllerConfiguration> controllers = new ArrayList<ControllerConfiguration>(); + @JsonIgnore + private Map<String, Object> additionalProperties = new HashMap<String, Object>(); + protected final static Object NOT_FOUND_VALUE = new Object(); + + /** + * No args constructor for use in serialization + * + */ + public PdpdConfiguration() { + } + + /** + * + * @param controller + * @param requestID + * @param entity + */ + public PdpdConfiguration(String requestID, String entity, List<ControllerConfiguration> controllers) { + this.requestID = requestID; + this.entity = entity; + this.controllers = controllers; + } + + /** + * Unique Transaction ID. This is an UUID. + * (Required) + * + * @return + * The requestID + */ + @JsonProperty("requestID") + public String getRequestID() { + return requestID; + } + + /** + * Unique Transaction ID. This is an UUID. + * (Required) + * + * @param requestID + * The requestID + */ + @JsonProperty("requestID") + public void setRequestID(String requestID) { + this.requestID = requestID; + } + + public PdpdConfiguration withRequestID(String requestID) { + this.requestID = requestID; + return this; + } + + /** + * Set of entities on which configuration can be performed: controller + * (Required) + * + * @return + * The entity + */ + @JsonProperty("entity") + public String getEntity() { + return entity; + } + + /** + * Set of entities on which configuration can be performed: controller + * (Required) + * + * @param entity + * The entity + */ + @JsonProperty("entity") + public void setEntity(String entity) { + this.entity = entity; + } + + public PdpdConfiguration withEntity(String entity) { + this.entity = entity; + return this; + } + + /** + * Controller Information, only applicable when the entity is set to controller + * + * @return + * The controller + */ + @JsonProperty("controller") + public List<ControllerConfiguration> getControllers() { + return controllers; + } + + /** + * Controller Information, only applicable when the entity is set to controller + * + * @param controller + * The controller + */ + @JsonProperty("controller") + public void setControllers(List<ControllerConfiguration> controllers) { + this.controllers = controllers; + } + + public PdpdConfiguration withController(List<ControllerConfiguration> controllers) { + this.controllers = controllers; + return this; + } + + @Override + public String toString() { + return ToStringBuilder.reflectionToString(this); + } + + @JsonAnyGetter + public Map<String, Object> getAdditionalProperties() { + return this.additionalProperties; + } + + @JsonAnySetter + public void setAdditionalProperty(String name, Object value) { + this.additionalProperties.put(name, value); + } + + public PdpdConfiguration withAdditionalProperty(String name, Object value) { + this.additionalProperties.put(name, value); + return this; + } + + @SuppressWarnings("unchecked") + protected boolean declaredProperty(String name, Object value) { + switch (name) { + case "requestID": + if (value instanceof String) { + setRequestID(((String) value)); + } else { + throw new IllegalArgumentException(("property \"requestID\" is of type \"java.lang.String\", but got "+ value.getClass().toString())); + } + return true; + case "entity": + if (value instanceof String) { + setEntity(((String) value)); + } else { + throw new IllegalArgumentException(("property \"entity\" is of type \"java.lang.String\", but got "+ value.getClass().toString())); + } + return true; + case "controllers": + if (value instanceof List) { + setControllers(((List<ControllerConfiguration> ) value)); + } else { + throw new IllegalArgumentException(("property \"controllers\" is of type \"java.util.List<org.openecomp.policy.drools.protocol.configuration.Controller>\", but got "+ value.getClass().toString())); + } + return true; + default: + return false; + } + } + + protected Object declaredPropertyOrNotFound(String name, Object notFoundValue) { + switch (name) { + case "requestID": + return getRequestID(); + case "entity": + return getEntity(); + case "controllers": + return getControllers(); + default: + return notFoundValue; + } + } + + @SuppressWarnings({ + "unchecked" + }) + public<T >T get(String name) { + Object value = declaredPropertyOrNotFound(name, PdpdConfiguration.NOT_FOUND_VALUE); + if (PdpdConfiguration.NOT_FOUND_VALUE!= value) { + return ((T) value); + } else { + return ((T) getAdditionalProperties().get(name)); + } + } + + public void set(String name, Object value) { + if (!declaredProperty(name, value)) { + getAdditionalProperties().put(name, ((Object) value)); + } + } + + public PdpdConfiguration with(String name, Object value) { + if (!declaredProperty(name, value)) { + getAdditionalProperties().put(name, ((Object) value)); + } + return this; + } + + @Override + public int hashCode() { + return new HashCodeBuilder().append(requestID).append(entity).append(controllers).append(additionalProperties).toHashCode(); + } + + @Override + public boolean equals(Object other) { + if (other == this) { + return true; + } + if ((other instanceof PdpdConfiguration) == false) { + return false; + } + PdpdConfiguration rhs = ((PdpdConfiguration) other); + return new EqualsBuilder().append(requestID, rhs.requestID).append(entity, rhs.entity).append(controllers, rhs.controllers).append(additionalProperties, rhs.additionalProperties).isEquals(); + } + +} 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 new file mode 100644 index 00000000..48e6313a --- /dev/null +++ b/policy-management/src/main/java/org/openecomp/policy/drools/server/restful/RestManager.java @@ -0,0 +1,1181 @@ +/*- + * ============LICENSE_START======================================================= + * policy-management + * ================================================================================ + * 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.server.restful; + +import java.util.ArrayList; +import java.util.List; +import java.util.Properties; +import java.util.UUID; +import java.util.regex.Pattern; + +import javax.ws.rs.Consumes; +import javax.ws.rs.DELETE; +import javax.ws.rs.DefaultValue; +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.PUT; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.QueryParam; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.Response.Status; + +import org.openecomp.policy.common.logging.eelf.MessageCodes; +import org.openecomp.policy.common.logging.flexlogger.FlexLogger; +import org.openecomp.policy.common.logging.flexlogger.Logger; +import org.openecomp.policy.drools.controller.DroolsController; +import org.openecomp.policy.drools.event.comm.TopicEndpoint; +import org.openecomp.policy.drools.event.comm.TopicSink; +import org.openecomp.policy.drools.event.comm.TopicSource; +import org.openecomp.policy.drools.event.comm.bus.DmaapTopicSink; +import org.openecomp.policy.drools.event.comm.bus.DmaapTopicSource; +import org.openecomp.policy.drools.event.comm.bus.UebTopicSink; +import org.openecomp.policy.drools.event.comm.bus.UebTopicSource; +import org.openecomp.policy.drools.properties.PolicyProperties; +import org.openecomp.policy.drools.protocol.coders.EventProtocolCoder; +import org.openecomp.policy.drools.protocol.coders.EventProtocolCoder.CoderFilters; +import org.openecomp.policy.drools.protocol.coders.JsonProtocolFilter; +import org.openecomp.policy.drools.protocol.coders.JsonProtocolFilter.FilterRule; +import org.openecomp.policy.drools.protocol.coders.ProtocolCoderToolset; +import org.openecomp.policy.drools.protocol.configuration.ControllerConfiguration; +import org.openecomp.policy.drools.protocol.configuration.PdpdConfiguration; +import org.openecomp.policy.drools.system.PolicyController; +import org.openecomp.policy.drools.system.PolicyEngine; + + +/** + * REST Endpoint for management of the Drools PDP + */ +@Path("/policy/pdp") +public class RestManager { + /** + * Logger + */ + private static Logger logger = FlexLogger.getLogger(RestManager.class); + + /** + * gets the Policy Engine + * + * @return the Policy Engine + */ + @GET + @Path("engine") + @Produces(MediaType.APPLICATION_JSON) + public PolicyEngine engine() { + return PolicyEngine.manager; + } + + + /** + * Updates the Policy Engine + * + * @param configuration configuration + * @return Policy Engine + */ + @PUT + @Path("engine") + @Produces(MediaType.APPLICATION_JSON) + @Consumes(MediaType.APPLICATION_JSON) + public Response updateEngine(PdpdConfiguration configuration) { + PolicyController controller = null; + boolean success = true; + try { + success = PolicyEngine.manager.configure(configuration); + } catch (Exception e) { + success = false; + logger.warn(MessageCodes.EXCEPTION_ERROR, e, + "PolicyEngine", this.toString()); + } + + if (!success) + return Response.status(Response.Status.NOT_ACCEPTABLE). + entity(new Error("cannot perform operation")).build(); + else + return Response.status(Response.Status.OK).entity(controller).build(); + } + + /** + * Activates the Policy Engine + * + * @param configuration configuration + * @return Policy Engine + */ + @PUT + @Path("engine/activation") + @Produces(MediaType.APPLICATION_JSON) + public Response activateEngine() { + boolean success = true; + try { + PolicyEngine.manager.activate(); + } catch (Exception e) { + success = false; + logger.warn(MessageCodes.EXCEPTION_ERROR, e, + "PolicyEngine", this.toString()); + } + + if (!success) + return Response.status(Response.Status.NOT_ACCEPTABLE). + entity(new Error("cannot perform operation")).build(); + else + return Response.status(Response.Status.OK).entity(PolicyEngine.manager).build(); + } + + /** + * Activates the Policy Engine + * + * @param configuration configuration + * @return Policy Engine + */ + @PUT + @Path("engine/deactivation") + @Produces(MediaType.APPLICATION_JSON) + public Response deactivateEngine() { + boolean success = true; + try { + PolicyEngine.manager.deactivate(); + } catch (Exception e) { + success = false; + logger.warn(MessageCodes.EXCEPTION_ERROR, e, + "PolicyEngine", this.toString()); + } + + if (!success) + return Response.status(Response.Status.NOT_ACCEPTABLE). + entity(new Error("cannot perform operation")).build(); + else + return Response.status(Response.Status.OK).entity(PolicyEngine.manager).build(); + } + + @DELETE + @Path("engine") + @Produces(MediaType.APPLICATION_JSON) + public Response engineShutdown() { + try { + PolicyEngine.manager.shutdown(); + } catch (IllegalStateException e) { + logger.warn(MessageCodes.EXCEPTION_ERROR, e, + "shutdown: " + PolicyEngine.manager); + return Response.status(Response.Status.BAD_REQUEST). + entity(PolicyEngine.manager). + build(); + } + + return Response.status(Response.Status.OK). + entity(PolicyEngine.manager). + build(); + } + + @PUT + @Path("engine/lock") + @Produces(MediaType.APPLICATION_JSON) + @Consumes(MediaType.APPLICATION_JSON) + public Response lockEngine() { + boolean success = PolicyEngine.manager.lock(); + if (success) + return Response.status(Status.OK). + entity("Policy Engine is locked"). + build(); + else + return Response.status(Status.SERVICE_UNAVAILABLE). + entity("Policy Engine cannot be locked"). + build(); + } + + @DELETE + @Path("engine/unlock") + @Produces(MediaType.APPLICATION_JSON) + @Consumes(MediaType.APPLICATION_JSON) + public Response unlockEngine() { + boolean success = PolicyEngine.manager.unlock(); + if (success) + return Response.status(Status.OK). + entity("Policy Engine is unlocked"). + build(); + else + return Response.status(Status.SERVICE_UNAVAILABLE). + entity("Policy Engine cannot be unlocked"). + build(); + } + + @GET + @Path("engine/controllers") + @Produces(MediaType.APPLICATION_JSON) + public List<PolicyController> controllers() { + return PolicyEngine.manager.getPolicyControllers(); + } + + @POST + @Path("engine/controllers") + @Produces(MediaType.APPLICATION_JSON) + @Consumes(MediaType.APPLICATION_JSON) + public Response addController(Properties config) { + if (config == null) + return Response.status(Response.Status.BAD_REQUEST). + entity(new Error("A configuration must be provided")). + build(); + + String controllerName = config.getProperty(PolicyProperties.PROPERTY_CONTROLLER_NAME); + if (controllerName == null || controllerName.isEmpty()) + return Response.status(Response.Status.BAD_REQUEST). + entity(new Error + ("Configuration must have an entry for " + + PolicyProperties.PROPERTY_CONTROLLER_NAME)). + build(); + + PolicyController controller; + try { + controller = PolicyController.factory.get(controllerName); + if (controller != null) + return Response.status(Response.Status.NOT_MODIFIED). + entity(controller). + build(); + } catch (IllegalArgumentException e) { + // This is OK + } catch (IllegalStateException e) { + logger.warn(MessageCodes.EXCEPTION_ERROR, e, + controllerName, this.toString()); + return Response.status(Response.Status.NOT_ACCEPTABLE). + entity(new Error(controllerName + " not found")).build(); + } + + try { + controller = PolicyEngine.manager.createPolicyController + (config.getProperty(PolicyProperties.PROPERTY_CONTROLLER_NAME), config); + } 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(); + } + + try { + boolean success = controller.start(); + if (!success) { + logger.warn("Can't start " + controllerName + ": " + controller.toString()); + return Response.status(Response.Status.PARTIAL_CONTENT). + entity(new Error(controllerName + " can't be started")).build(); + } + } catch (IllegalStateException e) { + logger.warn(MessageCodes.EXCEPTION_ERROR, e, + controllerName, this.toString()); + return Response.status(Response.Status.PARTIAL_CONTENT). + entity(controller).build(); + } + + return Response.status(Response.Status.CREATED). + entity(controller). + build(); + } + + @GET + @Path("engine/controllers/{controllerName}") + @Produces(MediaType.APPLICATION_JSON) + public Response controller(@PathParam("controllerName") String controllerName) { + PolicyController controller = null; + try { + controller = PolicyController.factory.get(controllerName); + } catch (IllegalArgumentException e) { + logger.info("Can't retrieve controller " + controllerName + + ". Reason: " + e.getMessage()); + } catch (IllegalStateException e) { + logger.warn(MessageCodes.EXCEPTION_ERROR, e, + controllerName, this.toString()); + return Response.status(Response.Status.NOT_ACCEPTABLE). + entity(new Error(controllerName + " not acceptable")).build(); + } + + if (controller != null) + return Response.status(Response.Status.OK). + entity(controller).build(); + else + return Response.status(Response.Status.NOT_FOUND). + entity(new Error(controllerName + " not found")).build(); + } + + @DELETE + @Path("engine/controllers/{controllerName}") + @Produces(MediaType.APPLICATION_JSON) + @Consumes(MediaType.APPLICATION_JSON) + public Response deleteController(@PathParam("controllerName") String controllerName) { + + if (controllerName == null || controllerName.isEmpty()) + return Response.status(Response.Status.BAD_REQUEST). + entity("A controller name must be provided"). + build(); + + PolicyController controller; + try { + controller = + PolicyController.factory.get(controllerName); + if (controller == null) + return Response.status(Response.Status.BAD_REQUEST). + entity(new Error(controllerName + " does not exist")). + build(); + } catch (IllegalArgumentException e) { + logger.warn(MessageCodes.EXCEPTION_ERROR, e, + controllerName, this.toString()); + return Response.status(Response.Status.BAD_REQUEST). + entity(new Error(controllerName + " not found: " + e.getMessage())). + build(); + } catch (IllegalStateException e) { + logger.warn(MessageCodes.EXCEPTION_ERROR, e, + controllerName, this.toString()); + return Response.status(Response.Status.NOT_ACCEPTABLE). + entity(new Error(controllerName + " not acceptable")).build(); + } + + try { + PolicyEngine.manager.removePolicyController(controllerName); + } catch (IllegalArgumentException | IllegalStateException e) { + logger.warn(MessageCodes.EXCEPTION_ERROR, e, + controllerName + controller); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR). + entity(new Error(e.getMessage())). + build(); + } + + return Response.status(Response.Status.OK). + entity(controller). + build(); + } + + /** + * Updates the Policy Engine + * + * @param configuration configuration + * @return Policy Engine + */ + @PUT + @Path("engine/controllers/{controllerName}") + @Produces(MediaType.APPLICATION_JSON) + @Consumes(MediaType.APPLICATION_JSON) + public Response updateController(@PathParam("controllerName") String controllerName, + ControllerConfiguration controllerConfiguration) { + + if (controllerName == null || controllerName.isEmpty() || + controllerConfiguration == null || + controllerConfiguration.getName().intern() != controllerName) + return Response.status(Response.Status.BAD_REQUEST). + entity("A valid or matching controller names must be provided"). + build(); + + PolicyController controller; + try { + controller = PolicyEngine.manager.updatePolicyController(controllerConfiguration); + if (controller == null) + return Response.status(Response.Status.BAD_REQUEST). + entity(new Error(controllerName + " does not exist")). + build(); + } catch (IllegalArgumentException e) { + logger.warn(MessageCodes.EXCEPTION_ERROR, e, + controllerName, this.toString()); + return Response.status(Response.Status.BAD_REQUEST). + entity(new Error(controllerName + " not found: " + e.getMessage())). + build(); + } catch (Exception e) { + logger.warn(MessageCodes.EXCEPTION_ERROR, e, + controllerName, this.toString()); + return Response.status(Response.Status.NOT_ACCEPTABLE). + entity(new Error(controllerName + " not acceptable")).build(); + } + + return Response.status(Response.Status.OK). + entity(controller). + 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}/decoders") + @Produces(MediaType.APPLICATION_JSON) + public Response decoders(@PathParam("controllerName") String controllerName) { + try { + DroolsController drools = getDroolsController(controllerName); + List<ProtocolCoderToolset> decoders = EventProtocolCoder.manager.getDecoders + (drools.getGroupId(), drools.getArtifactId()); + return Response.status(Response.Status.OK). + entity(decoders). + 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}/decoders/filters") + @Produces(MediaType.APPLICATION_JSON) + public Response decoderFilters(@PathParam("controllerName") String controllerName) { + try { + DroolsController drools = getDroolsController(controllerName); + List<CoderFilters> filters = EventProtocolCoder.manager.getDecoderFilters + (drools.getGroupId(), drools.getArtifactId()); + return Response.status(Response.Status.OK). + entity(filters). + 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}/decoders/{topicName}") + @Produces(MediaType.APPLICATION_JSON) + public Response decoder(@PathParam("controllerName") String controllerName, + @PathParam("topicName") String topicName) { + try { + DroolsController drools = getDroolsController(controllerName); + ProtocolCoderToolset decoder = EventProtocolCoder.manager.getDecoders + (drools.getGroupId(), drools.getArtifactId(), topicName); + return Response.status(Response.Status.OK). + entity(decoder). + 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}/decoders/{topicName}/filters") + @Produces(MediaType.APPLICATION_JSON) + public Response decoderFilter(@PathParam("controllerName") String controllerName, + @PathParam("topicName") String topicName) { + try { + DroolsController drools = getDroolsController(controllerName); + ProtocolCoderToolset decoder = EventProtocolCoder.manager.getDecoders + (drools.getGroupId(), drools.getArtifactId(), topicName); + if (decoder == null) + return Response.status(Response.Status.BAD_REQUEST). + entity(new Error(topicName + " does not exist")). + build(); + else + return Response.status(Response.Status.OK). + entity(decoder.getCoders()). + 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}/decoders/{topicName}/filters/{factClassName}") + @Produces(MediaType.APPLICATION_JSON) + public Response decoderFilter(@PathParam("controllerName") String controllerName, + @PathParam("topicName") String topicName, + @PathParam("factClassName") String factClass) { + try { + DroolsController drools = getDroolsController(controllerName); + ProtocolCoderToolset decoder = EventProtocolCoder.manager.getDecoders + (drools.getGroupId(), drools.getArtifactId(), topicName); + CoderFilters filters = decoder.getCoder(factClass); + if (filters == null) + return Response.status(Response.Status.BAD_REQUEST). + entity(new Error(topicName + ":" + factClass + " does not exist")). + build(); + else + return Response.status(Response.Status.OK). + entity(filters). + 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(); + } + } + + @POST + @Path("engine/controllers/{controllerName}/decoders/{topicName}/filters/{factClassName}") + @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON) + public Response decoderFilter(@PathParam("controllerName") String controllerName, + @PathParam("topicName") String topicName, + @PathParam("factClassName") String factClass, + JsonProtocolFilter configFilters) { + + if (configFilters == null) { + return Response.status(Response.Status.BAD_REQUEST). + entity(new Error("Configuration Filters not provided")). + build(); + } + + try { + DroolsController drools = getDroolsController(controllerName); + ProtocolCoderToolset decoder = EventProtocolCoder.manager.getDecoders + (drools.getGroupId(), drools.getArtifactId(), topicName); + CoderFilters filters = decoder.getCoder(factClass); + if (filters == null) + return Response.status(Response.Status.BAD_REQUEST). + entity(new Error(topicName + ":" + factClass + " does not exist")). + build(); + filters.setFilter(configFilters); + return Response.status(Response.Status.OK). + entity(filters). + 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}/decoders/{topicName}/filters/{factClassName}/rules") + @Produces(MediaType.APPLICATION_JSON) + public Response decoderFilterRules(@PathParam("controllerName") String controllerName, + @PathParam("topicName") String topicName, + @PathParam("factClassName") String factClass) { + try { + DroolsController drools = getDroolsController(controllerName); + ProtocolCoderToolset decoder = EventProtocolCoder.manager.getDecoders + (drools.getGroupId(), drools.getArtifactId(), topicName); + + CoderFilters filters = decoder.getCoder(factClass); + if (filters == null) + return Response.status(Response.Status.BAD_REQUEST). + entity(new Error(controllerName + ":" + topicName + ":" + factClass + " does not exist")). + build(); + + JsonProtocolFilter filter = filters.getFilter(); + if (filter == null) + return Response.status(Response.Status.BAD_REQUEST). + entity(new Error(controllerName + ":" + topicName + ":" + factClass + " no filters")). + build(); + + return Response.status(Response.Status.OK). + entity(filter.getRules()). + 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}/decoders/{topicName}/filters/{factClassName}/rules/{ruleName}") + @Produces(MediaType.APPLICATION_JSON) + public Response decoderFilterRules(@PathParam("controllerName") String controllerName, + @PathParam("topicName") String topicName, + @PathParam("factClassName") String factClass, + @PathParam("ruleName") String ruleName) { + try { + DroolsController drools = getDroolsController(controllerName); + ProtocolCoderToolset decoder = EventProtocolCoder.manager.getDecoders + (drools.getGroupId(), drools.getArtifactId(), topicName); + + CoderFilters filters = decoder.getCoder(factClass); + if (filters == null) + return Response.status(Response.Status.BAD_REQUEST). + entity(new Error(controllerName + ":" + topicName + ":" + factClass + " does not exist")). + build(); + + JsonProtocolFilter filter = filters.getFilter(); + if (filter == null) + return Response.status(Response.Status.BAD_REQUEST). + entity(new Error(controllerName + ":" + topicName + ":" + factClass + " no filters")). + build(); + + return Response.status(Response.Status.OK). + entity(filter.getRules(ruleName)). + 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(); + } + } + + @DELETE + @Path("engine/controllers/{controllerName}/decoders/{topicName}/filters/{factClassName}/rules/{ruleName}") + @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON) + public Response deleteDecoderFilterRule(@PathParam("controllerName") String controllerName, + @PathParam("topicName") String topicName, + @PathParam("factClassName") String factClass, + @PathParam("ruleName") String ruleName, + FilterRule rule) { + + try { + DroolsController drools = getDroolsController(controllerName); + ProtocolCoderToolset decoder = EventProtocolCoder.manager.getDecoders + (drools.getGroupId(), drools.getArtifactId(), topicName); + + CoderFilters filters = decoder.getCoder(factClass); + if (filters == null) + return Response.status(Response.Status.BAD_REQUEST). + entity(new Error(controllerName + ":" + topicName + ":" + factClass + " does not exist")). + build(); + + JsonProtocolFilter filter = filters.getFilter(); + if (filter == null) + return Response.status(Response.Status.BAD_REQUEST). + entity(new Error(controllerName + ":" + topicName + ":" + factClass + " no filters")). + build(); + + if (rule == null) { + filter.deleteRules(ruleName); + return Response.status(Response.Status.OK). + entity(filter.getRules()). + build(); + } + + if (rule.getName() == null || !rule.getName().equals(ruleName)) + return Response.status(Response.Status.BAD_REQUEST). + entity(new Error(controllerName + ":" + topicName + ":" + factClass + ":" + ruleName + + " rule name request inconsistencies (" + rule.getName() + ")")). + build(); + + filter.deleteRule(ruleName, rule.getRegex()); + return Response.status(Response.Status.OK). + entity(filter.getRules()). + 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(); + } + } + + @PUT + @Path("engine/controllers/{controllerName}/decoders/{topicName}/filters/{factClassName}/rules") + @Produces(MediaType.APPLICATION_JSON) + public Response decoderFilterRule(@PathParam("controllerName") String controllerName, + @PathParam("topicName") String topicName, + @PathParam("factClassName") String factClass, + JsonProtocolFilter.FilterRule rule) { + + try { + DroolsController drools = getDroolsController(controllerName); + ProtocolCoderToolset decoder = EventProtocolCoder.manager.getDecoders + (drools.getGroupId(), drools.getArtifactId(), topicName); + + CoderFilters filters = decoder.getCoder(factClass); + if (filters == null) + return Response.status(Response.Status.BAD_REQUEST). + entity(new Error(controllerName + ":" + topicName + ":" + factClass + " does not exist")). + build(); + + JsonProtocolFilter filter = filters.getFilter(); + if (filter == null) + return Response.status(Response.Status.BAD_REQUEST). + entity(new Error(controllerName + ":" + topicName + ":" + factClass + " no filters")). + build(); + + if (rule.getName() == null) + return Response.status(Response.Status.BAD_REQUEST). + entity(new Error(controllerName + ":" + topicName + ":" + factClass + + " rule name request inconsistencies (" + rule.getName() + ")")). + build(); + + filter.addRule(rule.getName(), rule.getRegex()); + return Response.status(Response.Status.OK). + entity(filter.getRules()). + 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}/encoders") + @Produces(MediaType.APPLICATION_JSON) + public Response encoderFilters(@PathParam("controllerName") String controllerName) { + List<CoderFilters> encoders; + try { + PolicyController controller = PolicyController.factory.get(controllerName); + if (controller == null) + return Response.status(Response.Status.BAD_REQUEST). + entity(new Error(controllerName + " does not exist")). + build(); + DroolsController drools = controller.getDrools(); + if (drools == null) + return Response.status(Response.Status.INTERNAL_SERVER_ERROR). + entity(new Error(controllerName + " has not drools component")). + build(); + encoders = EventProtocolCoder.manager.getEncoderFilters + (drools.getGroupId(), drools.getArtifactId()); + } catch (IllegalArgumentException e) { + logger.warn(MessageCodes.EXCEPTION_ERROR, e, + controllerName, this.toString()); + return Response.status(Response.Status.BAD_REQUEST). + entity(new Error(controllerName + " not found: " + e.getMessage())). + build(); + } catch (IllegalStateException e) { + logger.warn(MessageCodes.EXCEPTION_ERROR, e, + controllerName, this.toString()); + return Response.status(Response.Status.NOT_ACCEPTABLE). + entity(new Error(controllerName + " is not accepting the request")).build(); + } + + return Response.status(Response.Status.OK). + entity(encoders). + build(); + } + + @POST + @Path("engine/controllers/{controllerName}/decoders/{topic}") + @Produces(MediaType.APPLICATION_JSON) + public Response decode(@PathParam("controllerName") String controllerName, + @PathParam("topic") String topic, + String json) { + + PolicyController policyController = PolicyController.factory.get(controllerName); + + CodingResult result = new CodingResult(); + result.decoding = false; + result.encoding = false; + result.jsonEncoding = null; + + Object event; + try { + event = EventProtocolCoder.manager.decode + (policyController.getDrools().getGroupId(), + policyController.getDrools().getArtifactId(), + topic, + json); + result.decoding = true; + } catch (Exception e) { + return Response.status(Response.Status.BAD_REQUEST). + entity(new Error(e.getMessage())). + build(); + } + + try { + result.jsonEncoding = EventProtocolCoder.manager.encode(topic, event); + result.encoding = true; + } catch (Exception e) { + return Response.status(Response.Status.OK). + entity(result). + build(); + } + + return Response.status(Response.Status.OK). + entity(result). + build(); + } + + @GET + @Path("engine/topics") + @Produces(MediaType.APPLICATION_JSON) + public TopicEndpoint topics() { + return TopicEndpoint.manager; + } + + @SuppressWarnings("unchecked") + @GET + @Path("engine/topics/sources") + @Produces(MediaType.APPLICATION_JSON) + public List<TopicSource> sources() { + return (List<TopicSource>) TopicEndpoint.manager.getTopicSources(); + } + + @SuppressWarnings("unchecked") + @GET + @Path("engine/topics/sinks") + @Produces(MediaType.APPLICATION_JSON) + public List<TopicSink> sinks() { + return (List<TopicSink>) TopicEndpoint.manager.getTopicSinks(); + } + + @GET + @Path("engine/topics/sources/ueb") + @Produces(MediaType.APPLICATION_JSON) + public List<UebTopicSource> uebSources() { + return TopicEndpoint.manager.getUebTopicSources(); + } + + @GET + @Path("engine/topics/sinks/ueb") + @Produces(MediaType.APPLICATION_JSON) + public List<UebTopicSink> uebSinks() { + return (List<UebTopicSink>) TopicEndpoint.manager.getUebTopicSinks(); + } + + @GET + @Path("engine/topics/sources/dmaap") + @Produces(MediaType.APPLICATION_JSON) + public List<DmaapTopicSource> dmaapSources() { + return TopicEndpoint.manager.getDmaapTopicSources(); + } + + @GET + @Path("engine/topics/sinks/dmaap") + @Produces(MediaType.APPLICATION_JSON) + public List<DmaapTopicSink> dmaapSinks() { + return (List<DmaapTopicSink>) TopicEndpoint.manager.getDmaapTopicSinks(); + } + + @SuppressWarnings("unchecked") + @GET + @Path("engine/topics/{topic}/sources") + @Produces(MediaType.APPLICATION_JSON) + public List<TopicSource> sourceTopic(@PathParam("topic") String topic) { + List<String> topics = new ArrayList<String>(); + topics.add(topic); + + return (List<TopicSource>) TopicEndpoint.manager.getTopicSources(topics); + } + + @SuppressWarnings("unchecked") + @GET + @Path("engine/topics/{topic}/sinks") + @Produces(MediaType.APPLICATION_JSON) + public List<TopicSink> sinkTopic(@PathParam("topic") String topic) { + List<String> topics = new ArrayList<String>(); + topics.add(topic); + + return (List<TopicSink>) TopicEndpoint.manager.getTopicSinks(topics); + } + + + @GET + @Path("engine/topics/{topic}/ueb/source") + @Produces(MediaType.APPLICATION_JSON) + public UebTopicSource uebSourceTopic(@PathParam("topic") String topic) { + return TopicEndpoint.manager.getUebTopicSource(topic); + } + + @GET + @Path("engine/topics/{topic}/ueb/sink") + @Produces(MediaType.APPLICATION_JSON) + public UebTopicSink uebSinkTopic(@PathParam("topic") String topic) { + return TopicEndpoint.manager.getUebTopicSink(topic); + } + + @GET + @Path("engine/topics/{topic}/dmaap/source") + @Produces(MediaType.APPLICATION_JSON) + public DmaapTopicSource dmaapSourceTopic(@PathParam("topic") String topic) { + return TopicEndpoint.manager.getDmaapTopicSource(topic); + } + + @GET + @Path("engine/topics/{topic}/dmaap/sink") + @Produces(MediaType.APPLICATION_JSON) + public DmaapTopicSink dmaapSinkTopic(@PathParam("topic") String topic) { + return TopicEndpoint.manager.getDmaapTopicSink(topic); + } + + @GET + @Path("engine/topics/{topic}/ueb/source/events") + @Produces(MediaType.APPLICATION_JSON) + public Response uebSourceEvent(@PathParam("topic") String topicName) { + + UebTopicSource uebReader = TopicEndpoint.manager.getUebTopicSource(topicName); + String[] events = uebReader.getRecentEvents(); + return Response.status(Status.OK). + entity(events). + build(); + } + + @GET + @Path("engine/topics/{topic}/ueb/sink/events") + @Produces(MediaType.APPLICATION_JSON) + public Response uebSinkEvent(@PathParam("topic") String topicName) { + + UebTopicSink uebSink = TopicEndpoint.manager.getUebTopicSink(topicName); + String[] events = uebSink.getRecentEvents(); + return Response.status(Status.OK). + entity(events). + build(); + } + + @GET + @Path("engine/topics/{topic}/dmaap/source/events") + @Produces(MediaType.APPLICATION_JSON) + public Response dmaapSourcevent(@PathParam("topic") String topicName) { + + DmaapTopicSource uebReader = TopicEndpoint.manager.getDmaapTopicSource(topicName); + String[] events = uebReader.getRecentEvents(); + return Response.status(Status.OK). + entity(events). + build(); + } + + @GET + @Path("engine/topics/{topic}/dmaap/sink/events") + @Produces(MediaType.APPLICATION_JSON) + public Response dmaapSinkEvent(@PathParam("topic") String topicName) { + + DmaapTopicSink uebSink = TopicEndpoint.manager.getDmaapTopicSink(topicName); + String[] events = uebSink.getRecentEvents(); + return Response.status(Status.OK). + entity(events). + build(); + } + + @PUT + @Path("engine/topics/{topic}/ueb/sources/events") + @Consumes(MediaType.TEXT_PLAIN) + @Produces(MediaType.APPLICATION_JSON) + public Response uebOffer(@PathParam("topic") String topicName, + String json) { + try { + UebTopicSource uebReader = TopicEndpoint.manager.getUebTopicSource(topicName); + boolean success = uebReader.offer(json); + if (success) + return Response.status(Status.OK). + entity("Successfully injected event over " + topicName). + build(); + else + return Response.status(Status.NOT_ACCEPTABLE). + entity("Failure to inject event over " + topicName). + build(); + } catch (Exception e) { + return Response.status(Response.Status.BAD_REQUEST). + entity(new Error(e.getMessage())). + build(); + } + } + + @PUT + @Path("engine/topics/{topic}/dmaap/sources/events") + @Consumes(MediaType.TEXT_PLAIN) + @Produces(MediaType.APPLICATION_JSON) + public Response dmaapOffer(@PathParam("topic") String topicName, + String json) { + try { + DmaapTopicSource dmaapReader = TopicEndpoint.manager.getDmaapTopicSource(topicName); + boolean success = dmaapReader.offer(json); + if (success) + return Response.status(Status.OK). + entity("Successfully injected event over " + topicName). + build(); + else + return Response.status(Status.NOT_ACCEPTABLE). + entity("Failure to inject event over " + topicName). + build(); + } catch (Exception e) { + return Response.status(Response.Status.BAD_REQUEST). + entity(new Error(e.getMessage())). + build(); + } + } + + @PUT + @Path("engine/topics/lock") + @Produces(MediaType.APPLICATION_JSON) + @Consumes(MediaType.APPLICATION_JSON) + public Response lockTopics() { + boolean success = TopicEndpoint.manager.lock(); + if (success) + return Response.status(Status.OK). + entity("Endpoints are locked"). + build(); + else + return Response.status(Status.SERVICE_UNAVAILABLE). + entity("Endpoints cannot be locked"). + build(); + } + + @DELETE + @Path("engine/topics/lock") + @Produces(MediaType.APPLICATION_JSON) + @Consumes(MediaType.APPLICATION_JSON) + public Response unlockTopics() { + boolean success = TopicEndpoint.manager.unlock(); + if (success) + return Response.status(Status.OK). + entity("Endpoints are unlocked"). + build(); + else + return Response.status(Status.SERVICE_UNAVAILABLE). + entity("Endpoints cannot be unlocked"). + build(); + } + + @PUT + @Path("engine/topics/{topic}/ueb/sources/lock") + @Produces(MediaType.APPLICATION_JSON) + @Consumes(MediaType.APPLICATION_JSON) + public Response lockTopic(@PathParam("topic") String topicName) { + UebTopicSource reader = TopicEndpoint.manager.getUebTopicSource(topicName); + boolean success = reader.lock(); + if (success) + return Response.status(Status.OK). + entity("Endpoints are unlocked"). + build(); + else + return Response.status(Status.SERVICE_UNAVAILABLE). + entity("Endpoints cannot be unlocked"). + build(); + } + + @PUT + @Path("engine/topics/{topic}/ueb/sources/unlock") + @Produces(MediaType.APPLICATION_JSON) + @Consumes(MediaType.APPLICATION_JSON) + public Response unlockTopic(@PathParam("topic") String topicName) { + UebTopicSource reader = TopicEndpoint.manager.getUebTopicSource(topicName); + boolean success = reader.unlock(); + if (success) + return Response.status(Status.OK). + entity("Endpoints are unlocked"). + build(); + else + return Response.status(Status.SERVICE_UNAVAILABLE). + entity("Endpoints cannot be unlocked"). + build(); + } + + @PUT + @Path("engine/controllers/{controllerName}/lock") + @Produces(MediaType.APPLICATION_JSON) + public Response lockController(@PathParam("controllerName") String controllerName) { + PolicyController policyController = PolicyController.factory.get(controllerName); + boolean success = policyController.lock(); + if (success) + return Response.status(Status.OK). + entity("Controller " + controllerName + " is now locked"). + build(); + else + return Response.status(Status.SERVICE_UNAVAILABLE). + entity("Controller " + controllerName + " cannot be locked"). + build(); + } + + @DELETE + @Path("engine/controllers/{controllerName}/lock") + @Produces(MediaType.APPLICATION_JSON) + public Response unlockController(@PathParam("controllerName") String controllerName) { + PolicyController policyController = PolicyController.factory.get(controllerName); + boolean success = policyController.unlock(); + if (success) + return Response.status(Status.OK). + entity("Controller " + controllerName + " is now unlocked"). + build(); + else + return Response.status(Status.SERVICE_UNAVAILABLE). + entity("Controller " + controllerName + " cannot be unlocked"). + build(); + } + + @POST + @Path("engine/util/coders/filters/rules/{ruleName}") + @Produces(MediaType.APPLICATION_JSON) + public Response rules(@DefaultValue("false") @QueryParam("negate") boolean negate, + @PathParam("ruleName") String name, + String regex) { + String literalRegex = Pattern.quote(regex); + if (negate) + literalRegex = "^(?!" + literalRegex + "$).*"; + + return Response.status(Status.OK). + entity(new JsonProtocolFilter.FilterRule(name,literalRegex)). + build(); + } + + @GET + @Path("engine/util/uuid") + public Response uuid() { + return Response.status(Status.OK). + entity(UUID.randomUUID().toString()). + build(); + } + + /* + * Helper classes for aggregation of results + */ + + + public static class Endpoints { + public List<TopicSource> sources; + public List<TopicSink> sinks; + + public Endpoints(List<TopicSource> sources, + List<TopicSink> sinks) { + this.sources = sources; + this.sinks = sinks; + } + } + + public static class Endpoint { + public TopicSource source; + public TopicSink sink; + + public Endpoint(TopicSource source, + TopicSink sink) { + this.source = source; + this.sink = sink; + } + } + + public static class CodingResult { + public String jsonEncoding; + public Boolean encoding; + public Boolean decoding; + } + + public static class Error { + public String error; + + /** + * @param error + */ + public Error(String error) { + this.error = error; + } + } +} + diff --git a/policy-management/src/main/java/org/openecomp/policy/drools/system/Main.java b/policy-management/src/main/java/org/openecomp/policy/drools/system/Main.java new file mode 100644 index 00000000..108600b2 --- /dev/null +++ b/policy-management/src/main/java/org/openecomp/policy/drools/system/Main.java @@ -0,0 +1,131 @@ +/*- + * ============LICENSE_START======================================================= + * policy-management + * ================================================================================ + * 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.system; + +import java.io.File; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Properties; + +import org.openecomp.policy.common.logging.flexlogger.FlexLogger; +import org.openecomp.policy.common.logging.flexlogger.Logger; +import org.openecomp.policy.drools.core.PolicyContainer; +import org.openecomp.policy.drools.persistence.SystemPersistence; +import org.openecomp.policy.drools.utils.PropertyUtil; + +/** + * Programmatic entry point to the management layer + */ +public class Main { + + /** + * logger + */ + private static Logger logger = FlexLogger.getLogger(Main.class, true); + + public static void main(String args[]) { + + File configDir = new File(SystemPersistence.CONFIG_DIR_NAME); + + if (!configDir.isDirectory()) { + throw new IllegalArgumentException + ("config directory: " + configDir.getAbsolutePath() + + " not found"); + } + + + /* 0. Start the CORE layer first */ + + try { + PolicyContainer.globalInit(args); + } catch (Exception e) { + System.out.println("policy-core startup failed"); + logger.warn("policy-core startup failed"); + e.printStackTrace(); + } + + /* 1. Configure the Engine */ + + try { + Path policyEnginePath = Paths.get(configDir.toPath().toString(), SystemPersistence.PROPERTIES_FILE_ENGINE); + Properties properties = PropertyUtil.getProperties(policyEnginePath.toFile()); + PolicyEngine.manager.configure(properties); + } catch (Exception e) { + String msg = "Policy Engine cannot be configured with properties: " + e.getMessage() + " : " + PolicyEngine.manager; + System.out.println(msg); + logger.warn(msg); + } + + /* 2. Start the Engine with the basic services only (no Policy Controllers) */ + + try { + boolean success = PolicyEngine.manager.start(); + if (!success) { + System.out.println("Policy Engine found some problems starting some components: " + PolicyEngine.manager); + logger.warn("Policy Engine is in an invalid state: " + PolicyEngine.manager); + } + } catch (IllegalStateException e) { + String msg = "Policy Engine is starting in an unexpected state: " + e.getMessage() + " : " + PolicyEngine.manager; + System.out.println(msg); + logger.warn(msg); + } catch (Exception e) { + String msg = "Unexpected Situation. Policy Engine cannot be started: " + e.getMessage() + " : " + PolicyEngine.manager; + System.out.println(msg); + e.printStackTrace(); + System.exit(1); + } + + /* 3. Create and start the controllers */ + + File[] controllerFiles = configDir.listFiles(); + for (File config : controllerFiles) { + + if (config.getName().endsWith(SystemPersistence.PROPERTIES_FILE_CONTROLLER_SUFFIX)) { + int idxSuffix = + config.getName().indexOf(SystemPersistence.PROPERTIES_FILE_CONTROLLER_SUFFIX); + int lastIdxSuffix = + config.getName().lastIndexOf(SystemPersistence.PROPERTIES_FILE_CONTROLLER_SUFFIX); + if (idxSuffix != lastIdxSuffix) { + throw new IllegalArgumentException + ("Improper naming of controller properties file: " + + "Expected <controller-name>" + + SystemPersistence.PROPERTIES_FILE_CONTROLLER_SUFFIX); + } + + String name = + config.getName().substring(0, lastIdxSuffix); + try { + Properties properties = PropertyUtil.getProperties(config); + PolicyController controller = PolicyEngine.manager.createPolicyController(name, properties); + controller.start(); + } catch (Exception e) { + System.out.println("can't instantiate Policy Controller based on properties file: " + + config + " with message " + e.getMessage()); + e.printStackTrace(); + } catch (LinkageError le) { + System.out.println("can't instantiate Policy Controller based on properties file: " + + config + ". A Linkage Error has been encountered: " + le.getMessage()); + le.printStackTrace(); + } + } + } + } +} diff --git a/policy-management/src/main/java/org/openecomp/policy/drools/system/PolicyController.java b/policy-management/src/main/java/org/openecomp/policy/drools/system/PolicyController.java new file mode 100644 index 00000000..543fd0e3 --- /dev/null +++ b/policy-management/src/main/java/org/openecomp/policy/drools/system/PolicyController.java @@ -0,0 +1,110 @@ +/*- + * ============LICENSE_START======================================================= + * policy-management + * ================================================================================ + * 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.system; + +import java.util.List; +import java.util.Properties; + +import org.openecomp.policy.drools.controller.DroolsController; +import org.openecomp.policy.drools.event.comm.TopicSource; +import org.openecomp.policy.drools.event.comm.Topic.CommInfrastructure; +import org.openecomp.policy.drools.event.comm.TopicSink; +import org.openecomp.policy.drools.properties.Lockable; +import org.openecomp.policy.drools.properties.Startable; +import org.openecomp.policy.drools.protocol.configuration.DroolsConfiguration; + +/** + * A Policy Controller is the higher level unit of control. It corresponds to + * the ncomp equivalent of a controller. It provides management of underlying + * resources associated with the policy controller, which is a) communication + * infrastructure, and b) policy-core (drools) session infrastructure + * + */ +public interface PolicyController extends Startable, Lockable { + + /** + * name of this Policy Controller + */ + public String getName(); + + /** + * Get the topic readers of interest for this controller + */ + public List<? extends TopicSource> getTopicSources(); + + /** + * Get the topic readers of interest for this controller + */ + public List<? extends TopicSink> getTopicSinks(); + + /** + * Get the Drools Controller + */ + public DroolsController getDrools(); + + /** + * update maven configuration + * + * @param newDroolsConfiguration new drools configuration + * @return true if the update was successful, false otherwise + */ + public boolean updateDrools(DroolsConfiguration newDroolsConfiguration); + + /** + * Get the Initialization Properties + */ + public Properties getInitializationProperties(); + + /** + * Attempts delivering of an String over communication + * infrastructure "busType" + * + * @param eventBus Communication infrastructure identifier + * @param topic topic + * @param event the event object to send + * + * @return true if successful, false if a failure has occurred. + * @throws IllegalArgumentException when invalid or insufficient + * properties are provided + * @throws IllegalStateException when the engine is in a state where + * this operation is not permitted (ie. locked or stopped). + * @throws UnsupportedOperationException when the engine cannot deliver due + * to the functionality missing (ie. communication infrastructure + * not supported. + */ + public boolean deliver(CommInfrastructure busType, String topic, + Object event) + throws IllegalArgumentException, IllegalStateException, + UnsupportedOperationException; + + /** + * halts and permanently releases all resources + * @throws IllegalStateException + */ + public void halt() throws IllegalStateException; + + /** + * Factory that tracks and manages Policy Controllers + */ + public static PolicyControllerFactory factory = + new IndexedPolicyControllerFactory(); + +} diff --git a/policy-management/src/main/java/org/openecomp/policy/drools/system/PolicyControllerFactory.java b/policy-management/src/main/java/org/openecomp/policy/drools/system/PolicyControllerFactory.java new file mode 100644 index 00000000..e105bbb9 --- /dev/null +++ b/policy-management/src/main/java/org/openecomp/policy/drools/system/PolicyControllerFactory.java @@ -0,0 +1,464 @@ +/*- + * ============LICENSE_START======================================================= + * policy-management + * ================================================================================ + * 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.system; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Properties; + +import org.openecomp.policy.drools.controller.DroolsController; +import org.openecomp.policy.common.logging.flexlogger.FlexLogger; +import org.openecomp.policy.common.logging.flexlogger.Logger; +import org.openecomp.policy.drools.protocol.configuration.DroolsConfiguration; +import org.openecomp.policy.drools.system.internal.AggregatedPolicyController; + +/** + * Policy Controller Factory to manage controller creation, destruction, + * and retrieval for management interfaces + */ +public interface PolicyControllerFactory { + /** + * Build a controller from a properties file + * + * @param name the global name of this controller + * @param properties input parameters in form of properties for controller + * initialization. + * + * @return a Policy Controller + * + * @throws IllegalArgumentException invalid values provided in properties + */ + public PolicyController build(String name, Properties properties) + throws IllegalArgumentException; + + /** + * patches (updates) a controller from a critical configuration update. + * + * @param name + * @param configController + * + * @return a Policy Controller + */ + public PolicyController patch(String name, DroolsConfiguration configController); + + /** + * rebuilds (updates) a controller from a configuration update. + * + * @param controller + * @param configController + * + * @return a Policy Controller + */ + public PolicyController patch(PolicyController controller, + DroolsConfiguration configController); + + /** + * get PolicyController from DroolsController + * + * @param droolsController + * @return + * @throws IllegalArgumentException + * @throws IllegalStateException + */ + public PolicyController get(DroolsController droolsController) + throws IllegalArgumentException, IllegalStateException; + + /** + * Makes the Policy Controller identified by controllerName not operational, but + * does not delete its associated data + * + * @param controllerName name of the policy controller + * @throws IllegalArgumentException invalid arguments + */ + public void shutdown(String controllerName) throws IllegalArgumentException;; + + /** + * Makes the Policy Controller identified by controller not operational, but + * does not delete its associated data + * + * @param controller a Policy Controller + * @throws IllegalArgumentException invalid arguments + */ + public void shutdown(PolicyController controller) throws IllegalArgumentException; + + /** + * Releases all Policy Controllers from operation + */ + public void shutdown(); + + /** + * Destroys this Policy Controller + * + * @param controllerName name of the policy controller + * @throws IllegalArgumentException invalid arguments + */ + public void destroy(String controllerName) throws IllegalArgumentException;; + + /** + * Destroys this Policy Controller + * + * @param controller a Policy Controller + * @throws IllegalArgumentException invalid arguments + */ + public void destroy(PolicyController controller) throws IllegalArgumentException; + + /** + * Releases all Policy Controller resources + */ + public void destroy(); + + /** + * gets the Policy Controller identified by its name + * + * @param policyControllerName + * @return + * @throws IllegalArgumentException + * @throws IllegalStateException + */ + public PolicyController get(String policyControllerName) + throws IllegalArgumentException, IllegalStateException; + + /** + * gets the Policy Controller identified by group and artifact ids + * + * @param groupId group id + * @param artifactId artifact id + * @return + * @throws IllegalArgumentException + * @throws IllegalStateException + */ + public PolicyController get(String groupId, String artifactId) + throws IllegalArgumentException, IllegalStateException; + + /** + * returns the current inventory of Policy Controllers + * + * @return a list of Policy Controllers + */ + public List<PolicyController> inventory(); +} + +/** + * Factory of Policy Controllers indexed by the name of the Policy Controller + */ +class IndexedPolicyControllerFactory implements PolicyControllerFactory { + // get an instance of logger + private static Logger logger = FlexLogger.getLogger(PolicyControllerFactory.class); + + /** + * Policy Controller Name Index + */ + protected HashMap<String,PolicyController> policyControllers = + new HashMap<String,PolicyController>(); + + /** + * Group/Artifact Ids Index + */ + protected HashMap<String,PolicyController> coordinates2Controller = + new HashMap<String,PolicyController>(); + + /** + * produces key for indexing controller names + * + * @param group group id + * @param artifactId artifact id + * @return index key + */ + protected String toKey(String groupId, String artifactId) { + return groupId + ":" + artifactId; + } + + /** + * {@inheritDoc} + */ + @Override + public synchronized PolicyController build(String name, Properties properties) + throws IllegalArgumentException { + + if (this.policyControllers.containsKey(name)) { + return this.policyControllers.get(name); + } + + /* A PolicyController does not exist */ + + PolicyController controller = + new AggregatedPolicyController(name, properties); + + String coordinates = toKey(controller.getDrools().getGroupId(), + controller.getDrools().getArtifactId()); + + this.policyControllers.put(name, controller); + + + if (controller.getDrools().isBrained()) + this.coordinates2Controller.put(coordinates, controller); + + return controller; + } + + /** + * {@inheritDoc} + */ + @Override + public synchronized PolicyController patch(String name, DroolsConfiguration droolsConfig) + throws IllegalArgumentException { + + if (name == null || name.isEmpty() || !this.policyControllers.containsKey(name)) { + throw new IllegalArgumentException("Invalid " + name); + } + + if (droolsConfig == null) + throw new IllegalArgumentException("Invalid Drools Configuration"); + + PolicyController controller = this.get(name); + + if (controller == null) { + logger.warn("A POLICY CONTROLLER of name " + name + + "does not exist for patch operation: " + droolsConfig); + + throw new IllegalArgumentException("Not a valid controller of name " + name); + } + + this.patch(controller, droolsConfig); + + if (logger.isInfoEnabled()) + logger.info("UPDATED drools configuration: " + droolsConfig + " on " + this); + + return controller; + } + + + /** + * {@inheritDoc} + */ + @Override + public PolicyController patch(PolicyController controller, DroolsConfiguration droolsConfig) + throws IllegalArgumentException { + + if (controller == null) + throw new IllegalArgumentException("Not a valid controller: null"); + + if (!controller.updateDrools(droolsConfig)) { + logger.warn("Cannot update drools configuration: " + droolsConfig + " on " + this); + throw new IllegalArgumentException("Cannot update drools configuration Drools Configuration"); + } + + if (logger.isInfoEnabled()) + logger.info("UPDATED drools configuration: " + droolsConfig + " on " + this); + + String coordinates = toKey(controller.getDrools().getGroupId(), + controller.getDrools().getArtifactId()); + + if (controller.getDrools().isBrained()) + this.coordinates2Controller.put(coordinates, controller); + + return controller; + } + + /** + * {@inheritDoc} + */ + @Override + public void shutdown(String controllerName) throws IllegalArgumentException { + + if (controllerName == null || controllerName.isEmpty()) { + throw new IllegalArgumentException("Invalid " + controllerName); + } + + synchronized(this) { + if (!this.policyControllers.containsKey(controllerName)) { + return; + } + + PolicyController controller = this.policyControllers.get(controllerName); + this.shutdown(controller); + } + } + + /** + * {@inheritDoc} + */ + @Override + public void shutdown(PolicyController controller) throws IllegalArgumentException { + this.unmanage(controller); + controller.shutdown(); + } + + /** + * {@inheritDoc} + */ + @Override + public void shutdown() { + List<PolicyController> controllers = this.inventory(); + for (PolicyController controller: controllers) { + controller.shutdown(); + } + + synchronized(this) { + this.policyControllers.clear(); + this.coordinates2Controller.clear(); + } + } + + /** + * unmanage the controller + * + * @param controller + * @return + * @throws IllegalArgumentException + */ + protected void unmanage(PolicyController controller) throws IllegalArgumentException { + if (controller == null) { + throw new IllegalArgumentException("Invalid Controller"); + } + + synchronized(this) { + if (!this.policyControllers.containsKey(controller.getName())) { + return; + } + controller = this.policyControllers.remove(controller.getName()); + + String coordinates = toKey(controller.getDrools().getGroupId(), + controller.getDrools().getArtifactId()); + this.coordinates2Controller.remove(coordinates); + } + } + + /** + * {@inheritDoc} + */ + @Override + public void destroy(String controllerName) throws IllegalArgumentException { + + if (controllerName == null || controllerName.isEmpty()) { + throw new IllegalArgumentException("Invalid " + controllerName); + } + + synchronized(this) { + if (!this.policyControllers.containsKey(controllerName)) { + return; + } + + PolicyController controller = this.policyControllers.get(controllerName); + this.destroy(controller); + } + } + + /** + * {@inheritDoc} + */ + @Override + public void destroy(PolicyController controller) throws IllegalArgumentException { + this.unmanage(controller); + controller.halt(); + } + + /** + * {@inheritDoc} + */ + @Override + public void destroy() { + List<PolicyController> controllers = this.inventory(); + for (PolicyController controller: controllers) { + controller.halt(); + } + + synchronized(this) { + this.policyControllers.clear(); + this.coordinates2Controller.clear(); + } + } + + /** + * {@inheritDoc} + */ + @Override + public PolicyController get(String name) throws IllegalArgumentException, IllegalStateException { + + if (name == null || name.isEmpty()) { + throw new IllegalArgumentException("Invalid " + name); + } + + synchronized(this) { + if (this.policyControllers.containsKey(name)) { + return this.policyControllers.get(name); + } else { + throw new IllegalArgumentException("Invalid " + name); + } + } + } + + /** + * {@inheritDoc} + */ + @Override + public PolicyController get(String groupId, String artifactId) + throws IllegalArgumentException, IllegalStateException { + + if (groupId == null || groupId.isEmpty() || + artifactId == null || artifactId.isEmpty()) { + throw new IllegalArgumentException("Invalid group/artifact ids"); + } + + synchronized(this) { + String key = toKey(groupId,artifactId); + if (this.coordinates2Controller.containsKey(key)) { + return this.coordinates2Controller.get(key); + } else { + throw new IllegalArgumentException("Invalid " + key); + } + } + } + + /** + * {@inheritDoc} + */ + @Override + public PolicyController get(DroolsController droolsController) + throws IllegalArgumentException, IllegalStateException { + + if (droolsController == null) { + throw new IllegalArgumentException("No Drools Controller provided"); + } + + synchronized(this) { + String key = toKey(droolsController.getGroupId(), droolsController.getArtifactId()); + if (this.coordinates2Controller.containsKey(key)) { + return this.coordinates2Controller.get(key); + } else { + logger.error("Drools Controller not associated with Policy Controller " + droolsController + ":" + this); + throw new IllegalStateException("Drools Controller not associated with Policy Controller " + droolsController + ":" + this); + } + } + } + + /** + * {@inheritDoc} + */ + @Override + public List<PolicyController> inventory() { + List<PolicyController> controllers = + new ArrayList<PolicyController>(this.policyControllers.values()); + return controllers; + } + +} diff --git a/policy-management/src/main/java/org/openecomp/policy/drools/system/PolicyEngine.java b/policy-management/src/main/java/org/openecomp/policy/drools/system/PolicyEngine.java new file mode 100644 index 00000000..33f2a098 --- /dev/null +++ b/policy-management/src/main/java/org/openecomp/policy/drools/system/PolicyEngine.java @@ -0,0 +1,1182 @@ +/*- + * ============LICENSE_START======================================================= + * policy-management + * ================================================================================ + * 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.system; + +import java.util.ArrayList; +import java.util.List; +import java.util.Properties; + +import org.openecomp.policy.common.logging.eelf.MessageCodes; +import org.openecomp.policy.common.logging.flexlogger.FlexLogger; +import org.openecomp.policy.common.logging.flexlogger.Logger; +import org.openecomp.policy.drools.controller.DroolsController; +import org.openecomp.policy.drools.core.FeatureAPI; +import org.openecomp.policy.drools.core.jmx.PdpJmxListener; +import org.openecomp.policy.drools.event.comm.Topic; +import org.openecomp.policy.drools.event.comm.Topic.CommInfrastructure; +import org.openecomp.policy.drools.event.comm.TopicEndpoint; +import org.openecomp.policy.drools.event.comm.TopicListener; +import org.openecomp.policy.drools.event.comm.TopicSink; +import org.openecomp.policy.drools.event.comm.TopicSource; +import org.openecomp.policy.drools.http.server.HttpServletServer; +import org.openecomp.policy.drools.persistence.SystemPersistence; +import org.openecomp.policy.drools.properties.Lockable; +import org.openecomp.policy.drools.properties.PolicyProperties; +import org.openecomp.policy.drools.properties.Startable; +import org.openecomp.policy.drools.protocol.coders.EventProtocolCoder; +import org.openecomp.policy.drools.protocol.configuration.ControllerConfiguration; +import org.openecomp.policy.drools.protocol.configuration.PdpdConfiguration; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; + +/** + * Policy Engine, the top abstraction for the Drools PDP Policy Engine. + * It abstracts away a Drools PDP Engine from management purposes. + * This is the best place to looking at the code from a top down approach. + * Other managed entities can be obtained from the PolicyEngine, hierarchically. + * <br> + * PolicyEngine 1 --- * PolicyController 1 --- 1 DroolsController 1 --- 1 PolicyContainer 1 --- * PolicySession + * <br> + * PolicyEngine 1 --- 1 TopicEndpointManager 1 -- * TopicReader 1 --- 1 UebTopicReader + * <br> + * PolicyEngine 1 --- 1 TopicEndpointManager 1 -- * TopicReader 1 --- 1 DmaapTopicReader + * <br> + * PolicyEngine 1 --- 1 TopicEndpointManager 1 -- * TopicWriter 1 --- 1 DmaapTopicWriter + * <br> + * PolicyEngine 1 --- 1 TopicEndpointManager 1 -- * TopicReader 1 --- 1 RestTopicReader + * <br> + * PolicyEngine 1 --- 1 TopicEndpointManager 1 -- * TopicWriter 1 --- 1 RestTopicWriter + * <br> + * PolicyEngine 1 --- 1 ManagementServer + */ +public interface PolicyEngine extends Startable, Lockable, TopicListener { + + /** + * Default Config Server Port + */ + public static final int CONFIG_SERVER_DEFAULT_PORT = 9696; + + /** + * Default Config Server Hostname + */ + public static final String CONFIG_SERVER_DEFAULT_HOST = "localhost"; + + /** + * configure the policy engine according to the given properties + * + * @param properties Policy Engine properties + * @throws IllegalArgumentException when invalid or insufficient + * properties are provided + */ + public void configure(Properties properties) throws IllegalArgumentException; + + /** + * registers a new Policy Controller with the Policy Engine + * initialized per properties. + * + * @param controller name + * @param properties properties to initialize the Policy Controller + * @throws IllegalArgumentException when invalid or insufficient + * properties are provided + * @throws IllegalStateException when the engine is in a state where + * this operation is not permitted. + * @return the newly instantiated Policy Controller + */ + public PolicyController createPolicyController(String name, Properties properties) + throws IllegalArgumentException, IllegalStateException; + + /** + * updates the Policy Engine with the given configuration + * + * @param configuration the configuration + * @return success or failure + * @throws IllegalArgumentException if invalid argument provided + * @throws IllegalStateException if the system is in an invalid state + */ + public boolean configure(PdpdConfiguration configuration) + throws IllegalArgumentException, IllegalStateException; + + /** + * updates a set of Policy Controllers with configuration information + * + * @param configuration + * @return + * @throws IllegalArgumentException + * @throws IllegalStateException + */ + public List<PolicyController> updatePolicyControllers(List<ControllerConfiguration> configuration) + throws IllegalArgumentException, IllegalStateException; + + /** + * updates an already existing Policy Controller with configuration information + * + * @param configuration configuration + * + * @return the updated Policy Controller + * @throws IllegalArgumentException in the configuration is invalid + * @throws IllegalStateException if the controller is in a bad state + * @throws Exception any other reason + */ + public PolicyController updatePolicyController(ControllerConfiguration configuration) + throws Exception; + + /** + * removes the Policy Controller identified by its name from the Policy Engine + * + * @param name name of the Policy Controller + * @return the removed Policy Controller + */ + public void removePolicyController(String name); + + /** + * removes a Policy Controller from the Policy Engine + * @param controller the Policy Controller to remove from the Policy Engine + */ + public void removePolicyController(PolicyController controller); + + /** + * returns a list of the available Policy Controllers + * + * @return list of Policy Controllers + */ + public List<PolicyController> getPolicyControllers(); + + /** + * get unmanaged sources + * + * @return unmanaged sources + */ + public List<TopicSource> getSources(); + + /** + * get unmanaged sinks + * + * @return unmanaged sinks + */ + public List<TopicSink> getSinks(); + + /** + * get unmmanaged http servers list + * @return http servers + */ + public List<HttpServletServer> getHttpServers(); + + /** + * get properties configuration + * + * @return properties objects + */ + public Properties getProperties(); + + /** + * Attempts the dispatching of an "event" object + * + * @param topic topic + * @param event the event object to send + * + * @return true if successful, false if a failure has occurred. + * @throws IllegalArgumentException when invalid or insufficient + * properties are provided + * @throws IllegalStateException when the engine is in a state where + * this operation is not permitted (ie. locked or stopped). + */ + public boolean deliver(String topic, Object event) + throws IllegalArgumentException, IllegalStateException; + + /** + * Attempts the dispatching of an "event" object over communication + * infrastructure "busType" + * + * @param eventBus Communication infrastructure identifier + * @param topic topic + * @param event the event object to send + * + * @return true if successful, false if a failure has occurred. + * @throws IllegalArgumentException when invalid or insufficient + * properties are provided + * @throws IllegalStateException when the engine is in a state where + * this operation is not permitted (ie. locked or stopped). + * @throws UnsupportedOperationException when the engine cannot deliver due + * to the functionality missing (ie. communication infrastructure + * not supported. + */ + public boolean deliver(String busType, String topic, Object event) + throws IllegalArgumentException, IllegalStateException, + UnsupportedOperationException; + + /** + * Attempts the dispatching of an "event" object over communication + * infrastructure "busType" + * + * @param eventBus Communication infrastructure enum + * @param topic topic + * @param event the event object to send + * + * @return true if successful, false if a failure has occurred. + * @throws IllegalArgumentException when invalid or insufficient + * properties are provided + * @throws IllegalStateException when the engine is in a state where + * this operation is not permitted (ie. locked or stopped). + * @throws UnsupportedOperationException when the engine cannot deliver due + * to the functionality missing (ie. communication infrastructure + * not supported. + */ + public boolean deliver(CommInfrastructure busType, String topic, Object event) + throws IllegalArgumentException, IllegalStateException, + UnsupportedOperationException; + + /** + * Attempts delivering of an String over communication + * infrastructure "busType" + * + * @param eventBus Communication infrastructure identifier + * @param topic topic + * @param event the event object to send + * + * @return true if successful, false if a failure has occurred. + * @throws IllegalArgumentException when invalid or insufficient + * properties are provided + * @throws IllegalStateException when the engine is in a state where + * this operation is not permitted (ie. locked or stopped). + * @throws UnsupportedOperationException when the engine cannot deliver due + * to the functionality missing (ie. communication infrastructure + * not supported. + */ + public boolean deliver(CommInfrastructure busType, String topic, + String event) + throws IllegalArgumentException, IllegalStateException, + UnsupportedOperationException; + + /** + * Invoked when the host goes into the active state. + */ + public void activate(); + + /** + * Invoked when the host goes into the standby state. + */ + public void deactivate(); + + /** + * get policy controller names + * + * @return list of controller names + */ + public List<String> getControllers(); + + /** + * Policy Engine Manager + */ + public final static PolicyEngine manager = new PolicyEngineManager(); +} + +/** + * Policy Engine Manager Implementation + */ +class PolicyEngineManager implements PolicyEngine { + /** + * logger + */ + private static Logger logger = FlexLogger.getLogger(PolicyEngineManager.class); + + /** + * Is the Policy Engine running? + */ + protected boolean alive = false; + + /** + * Is the engine locked? + */ + protected boolean locked = false; + + /** + * Properties used to initialize the engine + */ + protected Properties properties; + + /** + * Policy Engine Sources + */ + protected List<? extends TopicSource> sources = new ArrayList<>(); + + /** + * Policy Engine Sinks + */ + protected List<? extends TopicSink> sinks = new ArrayList<>(); + + /** + * Policy Engine HTTP Servers + */ + protected List<HttpServletServer> httpServers = new ArrayList<HttpServletServer>(); + + protected Gson decoder = new GsonBuilder().disableHtmlEscaping().create(); + + /** + * {@inheritDoc} + */ + @Override + public void configure(Properties properties) throws IllegalArgumentException { + + if (properties == null) { + logger.warn("No properties provided"); + throw new IllegalArgumentException("No properties provided"); + } + + this.properties = properties; + + try { + this.sources = TopicEndpoint.manager.addTopicSources(properties); + for (TopicSource source: this.sources) { + source.register(this); + } + } catch (Exception e) { + logger.error(MessageCodes.EXCEPTION_ERROR, e, "PolicyEngine", "configure"); + } + + try { + this.sinks = TopicEndpoint.manager.addTopicSinks(properties); + } catch (IllegalArgumentException e) { + logger.error(MessageCodes.EXCEPTION_ERROR, e, "PolicyEngine", "configure"); + } + + try { + this.httpServers = HttpServletServer.factory.build(properties); + } catch (IllegalArgumentException e) { + logger.error(MessageCodes.EXCEPTION_ERROR, e, "PolicyEngine", "configure"); + } + + return; + } + + /** + * {@inheritDoc} + */ + @Override + public PolicyController createPolicyController(String name, Properties properties) + throws IllegalArgumentException, IllegalStateException { + + // check if a PROPERTY_CONTROLLER_NAME property is present + // if so, override the given name + + String propertyControllerName = properties.getProperty(PolicyProperties.PROPERTY_CONTROLLER_NAME); + if (propertyControllerName != null && !propertyControllerName.isEmpty()) { + if (!propertyControllerName.equals(name)) { + throw new IllegalStateException("Proposed name (" + name + + ") and properties name (" + propertyControllerName + + ") don't match"); + } + name = propertyControllerName; + } + + // feature hook + for (FeatureAPI feature : FeatureAPI.impl.getList()) { + feature.beforeCreateController(name, properties); + } + + PolicyController controller = PolicyController.factory.build(name, properties); + if (this.isLocked()) + controller.lock(); + + // feature hook + for (FeatureAPI feature : FeatureAPI.impl.getList()) { + // NOTE: this should change to the actual controller object + feature.afterCreateController(name); + } + + return controller; + } + + + /** + * {@inheritDoc} + */ + @Override + public boolean configure(PdpdConfiguration config) throws IllegalArgumentException, IllegalStateException { + + if (config == null) + throw new IllegalArgumentException("No configuration provided"); + + String entity = config.getEntity(); + + switch (entity) { + case PdpdConfiguration.CONFIG_ENTITY_CONTROLLER: + /* only this one supported for now */ + List<ControllerConfiguration> configControllers = config.getControllers(); + if (configControllers == null || configControllers.isEmpty()) { + if (logger.isInfoEnabled()) + logger.info("No controller configuration provided: " + config); + return false; + } + List<PolicyController> policyControllers = this.updatePolicyControllers(config.getControllers()); + if (policyControllers == null || policyControllers.isEmpty()) + return false; + else if (policyControllers.size() == configControllers.size()) + return true; + + return false; + default: + String msg = "Configuration Entity is not supported: " + entity; + logger.warn(msg); + throw new IllegalArgumentException(msg); + } + } + + /** + * {@inheritDoc} + */ + @Override + public List<PolicyController> updatePolicyControllers(List<ControllerConfiguration> configControllers) + throws IllegalArgumentException, IllegalStateException { + + List<PolicyController> policyControllers = new ArrayList<PolicyController>(); + if (configControllers == null || configControllers.isEmpty()) { + if (logger.isInfoEnabled()) + logger.info("No controller configuration provided: " + configControllers); + return policyControllers; + } + + for (ControllerConfiguration configController: configControllers) { + try { + PolicyController policyController = this.updatePolicyController(configController); + policyControllers.add(policyController); + } catch (Exception e) { + logger.error(MessageCodes.EXCEPTION_ERROR, e, "PolicyEngine", "updatePolicyControllers"); + } + } + + return policyControllers; + } + + /** + * {@inheritDoc} + */ + @Override + public PolicyController updatePolicyController(ControllerConfiguration configController) + throws Exception { + + if (configController == null) + throw new IllegalArgumentException("No controller configuration has been provided"); + + String controllerName = configController.getName(); + if (controllerName == null || controllerName.isEmpty()) { + logger.warn("controller-name must be provided"); + throw new IllegalArgumentException("No controller configuration has been provided"); + } + + PolicyController policyController = null; + try { + String operation = configController.getOperation(); + if (operation == null || operation.isEmpty()) { + logger.warn("operation must be provided"); + throw new IllegalArgumentException("operation must be provided"); + } + + try { + policyController = PolicyController.factory.get(controllerName); + } catch (IllegalArgumentException e) { + // not found + logger.warn("Policy Controller " + controllerName + " not found"); + } + + if (policyController == null) { + + if (operation.equalsIgnoreCase(ControllerConfiguration.CONFIG_CONTROLLER_OPERATION_LOCK) || + operation.equalsIgnoreCase(ControllerConfiguration.CONFIG_CONTROLLER_OPERATION_UNLOCK)) { + throw new IllegalArgumentException(controllerName + " is not available for operation " + operation); + } + + /* Recovery case */ + + logger.warn("controller " + controllerName + " does not exist. " + + "Attempting recovery from disk"); + + Properties properties = + SystemPersistence.manager.getControllerProperties(controllerName); + + /* + * returned properties cannot be null (per implementation) + * assert (properties != null) + */ + + if (properties == null) { + throw new IllegalArgumentException(controllerName + " is invalid"); + } + + logger.warn("controller " + controllerName + " being recovered. " + + "Reset controller's bad maven coordinates to brainless"); + + /* + * try to bring up bad controller in brainless mode, + * after having it working, apply the new create/update operation. + */ + properties.setProperty(PolicyProperties.RULES_GROUPID, DroolsController.NO_GROUP_ID); + properties.setProperty(PolicyProperties.RULES_ARTIFACTID, DroolsController.NO_ARTIFACT_ID); + properties.setProperty(PolicyProperties.RULES_VERSION, DroolsController.NO_VERSION); + + policyController = PolicyEngine.manager.createPolicyController(controllerName, properties); + + /* fall through to do brain update operation*/ + } + + switch (operation) { + case ControllerConfiguration.CONFIG_CONTROLLER_OPERATION_CREATE: + PolicyController.factory.patch(policyController, configController.getDrools()); + break; + case ControllerConfiguration.CONFIG_CONTROLLER_OPERATION_UPDATE: + policyController.unlock(); + PolicyController.factory.patch(policyController, configController.getDrools()); + break; + case ControllerConfiguration.CONFIG_CONTROLLER_OPERATION_LOCK: + policyController.lock(); + break; + case ControllerConfiguration.CONFIG_CONTROLLER_OPERATION_UNLOCK: + policyController.unlock(); + break; + default: + String msg = "Controller Operation Configuration is not supported: " + + operation + " for " + controllerName; + logger.warn(msg); + throw new IllegalArgumentException(msg); + } + + return policyController; + } catch (Exception e) { + logger.error(MessageCodes.EXCEPTION_ERROR, e, "PolicyEngine", "updatePolicyController " + e.getMessage()); + throw e; + } catch (LinkageError e) { + logger.error(MessageCodes.EXCEPTION_ERROR, e, "PolicyEngine", "updatePolicyController " + e.getMessage()); + throw new IllegalStateException(e); + } + } + + /** + * {@inheritDoc} + */ + @Override + public boolean start() throws IllegalStateException { + + if (this.locked) { + throw new IllegalStateException("Engine is locked"); + } + + // Features hook + for (FeatureAPI feature : FeatureAPI.impl.getList()) { + feature.beforeStartEngine(); + } + + synchronized(this) { + this.alive = true; + } + + boolean success = true; + + /* Start Policy Engine exclusively-owned (unmanaged) http servers */ + + for (HttpServletServer httpServer: this.httpServers) { + try { + if (!httpServer.start()) + success = false; + } catch (Exception e) { + logger.error(MessageCodes.EXCEPTION_ERROR, e, httpServer.toString(), this.toString()); + } + } + /* Start Policy Engine exclusively-owned (unmanaged) sources */ + + for (TopicSource source: this.sources) { + try { + if (!source.start()) + success = false; + } catch (Exception e) { + logger.error(MessageCodes.EXCEPTION_ERROR, e, source.toString(), this.toString()); + } + } + + /* Start Policy Engine owned (unmanaged) sinks */ + + for (TopicSink sink: this.sinks) { + try { + if (!sink.start()) + success = false; + } catch (Exception e) { + logger.error(MessageCodes.EXCEPTION_ERROR, e, sink.toString(), this.toString()); + } + } + + /* Start Policy Controllers */ + + List<PolicyController> controllers = PolicyController.factory.inventory(); + for (PolicyController controller : controllers) { + try { + if (!controller.start()) + success = false; + } catch (Exception e) { + logger.error(MessageCodes.EXCEPTION_ERROR, e, controller.toString(), this.toString()); + success = false; + } + } + + /* Start managed Topic Endpoints */ + + try { + if (!TopicEndpoint.manager.start()) + success = false; + } catch (IllegalStateException e) { + String msg = "Topic Endpoint Manager is in an invalid state: " + e.getMessage() + " : " + this; + logger.warn(msg); + } + + + // Start the JMX listener + + PdpJmxListener.start(); + + // Features hook + for (FeatureAPI feature : FeatureAPI.impl.getList()) { + feature.afterStartEngine(); + } + + return success; + } + + /** + * {@inheritDoc} + */ + @Override + public boolean stop() { + + /* stop regardless of the lock state */ + + synchronized(this) { + if (!this.alive) + return true; + + this.alive = false; + } + + boolean success = true; + List<PolicyController> controllers = PolicyController.factory.inventory(); + for (PolicyController controller : controllers) { + try { + if (!controller.stop()) + success = false; + } catch (Exception e) { + logger.error(MessageCodes.EXCEPTION_ERROR, e, controller.toString(), this.toString()); + success = false; + } + } + + /* Stop Policy Engine owned (unmanaged) sources */ + for (TopicSource source: this.sources) { + try { + if (!source.stop()) + success = false; + } catch (Exception e) { + logger.error(MessageCodes.EXCEPTION_ERROR, e, source.toString(), this.toString()); + } + } + + /* Stop Policy Engine owned (unmanaged) sinks */ + for (TopicSink sink: this.sinks) { + try { + if (!sink.stop()) + success = false; + } catch (Exception e) { + logger.error(MessageCodes.EXCEPTION_ERROR, e, sink.toString(), this.toString()); + } + } + + /* stop all managed topics sources and sinks */ + if (!TopicEndpoint.manager.stop()) + success = false; + + /* stop all unmanaged http servers */ + for (HttpServletServer httpServer: this.httpServers) { + try { + if (!httpServer.stop()) + success = false; + } catch (Exception e) { + logger.error(MessageCodes.EXCEPTION_ERROR, e, httpServer.toString(), this.toString()); + } + } + + return success; + } + + /** + * {@inheritDoc} + */ + @Override + public void shutdown() throws IllegalStateException { + + synchronized(this) { + this.alive = false; + } + + // feature hook reporting that the Policy Engine is being shut down + for (FeatureAPI feature : FeatureAPI.impl.getList()) { + feature.beforeShutdownEngine(); + } + + /* Shutdown Policy Engine owned (unmanaged) sources */ + for (TopicSource source: this.sources) { + try { + source.shutdown(); + } catch (Exception e) { + logger.error(MessageCodes.EXCEPTION_ERROR, e, source.toString(), this.toString()); + } + } + + /* Shutdown Policy Engine owned (unmanaged) sinks */ + for (TopicSink sink: this.sinks) { + try { + sink.shutdown(); + } catch (Exception e) { + logger.error(MessageCodes.EXCEPTION_ERROR, e, sink.toString(), this.toString()); + } + } + + /* Shutdown managed resources */ + PolicyController.factory.shutdown(); + TopicEndpoint.manager.shutdown(); + HttpServletServer.factory.destroy(); + + // Stop the JMX listener + + PdpJmxListener.stop(); + + // feature hook reporting that the Policy Engine has being shut down + for (FeatureAPI feature : FeatureAPI.impl.getList()) { + feature.afterShutdownEngine(); + } + + new Thread(new Runnable() { + @Override + public void run() { + try { + Thread.sleep(5000L); + } catch (InterruptedException e) { + logger.warn("InterruptedException while shutting down management server: " + this.toString()); + } + + /* shutdown all unmanaged http servers */ + for (HttpServletServer httpServer: getHttpServers()) { + try { + httpServer.shutdown(); + } catch (Exception e) { + logger.error(MessageCodes.EXCEPTION_ERROR, e, httpServer.toString(), this.toString()); + } + } + + try { + Thread.sleep(5000L); + } catch (InterruptedException e) { + logger.warn("InterruptedException while shutting down management server: " + this.toString()); + } + + System.exit(0); + } + }).start(); + } + + /** + * {@inheritDoc} + */ + @Override + public boolean isAlive() { + return this.alive; + } + + /** + * {@inheritDoc} + */ + @Override + public boolean lock() { + + synchronized(this) { + if (this.locked) + return true; + + this.locked = true; + } + + boolean success = true; + List<PolicyController> controllers = PolicyController.factory.inventory(); + for (PolicyController controller : controllers) { + try { + success = controller.lock() && success; + } catch (Exception e) { + logger.error(MessageCodes.EXCEPTION_ERROR, e, controller.toString(), this.toString()); + success = false; + } + } + + success = TopicEndpoint.manager.lock(); + return success; + } + + /** + * {@inheritDoc} + */ + @Override + public boolean unlock() { + synchronized(this) { + if (!this.locked) + return true; + + this.locked = false; + } + + boolean success = true; + List<PolicyController> controllers = PolicyController.factory.inventory(); + for (PolicyController controller : controllers) { + try { + success = controller.unlock() && success; + } catch (Exception e) { + logger.error(MessageCodes.EXCEPTION_ERROR, e, controller.toString(), this.toString()); + success = false; + } + } + + success = TopicEndpoint.manager.unlock(); + return success; + } + + /** + * {@inheritDoc} + */ + @Override + public boolean isLocked() { + return this.locked; + } + + /** + * {@inheritDoc} + */ + @Override + public void removePolicyController(String name) { + PolicyController.factory.destroy(name); + } + + /** + * {@inheritDoc} + */ + @Override + public void removePolicyController(PolicyController controller) { + PolicyController.factory.destroy(controller); + } + + /** + * {@inheritDoc} + */ + @JsonIgnore + @Override + public List<PolicyController> getPolicyControllers() { + return PolicyController.factory.inventory(); + } + + /** + * {@inheritDoc} + */ + @Override + public List<String> getControllers() { + List<String> controllerNames = new ArrayList<String>(); + for (PolicyController controller: PolicyController.factory.inventory()) { + controllerNames.add(controller.getName()); + } + return controllerNames; + } + + /** + * {@inheritDoc} + */ + @Override + public Properties getProperties() { + return this.properties; + } + + + /** + * {@inheritDoc} + */ + @SuppressWarnings("unchecked") + @Override + public List<TopicSource> getSources() { + return (List<TopicSource>) this.sources; + } + + /** + * {@inheritDoc} + */ + @SuppressWarnings("unchecked") + @Override + public List<TopicSink> getSinks() { + return (List<TopicSink>) this.sinks; + } + + /** + * {@inheritDoc} + */ + @Override + public List<HttpServletServer> getHttpServers() { + return this.httpServers; + } + + /** + * {@inheritDoc} + */ + @Override + public boolean onTopicEvent(CommInfrastructure commType, String topic, String event) { + /* configuration request */ + try { + PdpdConfiguration configuration = this.decoder.fromJson(event, PdpdConfiguration.class); + this.configure(configuration); + } catch (Exception e) { + logger.error(MessageCodes.EXCEPTION_ERROR, e, "CONFIGURATION ERROR IN PDP-D POLICY ENGINE: "+ event + ":" + e.getMessage() + ":" + this); + } + + return true; + } + + /** + * {@inheritDoc} + */ + @Override + public boolean deliver(String topic, Object event) + throws IllegalArgumentException, IllegalStateException { + + /* + * Note this entry point is usually from the DRL + */ + + if (topic == null || topic.isEmpty()) + throw new IllegalArgumentException("Invalid Topic"); + + if (event == null) + throw new IllegalArgumentException("Invalid Event"); + + if (!this.isAlive()) + throw new IllegalStateException("Policy Engine is stopped"); + + if (this.isLocked()) + throw new IllegalStateException("Policy Engine is locked"); + + List<? extends TopicSink> sinks = + TopicEndpoint.manager.getTopicSinks(topic); + if (sinks == null || sinks.isEmpty() || sinks.size() > 1) + throw new IllegalStateException + ("Cannot ensure correct delivery on topic " + topic + ": " + sinks); + + return this.deliver(sinks.get(0).getTopicCommInfrastructure(), + topic, event); + } + + /** + * {@inheritDoc} + */ + @Override + public boolean deliver(String busType, String topic, Object event) + throws IllegalArgumentException, IllegalStateException, + UnsupportedOperationException { + + /* + * Note this entry point is usually from the DRL (one of the reasons + * busType is String. + */ + + if (busType == null || busType.isEmpty()) + throw new IllegalArgumentException + ("Invalid Communication Infrastructure"); + + if (topic == null || topic.isEmpty()) + throw new IllegalArgumentException("Invalid Topic"); + + if (event == null) + throw new IllegalArgumentException("Invalid Event"); + + boolean valid = false; + for (Topic.CommInfrastructure comm: Topic.CommInfrastructure.values()) { + if (comm.name().equals(busType)) { + valid = true; + } + } + + if (!valid) + throw new IllegalArgumentException + ("Invalid Communication Infrastructure: " + busType); + + + if (!this.isAlive()) + throw new IllegalStateException("Policy Engine is stopped"); + + if (this.isLocked()) + throw new IllegalStateException("Policy Engine is locked"); + + + return this.deliver(Topic.CommInfrastructure.valueOf(busType), + topic, event); + } + + /** + * {@inheritDoc} + */ + @Override + public boolean deliver(Topic.CommInfrastructure busType, + String topic, Object event) + throws IllegalArgumentException, IllegalStateException, + UnsupportedOperationException { + + if (topic == null || topic.isEmpty()) + throw new IllegalArgumentException("Invalid Topic"); + + if (event == null) + throw new IllegalArgumentException("Invalid Event"); + + if (!this.isAlive()) + throw new IllegalStateException("Policy Engine is stopped"); + + if (this.isLocked()) + throw new IllegalStateException("Policy Engine is locked"); + + /* Try to send through the controller, this is the + * preferred way, since it may want to apply additional + * processing + */ + try { + DroolsController droolsController = + EventProtocolCoder.manager.getDroolsController(topic, event); + PolicyController controller = PolicyController.factory.get(droolsController); + if (controller != null) + return controller.deliver(busType, topic, event); + } catch (Exception e) { + logger.warn(MessageCodes.EXCEPTION_ERROR, e, + busType + ":" + topic + " :" + event, this.toString()); + /* continue (try without routing through the controller) */ + } + + /* + * cannot route through the controller, send directly through + * the topic sink + */ + try { + String json = EventProtocolCoder.manager.encode(topic, event); + return this.deliver(busType, topic, json); + + } catch (Exception e) { + logger.warn(MessageCodes.EXCEPTION_ERROR, e, + busType + ":" + topic + " :" + event, this.toString()); + throw e; + } + } + + /** + * {@inheritDoc} + */ + @Override + public boolean deliver(Topic.CommInfrastructure busType, + String topic, String event) + throws IllegalArgumentException, IllegalStateException, + UnsupportedOperationException { + + if (topic == null || topic.isEmpty()) + throw new IllegalArgumentException("Invalid Topic"); + + if (event == null || event.isEmpty()) + throw new IllegalArgumentException("Invalid Event"); + + if (!this.isAlive()) + throw new IllegalStateException("Policy Engine is stopped"); + + if (this.isLocked()) + throw new IllegalStateException("Policy Engine is locked"); + + try { + TopicSink sink = + TopicEndpoint.manager.getTopicSink + (busType, topic); + + if (sink == null) + throw new IllegalStateException("Inconsistent State: " + this); + + return sink.send(event); + + } catch (Exception e) { + logger.warn(MessageCodes.EXCEPTION_ERROR, e, + busType + ":" + topic + " :" + event, this.toString()); + throw e; + } + } + + /** + * {@inheritDoc} + */ + @Override + public synchronized void activate() { + + // activate 'policy-management' + for (PolicyController policyController : getPolicyControllers()) { + try { + policyController.unlock(); + policyController.start(); + } catch (Exception e) { + logger.error(MessageCodes.EXCEPTION_ERROR, e, "PolicyEngine.activate: cannot start " + + policyController + " because of " + e.getMessage()); + } catch (LinkageError e) { + logger.error(MessageCodes.EXCEPTION_ERROR, e, "PolicyEngine.activate: cannot start " + + policyController + " because of " + e.getMessage()); + } + } + + this.unlock(); + } + + /** + * {@inheritDoc} + */ + @Override + public synchronized void deactivate() { + + this.lock(); + + for (PolicyController policyController : getPolicyControllers()) { + try { + policyController.stop(); + } catch (Exception e) { + logger.error(MessageCodes.EXCEPTION_ERROR, e, "PolicyEngine.deactivate: cannot stop " + + policyController + " because of " + e.getMessage()); + } catch (LinkageError e) { + logger.error(MessageCodes.EXCEPTION_ERROR, e, "PolicyEngine.deactivate: cannot start " + + policyController + " because of " + e.getMessage()); + } + } + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("PolicyEngineManager [alive=").append(alive).append(", locked=").append(locked).append("]"); + return builder.toString(); + } + +} + + diff --git a/policy-management/src/main/java/org/openecomp/policy/drools/system/internal/AggregatedPolicyController.java b/policy-management/src/main/java/org/openecomp/policy/drools/system/internal/AggregatedPolicyController.java new file mode 100644 index 00000000..96f9e5bf --- /dev/null +++ b/policy-management/src/main/java/org/openecomp/policy/drools/system/internal/AggregatedPolicyController.java @@ -0,0 +1,462 @@ +/*- + * ============LICENSE_START======================================================= + * policy-management + * ================================================================================ + * 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.system.internal; + +import java.util.HashMap; +import java.util.List; +import java.util.Properties; + +import org.openecomp.policy.drools.controller.DroolsController; +import org.openecomp.policy.drools.event.comm.Topic; +import org.openecomp.policy.drools.event.comm.TopicEndpoint; +import org.openecomp.policy.drools.event.comm.TopicListener; +import org.openecomp.policy.drools.event.comm.TopicSink; +import org.openecomp.policy.drools.event.comm.TopicSource; +import org.openecomp.policy.common.logging.flexlogger.FlexLogger; +import org.openecomp.policy.common.logging.flexlogger.Logger; +import org.openecomp.policy.drools.persistence.SystemPersistence; +import org.openecomp.policy.drools.properties.PolicyProperties; +import org.openecomp.policy.drools.protocol.configuration.DroolsConfiguration; +import org.openecomp.policy.drools.system.PolicyController; +import com.fasterxml.jackson.annotation.JsonIgnore; + +/** + * This implementation of the Policy Controller merely aggregates and tracks for + * management purposes all underlying resources that this controller depends upon. + */ +public class AggregatedPolicyController implements PolicyController, + TopicListener { + + /** + * Logger + */ + private static Logger logger = FlexLogger.getLogger(AggregatedPolicyController.class); + + /** + * identifier for this policy controller + */ + protected final String name; + + /** + * Abstracted Event Sources List regardless communication + * technology + */ + protected final List<? extends TopicSource> sources; + + /** + * Abstracted Event Sinks List regardless communication + * technology + */ + protected final List<? extends TopicSink> sinks; + + /** + * Mapping topics to sinks + */ + @JsonIgnore + protected final HashMap<String, TopicSink> topic2Sinks = + new HashMap<String, TopicSink>(); + + /** + * Is this Policy Controller running (alive) ? + * reflects invocation of start()/stop() only + */ + protected volatile boolean alive; + + /** + * Is this Policy Controller locked ? + * reflects if i/o controller related operations and start + * are permitted, + * more specifically: start(), deliver() and onTopicEvent(). + * It does not affect the ability to stop the + * underlying drools infrastructure + */ + protected volatile boolean locked; + + /** + * Policy Drools Controller + */ + protected volatile DroolsController droolsController; + + /** + * Properties used to initialize controller + */ + protected final Properties properties; + + /** + * Constructor version mainly used for bootstrapping at initialization time + * a policy engine controller + * + * @param name controller name + * @param properties + * + * @throws IllegalArgumentException when invalid arguments are provided + */ + public AggregatedPolicyController(String name, Properties properties) + throws IllegalArgumentException { + + this.name = name; + + /* + * 1. Register read topics with network infrastructure (ueb, dmaap, rest) + * 2. Register write topics with network infrastructure (ueb, dmaap, rest) + * 3. Register with drools infrastructure + */ + + // Create/Reuse Readers/Writers for all event sources endpoints + + this.sources = TopicEndpoint.manager.addTopicSources(properties); + this.sinks = TopicEndpoint.manager.addTopicSinks(properties); + + initDrools(properties); + initSinks(); + + /* persist new properties */ + SystemPersistence.manager.storeController(name, properties); + this.properties = properties; + } + + /** + * initialize drools layer + * @throws IllegalArgumentException if invalid parameters are passed in + */ + protected void initDrools(Properties properties) throws IllegalArgumentException { + try { + // Register with drools infrastructure + this.droolsController = DroolsController.factory.build(properties, sources, sinks); + } catch (Exception | LinkageError e) { + logger.error("BUILD-INIT-DROOLS: " + e.getMessage()); + e.printStackTrace(); + + // throw back exception as input properties cause problems + throw new IllegalArgumentException(e); + } + } + + /** + * initialize sinks + * @throws IllegalArgumentException if invalid parameters are passed in + */ + protected void initSinks() throws IllegalArgumentException { + this.topic2Sinks.clear(); + for (TopicSink sink: sinks) { + this.topic2Sinks.put(sink.getTopic(), sink); + } + } + + /** + * {@inheritDoc} + */ + @Override + public boolean updateDrools(DroolsConfiguration newDroolsConfiguration) { + + DroolsConfiguration oldDroolsConfiguration = + new DroolsConfiguration(this.droolsController.getArtifactId(), + this.droolsController.getGroupId(), + this.droolsController.getVersion()); + + if (oldDroolsConfiguration.getGroupId().equalsIgnoreCase(newDroolsConfiguration.getGroupId()) && + oldDroolsConfiguration.getArtifactId().equalsIgnoreCase(newDroolsConfiguration.getArtifactId()) && + oldDroolsConfiguration.getVersion().equalsIgnoreCase(newDroolsConfiguration.getVersion())) { + logger.warn("UPDATE-DROOLS: nothing to do: identical configuration: " + oldDroolsConfiguration + + " <=> " + newDroolsConfiguration); + return true; + } + + try { + /* Drools Controller created, update initialization properties for restarts */ + + this.properties.setProperty(PolicyProperties.RULES_GROUPID, newDroolsConfiguration.getGroupId()); + this.properties.setProperty(PolicyProperties.RULES_ARTIFACTID, newDroolsConfiguration.getArtifactId()); + this.properties.setProperty(PolicyProperties.RULES_VERSION, newDroolsConfiguration.getVersion()); + + SystemPersistence.manager.storeController(name, this.properties); + + this.initDrools(this.properties); + + /* set drools controller to current locked status */ + + if (this.isLocked()) + this.droolsController.lock(); + else + this.droolsController.unlock(); + + /* set drools controller to current alive status */ + + if (this.isAlive()) + this.droolsController.start(); + else + this.droolsController.stop(); + + } catch (IllegalArgumentException e) { + logger.warn("INIT-DROOLS: " + e.getMessage()); + e.printStackTrace(); + return false; + } + + return true; + } + + /** + * {@inheritDoc} + */ + @Override + public String getName() { + return this.name; + } + + /** + * {@inheritDoc} + */ + @Override + public boolean start() throws IllegalStateException { + if (logger.isInfoEnabled()) + logger.info("START: " + this); + + if (this.isLocked()) + throw new IllegalStateException("Policy Controller " + name + " is locked"); + + synchronized(this) { + if (this.alive) + return true; + + this.alive = true; + } + + boolean success = this.droolsController.start(); + + // register for events + + for (TopicSource source: sources) { + source.register(this); + } + + for (TopicSink sink: sinks) { + try { + sink.start(); + } catch (Exception e) { + logger.warn("can't start sink: " + sink + " because of " + e.getMessage()); + e.printStackTrace(); + } + } + + return success; + } + + /** + * {@inheritDoc} + */ + @Override + public boolean stop() { + + logger.info("STOP: " + this); + + /* stop regardless locked state */ + + synchronized(this) { + if (!this.alive) + return true; + + this.alive = false; + } + + // 1. Stop registration + + for (TopicSource source: sources) { + source.unregister(this); + } + + boolean success = this.droolsController.stop(); + return success; + } + + /** + * {@inheritDoc} + */ + @Override + public void shutdown() throws IllegalStateException { + if (logger.isInfoEnabled()) + logger.info(this + "SHUTDOWN"); + + this.stop(); + + DroolsController.factory.shutdown(this.droolsController); + } + + /** + * {@inheritDoc} + */ + @Override + public void halt() throws IllegalStateException { + if (logger.isInfoEnabled()) + logger.info(this + "HALT"); + + this.stop(); + DroolsController.factory.destroy(this.droolsController); + SystemPersistence.manager.deleteController(this.name); + } + + /** + * {@inheritDoc} + */ + @Override + public boolean onTopicEvent(Topic.CommInfrastructure commType, + String topic, String event) { + + logger.info("EVENT NOTIFICATION: " + commType + ":" + topic + ":" + event + " INTO " + this); + + if (this.locked) + return false; + + if (!this.alive) + return true; + + return this.droolsController.offer(topic, event); + } + + /** + * {@inheritDoc} + */ + @Override + public boolean deliver(Topic.CommInfrastructure commType, + String topic, Object event) + throws IllegalArgumentException, IllegalStateException, + UnsupportedOperationException { + + logger.info("DELIVER: " + commType + ":" + topic + ":" + event + " FROM " + this); + + if (topic == null || topic.isEmpty()) + throw new IllegalArgumentException("Invalid Topic"); + + if (event == null) + throw new IllegalArgumentException("Invalid Event"); + + if (!this.isAlive()) + throw new IllegalStateException("Policy Engine is stopped"); + + if (this.isLocked()) + throw new IllegalStateException("Policy Engine is locked"); + + if (!this.topic2Sinks.containsKey(topic)) { + logger.error("UNDELIVERED: " + commType + ":" + topic + ":" + event + " FROM " + this); + throw new IllegalArgumentException + ("Unsuported topic " + topic + " for delivery"); + } + + return this.droolsController.deliver + (this.topic2Sinks.get(topic), event); + } + + /** + * {@inheritDoc} + */ + @Override + public boolean isAlive() { + return this.alive; + } + + /** + * {@inheritDoc} + */ + @Override + public boolean lock() { + logger.info("LOCK: " + this); + + synchronized(this) { + if (this.locked) + return true; + + this.locked = true; + } + + // it does not affect associated sources/sinks, they are + // autonomous entities + + return this.droolsController.lock(); + } + + /** + * {@inheritDoc} + */ + @Override + public boolean unlock() { + logger.info("UNLOCK: " + this); + + synchronized(this) { + if (!this.locked) + return true; + + this.locked = false; + } + + return this.droolsController.unlock(); + } + + /** + * {@inheritDoc} + */ + @Override + public boolean isLocked() { + return this.locked; + } + + /** + * {@inheritDoc} + */ + @Override + public List<? extends TopicSource> getTopicSources() { + return this.sources; + } + + /** + * {@inheritDoc} + */ + @Override + public List<? extends TopicSink> getTopicSinks() { + return this.sinks; + } + + /** + * {@inheritDoc} + */ + @Override + public DroolsController getDrools() { + return this.droolsController; + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("AggregatedPolicyController [name=").append(name).append(", sources=").append(sources) + .append(", sinks=").append(sinks).append(", alive=").append(alive).append(", locked=").append(locked) + .append(", droolsController=").append(droolsController).append("]"); + return builder.toString(); + } + + /** + * {@inheritDoc} + */ + @Override + public Properties getInitializationProperties() { + return this.properties; + } + +} + diff --git a/policy-management/src/main/server-gen/bin/add-secured-participant.sh b/policy-management/src/main/server-gen/bin/add-secured-participant.sh new file mode 100644 index 00000000..d6843fee --- /dev/null +++ b/policy-management/src/main/server-gen/bin/add-secured-participant.sh @@ -0,0 +1,122 @@ +#! /bin/bash + +### +# ============LICENSE_START======================================================= +# policy-management +# ================================================================================ +# 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========================================================= +### + +function usage() { + echo -n "Usage: $(basename $0) " + echo -n "[(-d|--debug)] " + echo -n "(-h|--host) <bus-host> " + echo -n "[(-p|--port) <bus-port>] " + echo -n "(-k|--key) <api-key> " + echo -n "(-s|--secret) <api-secret> " + echo -n "(-P|--producer-key) <producer-key> " + echo -n "(-C|--consumer-key) <consumer-key> " + echo "(-t|--topic) <topic> " +} + +BUS_PORT=3904 + +# command line options parsing +until [[ -z "$1" ]]; do + case $1 in + -d|--debug) set -x + ;; + -h|--host) shift + BUS_HOST=$1 + ;; + -p|--port) shift + BUS_PORT=$1 + ;; + -k|--key) shift + API_KEY=$1 + ;; + -s|--secret) shift + API_SECRET=$1 + ;; + -t|--topic) shift + TOPIC=$1 + ;; + -P|--producer-key) shift + URL_CONTEXT="producers" + PRODUCER_KEY=$1 + KEY=$1 + ;; + -C|--consumer-key) shift + URL_CONTEXT="consumers" + CONSUMER_KEY=$1 + KEY=$1 + ;; + *) usage + exit 1 + ;; + esac + shift +done + +if [[ -z ${BUS_HOST} ]]; then + echo "An UEB/DMAAP server must be provided." + echo + usage + exit 1 +fi + +if [[ -z ${API_KEY} ]]; then + echo "The API Key must be provided." + usage + exit 2 +fi + +if [[ -z ${API_SECRET} ]]; then + echo "The API Secret must be provided." + usage + exit 3 +fi + +if [[ -z ${TOPIC} ]]; then + echo "The Topic Name must be provided." + usage + exit 3 +fi + +if [[ -z ${PRODUCER_KEY} && -z ${CONSUMER_KEY} ]]; then + echo "Either the Producer or Consumer options must be provided." + usage + exit 4 +fi + +if [[ -n ${PRODUCER_KEY} && -n ${CONSUMER_KEY} ]]; then + echo "Only and only one of the Producer or Consumer options must be provided." + usage + exit 5 +fi + + +DATE=$(date) +DATE_HASH=$(echo -n "${DATE}" | openssl sha1 -hmac "${API_SECRET}" -binary | openssl base64) + +unset http_proxy +curl --silent -X PUT \ + --header "Accept:" \ + --header "X-CambriaDate: ${DATE}" \ + --header "X-CambriaAuth: ${API_KEY}:${DATE_HASH}" \ + --header "Content-Type: application/json" \ + --data "{}" \ + http://${BUS_HOST}:${BUS_PORT}/topics/${TOPIC}/${URL_CONTEXT}/${KEY} diff --git a/policy-management/src/main/server-gen/bin/create-api-key.sh b/policy-management/src/main/server-gen/bin/create-api-key.sh new file mode 100644 index 00000000..ea0ec7ad --- /dev/null +++ b/policy-management/src/main/server-gen/bin/create-api-key.sh @@ -0,0 +1,76 @@ +#! /bin/bash + +### +# ============LICENSE_START======================================================= +# policy-management +# ================================================================================ +# 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========================================================= +### + +function usage() { + echo -n "Usage: $(basename $0) " + echo -n "[(-d|--debug)] " + echo -n "(-h|--host) <bus-host> " + echo -n "[(-p|--port) <bus-port>] " + echo "(-e|--email) <email>" +} + +BUS_PORT=3904 + +# command line options parsing +until [[ -z "$1" ]]; do + case $1 in + -d|--debug) set -x + ;; + -h|--host) shift + BUS_HOST=$1 + ;; + -p|--port) shift + BUS_PORT=$1 + ;; + -e|--email) shift + EMAIL=$1 + ;; + *) usage + exit 1 + ;; + esac + shift +done + +if [[ -z ${BUS_HOST} ]]; then + echo "An UEB/DMAAP server must be provided." + echo + usage + exit 1 +fi + +if [[ -z ${EMAIL} ]]; then + echo "An email address must be provided." + usage + exit 2 +fi + +REQUEST_API_KEY_BODY=$(< <(cat <<EOF +{ + "email": "${EMAIL}", + "description": "Generated by PDP-D $(hostname -f)" +} +EOF +)) + +unset http_proxy +curl -s -X POST --data "${REQUEST_API_KEY_BODY}" --header "Content-Type: application/json" http://${BUS_HOST}:${BUS_PORT}/v1/apiKeys/create diff --git a/policy-management/src/main/server-gen/bin/create-secured-topic.sh b/policy-management/src/main/server-gen/bin/create-secured-topic.sh new file mode 100644 index 00000000..b0d4d6f2 --- /dev/null +++ b/policy-management/src/main/server-gen/bin/create-secured-topic.sh @@ -0,0 +1,130 @@ +#! /bin/bash + +### +# ============LICENSE_START======================================================= +# policy-management +# ================================================================================ +# 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========================================================= +### + +function usage() { + echo -n "Usage: $(basename $0) " + echo -n "[(-d|--debug)] " + echo -n "(-h|--host) <bus-host> " + echo -n "[(-p|--port) <bus-port>] " + echo -n "(-k|--key) <api-key> " + echo -n "(-s|--secret) <api-secret> " + echo -n "[(-P|--partition) <partition-count>] " + echo -n "[(-R|--replication) <replication-count>] " + echo "(-t|--topic) <topic> " + echo "" +} + +BUS_PORT=3904 +PARTITION_COUNT=1 +REPLICATION_COUNT=1 + +# command line options parsing +until [[ -z "$1" ]]; do + case $1 in + -d|--debug) set -x + ;; + -h|--host) shift + BUS_HOST=$1 + ;; + -p|--port) shift + BUS_PORT=$1 + ;; + -k|--key) shift + API_KEY=$1 + ;; + -s|--secret) shift + API_SECRET=$1 + ;; + -t|--topic) shift + TOPIC=$1 + ;; + -P|--partition-count) shift + PARTITION_COUNT=$1 + ;; + -R|--replication-count) shift + REPLICATION_COUNT=$1 + ;; + *) usage + exit 1 + ;; + esac + shift +done + +if [[ -z ${BUS_HOST} ]]; then + echo "An UEB/DMAAP server must be provided." + echo + usage + exit 1 +fi + +if [[ -z ${API_KEY} ]]; then + echo "The API Key must be provided." + usage + exit 2 +fi + +if [[ -z ${API_SECRET} ]]; then + echo "The API Secret must be provided." + usage + exit 3 +fi + +if [[ -z ${TOPIC} ]]; then + echo "The Topic Name must be provided." + usage + exit 3 +fi + +if [[ -z ${PARTITION_COUNT} ]]; then + echo "The Partition Count must be provided." + usage + exit 4 +fi + +if [[ -z ${REPLICATION_COUNT} ]]; then + echo "The Replication Count must be provided." + usage + exit 5 +fi + +REQUEST_API_KEY_BODY=$(< <(cat <<EOF +{ + "topicName": "${TOPIC}", + "topicDescription": "Generated by PDP-D $(hostname -f)", + "partitionCount": ${PARTITION_COUNT}, + "replicationCount": ${REPLICATION_COUNT} +} +EOF +)) + +DATE=$(date) +DATE_HASH=$(echo -n "${DATE}" | openssl sha1 -hmac "${API_SECRET}" -binary | openssl base64) + +unset http_proxy +curl --silent -X POST \ + --header "Accept:" \ + --header "X-CambriaDate: ${DATE}" \ + --header "X-CambriaAuth: ${API_KEY}:${DATE_HASH}" \ + --header "Content-Type: application/json" \ + --data "${REQUEST_API_KEY_BODY}" \ + http://${BUS_HOST}:${BUS_PORT}/topics/create diff --git a/policy-management/src/main/server-gen/bin/options b/policy-management/src/main/server-gen/bin/options new file mode 100644 index 00000000..a9ae7125 --- /dev/null +++ b/policy-management/src/main/server-gen/bin/options @@ -0,0 +1,125 @@ +#! /bin/bash + +lib=${POLICY_HOME}/lib +opt=${lib}/opt + +# change to the options directory +cd ${opt} + +# default field lengths +nameLength=20 +versionLength=15 + +# update field lengths, if needed +for jar in $(ls) ; do + # get file name without 'jar' suffix + tmp="${jar%\.jar}" + + # get feature name by removing the version portion + name="${tmp%%-[0-9]*}" + + # extract version portion of name + version="${tmp#${name}-}" + + # grow the size of the name/version field, if needed + if (( "${#name}" > nameLength )) ; then + nameLength="${#name}" + fi + if (( "${#version}" > versionLength )) ; then + versionLength="${#version}" + fi +done + +# dump out status information +function status +{ + local tmp name version status + local format="%-${nameLength}s %-${versionLength}s %s\n" + + printf "${format}" "name" "version" "status" + printf "${format}" "----" "-------" "------" + for jar in $(ls) ; do + # get file name without 'jar' suffix + tmp="${jar%\.jar}" + + # get feature name by removing the version portion + name="${tmp%%-[0-9]*}" + + # extract version portion of name + version="${tmp#${name}-}" + + # determine status + status=disabled + if [[ -e "${lib}/${jar}" ]] ; then + status=enabled + fi + printf "${format}" "${name}" "${version}" "${status}" + done +} + +case "$1" in + status) + { + # dump out status information + status + };; + + enable) + { + # enable the specified options + shift + match= + for name in "$@" ; do + # look for matches - 'file' has the full path name + file=$(ls ${opt}/"${name}"-[0-9]* 2>/dev/null) + if [[ "$?" != 0 ]] ; then + # no matching file + echo "${name}: no such option" + else + # found a match (handle multiple matches, just in case) + match=true + ln -s -f ${file} "${lib}/" + fi + done + if [[ "${match}" ]] ; then + echo + status + fi + };; + + disable) + { + # disable the specified options + shift + match= + for name in "$@" ; do + # look for matches -- 'file' has the last segment of the path name + file=$(ls "${name}"-[0-9]* 2>/dev/null) + if [[ "$?" != 0 ]] ; then + echo "${name}: no such option" + else + # found a match (handle multiple matches, just in case) + match=true + (cd ${lib} ; rm -f ${file}) + fi + done + if [[ "${match}" ]] ; then + echo + status + fi + };; + + *) + { + # print out usage information + cat >&2 <<-'EOF' + Usage: options status + Get enabled/disabled status on all options + options enable <option> ... + Enable the specified options + options disable <option> ... + Disable the specified options + EOF + };; +esac +exit diff --git a/policy-management/src/main/server-gen/bin/pdpd-configuration.sh b/policy-management/src/main/server-gen/bin/pdpd-configuration.sh new file mode 100644 index 00000000..8c553927 --- /dev/null +++ b/policy-management/src/main/server-gen/bin/pdpd-configuration.sh @@ -0,0 +1,200 @@ +#! /bin/bash + +### +# ============LICENSE_START======================================================= +# policy-management +# ================================================================================ +# 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========================================================= +### + +function usage() { + echo -n "Usage: $(basename $0) " + echo -n "[(-d|--debug)] " + echo -n "(-h|--host) <bus-host> " + echo -n "[(-p|--port) <bus-port>] " + echo -n "[(-k|--key) <api-key>] " + echo -n "[(-s|--secret) <api-secret>] " + echo -n "[(-r|--request-id) <request-id>] " + echo -n "(-c|--controller-name) <controller-name> " + echo -n "(-o|--operation) <create|update|lock|unlock> " + echo -n "[(-g|--group-id) <group-id> " + echo -n "(-a|--artifact-id) <artifact-id> " + echo -n "(-v|--version) <version>] " + echo -n "[(-t|--topic) <topic>] " + echo "" +} + +BUS_PORT=3904 +ENTITY=controller +REQUEST_ID="7f5474ca-16a9-42ac-abc0-d86f62296fbc" +TOPIC="PDPD_CONFIGURATION" + +# command line options parsing +until [[ -z "$1" ]]; do + case $1 in + -d|--debug) set -x + ;; + -h|--host) shift + BUS_HOST=$1 + ;; + -p|--port) shift + BUS_PORT=$1 + ;; + -r|--request-id) shift + REQUEST_ID=$1 + ;; + -k|--key) shift + API_KEY=$1 + ;; + -s|--secret) shift + API_SECRET=$1 + ;; + -c|--controller-name) shift + CONTROLLER_NAME=$1 + ;; + -o|--operation) shift + OPERATION=$1 + ;; + -g|--group-id) shift + GROUP_ID=$1 + ;; + -a|--artifact-id) shift + ARTIFACT_ID=$1 + ;; + -v|--version) shift + VERSION=$1 + ;; + -t|--topic) shift + TOPIC=$1 + ;; + *) usage + exit 1 + ;; + esac + shift +done + +if [[ -z ${BUS_HOST} ]]; then + echo "An UEB/DMAAP server must be provided." + echo + usage + exit 1 +fi + +if [[ -z ${CONTROLLER_NAME} ]]; then + echo "The controller-name must be provided." + usage + exit 2 +fi + +if [[ -z ${OPERATION} ]]; then + echo "The operation must be provided: create|update|lock|unlock" + usage + exit 3 +fi + +if [[ ${OPERATION} == "create" ]] || [[ ${OPERATION} == "update" ]]; then + if [[ -z ${GROUP_ID} ]]; then + echo "The maven group id must be provided when operation is create|update" + usage + exit 4 + fi + + if [[ -z ${ARTIFACT_ID} ]]; then + echo "The maven artifact id must be provided when operation is create|update" + usage + exit 5 + fi + + if [[ -z ${VERSION} ]]; then + echo "The maven version must be provided when operation is create|update" + usage + exit 6 + fi +fi + +UPDATE_BODY=$(< <(cat <<EOF +{ + "requestID": "${REQUEST_ID}", + "entity": "controller", + "controllers": [{ + "name": "${CONTROLLER_NAME}", + "drools": { + "groupId": "${GROUP_ID}", + "artifactId": "${ARTIFACT_ID}", + "version": "${VERSION}" + }, + "operation": "${OPERATION}" + }] +} + +EOF +)) + +LOCK_BODY=$(< <(cat <<EOF +{ + "requestID": "${REQUEST_ID}", + "entity": "controller", + "controllers": [{ + "name": "${CONTROLLER_NAME}", + "operation": "${OPERATION}" + }] +} + +EOF +)) + +unset http_proxy + +if [[ ${OPERATION} == "lock" ]] || [[ ${OPERATION} == "unlock" ]]; then + if [[ -n ${API_KEY} ]]; then + DATE=$(date) + DATE_HASH=$(echo -n "${DATE}" | openssl sha1 -hmac "${API_SECRET}" -binary | openssl base64) + curl --silent -X POST \ + --header "Accept:" \ + --header "X-CambriaDate: ${DATE}" \ + --header "X-CambriaAuth: ${API_KEY}:${DATE_HASH}" \ + --header "Content-Type: application/json" \ + --data "${LOCK_BODY}" \ + http://${BUS_HOST}:${BUS_PORT}/events/${TOPIC} + else + curl --silent -X POST \ + --header "Accept:" \ + --header "Content-Type: application/json" \ + --data "${LOCK_BODY}" \ + http://${BUS_HOST}:${BUS_PORT}/events/${TOPIC} + fi +fi + +if [[ ${OPERATION} == "create" ]] || [[ ${OPERATION} == "update" ]]; then + if [[ -n ${API_KEY} ]]; then + DATE=$(date) + DATE_HASH=$(echo -n "${DATE}" | openssl sha1 -hmac "${API_SECRET}" -binary | openssl base64) + curl --silent -X POST \ + --header "Accept:" \ + --header "X-CambriaDate: ${DATE}" \ + --header "X-CambriaAuth: ${API_KEY}:${DATE_HASH}" \ + --header "Content-Type: application/json" \ + --data "${UPDATE_BODY}" \ + http://${BUS_HOST}:${BUS_PORT}/events/${TOPIC} + else + curl --silent -X POST \ + --header "Accept:" \ + --header "Content-Type: application/json" \ + --data "${UPDATE_BODY}" \ + http://${BUS_HOST}:${BUS_PORT}/events/${TOPIC} + fi +fi diff --git a/policy-management/src/main/server-gen/bin/policy-management-controller b/policy-management/src/main/server-gen/bin/policy-management-controller new file mode 100644 index 00000000..4d28d941 --- /dev/null +++ b/policy-management/src/main/server-gen/bin/policy-management-controller @@ -0,0 +1,191 @@ +#!/bin/bash + +SNAME="Policy Management" +PNAME=policy-management +CLASS=org.openecomp.policy.drools.system.Main + + +function start() { + um_start + if [[ ${RETVAL} != 0 ]]; then + update_monitor off + else + update_monitor on + fi +} + +# unmonitored start, does not change monitor status (immutable) +function um_start() { + status + if [ "$_RUNNING" = "1" ]; then + echo $_STATUS + RETVAL=0 + return + fi + mkdir -p $_DIR/logs + if [ -e $_DIR/logs/$PNAME.out.1 ]; then mv $_DIR/logs/$PNAME.out.1 $_DIR/logs/$PNAME.out.2; fi + if [ -e $_DIR/logs/$PNAME.err.1 ]; then mv $_DIR/logs/$PNAME.err.1 $_DIR/logs/$PNAME.err.2; fi + if [ -e $_DIR/logs/$PNAME.out ]; then mv $_DIR/logs/$PNAME.out $_DIR/logs/$PNAME.out.1; fi + if [ -e $_DIR/logs/$PNAME.err ]; then mv $_DIR/logs/$PNAME.err $_DIR/logs/$PNAME.err.1; fi + CP=$(ls $_DIR/lib/*.jar | xargs -I X printf ":%s" X) + + # If 'system.properties' exists, convert it into JVM arguments. + # Note that the following also handles property values with spaces. + IFS=$'\n' + systemProperties=($( + if [[ -f $_DIR/config/system.properties ]] ; then + sed -n -e 's/^[ \t]*\([^ \t#]*\)[ \t]*=[ \t]*\(.*\)$/-D\1=\2/p' \ + $_DIR/config/system.properties + fi + )) + + cd $_DIR + ( + if [[ "${cfg}" != "" ]] ; then + # need to make sure that we don't pass the lock file descriptor + # to subprocesses + exec {cfg}>&- + fi + nohup $JAVA_HOME/bin/java -Dkie.maven.settings.custom=$_DIR/config/kie_settings.xml -Dlog4j.configuration=file:$_DIR/config/log4j.properties -cp $_DIR/config:$_DIR/lib:$CP "${systemProperties[@]}" "$@" $CLASS > >( while read line; do echo "$(date): ${line}"; done > $_DIR/logs/$PNAME.out) 2> >( while read line; do echo "$(date): ${line}"; done > $_DIR/logs/$PNAME.err) & + + _PID=$! + echo $_PID > $_PIDFILE + ) + sleep 5 + status + echo $_STATUS + if [ "$_RUNNING" = "1" ]; then + RETVAL=0 + else + echo "Failed to start" + remove_pid_file + RETVAL=1 + fi +} + +function stop() { + um_stop + update_monitor off +} + +# unmonitored stop, does not change monitor status (immutable) +function um_stop() { + status + if [ "$_RUNNING" = "0" ]; then + echo $_STATUS + remove_pid_file + else + if [[ -n ${ENGINE_MANAGEMENT_PASSWORD} ]]; then + http_proxy= curl --silent --user ${ENGINE_MANAGEMENT_USER}:${ENGINE_MANAGEMENT_PASSWORD} -X DELETE http://localhost:${ENGINE_MANAGEMENT_PORT}/policy/pdp/engine -o /dev/null + else + http_proxy= curl --silent -X DELETE http://localhost:${ENGINE_MANAGEMENT_PORT}/policy/pdp/engine -o /dev/null + fi + sleep 5 + echo "Stopping $SNAME..." + _PID_TO_KILL=$_PID; + echo "$SNAME (pid=${_PID_TO_KILL}) is stopping..." + kill -TERM $_PID_TO_KILL 2> /dev/null + sleep 5 + check_status_of_pid $_PID_TO_KILL + if [ "$_RUNNING" = "1" ]; then + kill -TERM $_PID_TO_KILL + fi + while [ "$_RUNNING" = "1" ]; do + sleep 2 + check_status_of_pid $_PID_TO_KILL + done + remove_pid_file + echo "$SNAME has stopped." + fi + RETVAL=0 +} + +function status() { + if [ -f "${_PIDFILE}" ]; then + _PID=`cat "${_PIDFILE}"` + check_status_of_pid $_PID + else + _STATUS="$SNAME (no pidfile) is NOT running" + _RUNNING=0 + fi + if [[ $_RUNNING = 1 ]]; then + RETVAL=0 + else + RETVAL=1 + fi +} + + +function check_status_of_pid () +{ + if [ -n "$1" ] && kill -0 $1 2>/dev/null ; then + _STATUS="$SNAME (pid $1) is running" + _RUNNING=1 + else + _STATUS="$SNAME (pid $1) is NOT running" + _RUNNING=0 + fi +} + +function remove_pid_file () +{ + if [ -f "${_PIDFILE}" ]; then + rm "${_PIDFILE}" + fi +} + +function update_monitor() { + STATUS=$1 + if [[ -f ${POLICY_HOME}/etc/monitor/monitor.cfg ]]; then + /bin/sed -i.bak \ + -e "s/^${CONTROLLER}=.*/${CONTROLLER}=${STATUS}/g" \ + ${POLICY_HOME}/etc/monitor/monitor.cfg + fi +} + + +# main + +_DIR=${POLICY_HOME} +CONTROLLER=policy-management-controller + +RETVAL=0 + +_PIDFILE=${POLICY_HOME}/PID + +case "$1" in + status) + status + echo "$_STATUS" + ;; + start) + if flock ${cfg} ; then + start + fi {cfg}>>${POLICY_HOME}/etc/monitor/monitor.cfg.lock + ;; + umstart) + um_start + ;; + stop) + if flock ${cfg} ; then + stop + fi {cfg}>>${POLICY_HOME}/etc/monitor/monitor.cfg.lock + ;; + umstop) + um_stop + ;; + restart) + if flock ${cfg} ; then + stop + sleep 2 + start + fi {cfg}>>${POLICY_HOME}/etc/monitor/monitor.cfg.lock + ;; + *) + echo "error: invalid option $@" + echo "Usage: $0 status|start|stop|restart" + RETVAL=1 + ;; +esac + +exit ${RETVAL} diff --git a/policy-management/src/main/server-gen/bin/rest-add-controller.sh b/policy-management/src/main/server-gen/bin/rest-add-controller.sh new file mode 100644 index 00000000..187b2916 --- /dev/null +++ b/policy-management/src/main/server-gen/bin/rest-add-controller.sh @@ -0,0 +1,37 @@ +#! /bin/bash + +### +# ============LICENSE_START======================================================= +# policy-management +# ================================================================================ +# 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========================================================= +### + +source $POLICY_HOME/etc/profile.d/env.sh + +json=$1-controller.rest.json + +if [ -f ${json} ]; then + if [[ -n ${ENGINE_MANAGEMENT_PASSWORD} ]]; then + curl --silent --user ${ENGINE_MANAGEMENT_USER}:${ENGINE_MANAGEMENT_PASSWORD} -X POST --data @${json} --header "Content-Type: application/json" \ + http://localhost:${ENGINE_MANAGEMENT_PORT}/policy/pdp/engine/controllers + else + curl --silent -X POST --data @${json} --header "Content-Type: application/json" \ + http://localhost:${ENGINE_MANAGEMENT_PORT}/policy/pdp/engine/controllers + fi +else + echo "Usage: rest-add-controller.sh closed-loop-sample|reporter|sepc|vsegw|.. (or any other config file ending with *-controller.rest.json)" +fi diff --git a/policy-management/src/main/server-gen/bin/rest-delete-controller.sh b/policy-management/src/main/server-gen/bin/rest-delete-controller.sh new file mode 100644 index 00000000..de1d601c --- /dev/null +++ b/policy-management/src/main/server-gen/bin/rest-delete-controller.sh @@ -0,0 +1,43 @@ +#! /bin/bash + +### +# ============LICENSE_START======================================================= +# policy-management +# ================================================================================ +# 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========================================================= +### + +source $POLICY_HOME/etc/profile.d/env.sh + +if [[ -n $1 ]]; then + if [[ -n ${ENGINE_MANAGEMENT_PASSWORD} ]]; then + curl --silent --user ${ENGINE_MANAGEMENT_USER}:${ENGINE_MANAGEMENT_PASSWORD} -X DELETE --header "Content-Type: application/json" \ + http://localhost:${ENGINE_MANAGEMENT_PORT}/policy/pdp/engine/controllers/${1} + else + curl --silent -X DELETE --header "Content-Type: application/json" \ + http://localhost:${ENGINE_MANAGEMENT_PORT}/policy/pdp/engine/controllers/${1} + fi + echo + exit +fi + + + +cat <<-'EOF' + +Usage: rest-delete-controller.sh closed-loop-sample|reporter|sepc|vsegw|.. (or any other controller idenfied by name) + +EOF diff --git a/policy-management/src/main/server/config/IntegrityMonitor.properties b/policy-management/src/main/server/config/IntegrityMonitor.properties new file mode 100644 index 00000000..1201a9da --- /dev/null +++ b/policy-management/src/main/server/config/IntegrityMonitor.properties @@ -0,0 +1,81 @@ +### +# ============LICENSE_START======================================================= +# policy-management +# ================================================================================ +# 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========================================================= +### + +hostPort = ${{host_port}} + +# The following were added as part of US673632 +# +# Forward Progress Monitor update interval seconds +fp_monitor_interval = ${{fp_monitor_interval}} +# Failed counter threshold before failover +failed_counter_threshold = ${{failed_counter_threshold}} +# Interval between test transactions when no traffic seconds +test_trans_interval = ${{test_trans_interval}} +# Interval between writes of the FPC to the DB seconds +write_fpc_interval = ${{write_fpc_interval}} +# Name of the site in which this node is hosted +site_name = ${{site_name}} +# Node type +# Note: Make sure you don't leave any trailing spaces, or you'll get an 'invalid node type' error! +node_type = pdp_drools +# Dependency groups are groups of resources upon which a node operational state is dependent upon. +# Each group is a comma-separated list of resource names and groups are separated by a semicolon. For example: +dependency_groups=${{dependency_groups}} +# When set to true, dependent health checks are performed by using JMX to invoke test() on the dependent. +# The default false is to use state checks for health. +test_via_jmx=${{test_via_jmx}} +# This is the max number of seconds beyond which a non incrementing FPC is considered a failure +max_fpc_update_interval=${{max_fpc_update_interval}} + +# Needed by DroolsPdpsElectionHandler +pdp.checkInterval=7000 +pdp.updateInterval=10000 +#pdp.timeout=3000 +# Need long timeout, because testTransaction is only run every 10 seconds. +pdp.timeout=15000 +#how long do we wait for the pdp table to populate on initial startup +pdp.initialWait=20000 + +# Known as the PDPID in the droolpdpentity table. +#resource.name=pdp1 +resource.name=${{resource_name}} + +# The amount of this a resource (entity) should sleep between audit executions. +# If not specified, defaults to five seconds. +# -1 turns off audit +# zero forces audit to run continuously +integrity_audit_period_seconds=-1 + +# Properties needed for repository audit +repository.audit.id=${{repositoryID}} +repository.audit.url=${{repositoryUrl}} +repository.audit.username=${{repositoryUsername}} +repository.audit.password=${{repositoryPassword}} + +# Flag to control the execution of the subsystemTest for the Database +db.audit.is.active=false + +# Flag to control the execution of the subsystemTest for the Nexus Maven repository +repository.audit.is.active=false + + + + + diff --git a/policy-management/src/main/server/config/controller.properties.README b/policy-management/src/main/server/config/controller.properties.README new file mode 100644 index 00000000..8421cf40 --- /dev/null +++ b/policy-management/src/main/server/config/controller.properties.README @@ -0,0 +1,153 @@ +# +# *-controller.properties configuration +# +# +# The <controller-name>-controller.properties file define the +# configuration aspects of a give controller at initialization time. +# +# It contains 3 major sections: +# +# 1. CONTROLLER +# 2. DMAAP +# 4. UEB +# 5. DROOLS +# +# 1. CONTROLLER +# +# controller.name: controller unique name identifier. +# +# 2. DMAAP: +# 2.1. DMAAP Sources Information +# 2.1.1. Topics that this controller supports over DMAAP. +# 2.1.1. DMAAP Network Information for each topic. +# 2.1.2. Decoders information for each topic to map network input to +# an object that will be injected into its appropriate drools +# sessions. +# 2.1.3. Filtering information for each decoder, to filter out from +# drools, messages that should not be processed. +# 2.2. DMAAP Sinks Information +# 2.2.1. Topics that this controller supports over DMAAP. +# 2.2.2. DMAAP Network Information for each topic. +# 2.2.3. Encoders information for each topic to map a model object +# to serialize network output that will be send over the +# appropriate DMAAP topic according to its network information. +# +# 2.1 DMAAP Sources +# +# dmaap.source.topics: comma separated list of DMAAP topics source of events. +# dmaap.source.topics.<aTopic>.servers: comma separated list of DMAAP servers to poll for events. +# [optional] dmaap.source.topics.<aTopic>.apiKey=<APIKEY> : api key +# [optional] dmaap.source.topics.<aTopic>.apiSecret=<APISECRET> : api secret +# [optional] dmaap.source.topics.<aTopic>.consumerGroup=<CONSUMER-GROUP> : consumer group +# [optional] dmaap.source.topics.<aTopic>.consumerInstance=<CONSUMER-INSTANCE> : consumer instance +# dmaap.source.topics.<aTopic>.events: comma separated list of classes to which an event can be mapped to, +# where <aTopic> must be declared in dmaap.source.topics +# [optional] dmaap.source.topics.<aTopic>.events.<eventClass>.filter: comma separated list of conditions in the form of +# pairs of "<field-name>=<field-value-regex>" values, where <field-name> identifies a field of the event, and +# <field-value-regex> is a regular expression that that field's value in the event must match +# against each particular instantiation of the event for this controller. Note that multiple +# "<field-name>=<field-value-regex>" are evaluated for acceptance by AND'ing each condition. +# Further, <aTopic> must be declared in dmaap.source.topics, and +# <eventClass> in dmaap.source.topics.<aTopic>.events. +# [optional] dmaap.source.topics.<aTopic>.events.custom.gson: comma separated pair, where the first item +# is a class in the model that contains a gson parser, and the second is the actual gson parser in +# the class. This setting overrides the PDP-D generic framework parsers with an specific model +# provided one +# [optional] dmaap.source.topics.<aTopic>.events.custom.jackson: comma separated pair, where the first item +# is a class in the model that contains a jackson parser, and the second is the actual jackson parser in +# the class. This setting overrides the PDP-D generic framework parsers with an specific model +# provided one +# +# 2.2 DMAAP Sinks +# +# dmaap.sink.topics: comma separated list of DMAAP topics destination of locally produced events. +# dmaap.sink.topics.<aTopic>.servers: comma separated list of DMAAP servers to send events. +# [optional] dmaap.sink.topics.<aTopic>.apiKey=<API-KEY> : api key +# [optional] dmaap.sink.topics.<aTopic>.apiSecret=<API-SECRET> : api secret +# [optional] dmaap.sink.topics.<aTopic>.partitionKey=<PARTITIONKEY> : partition key +# dmaap.sink.topics.<aTopic>.events: comma separated list of classes to which an event can be mapped to, +# where <aTopic> must be declared in dmaap.sink.topics +# [optional] dmaap.sink.topics.<aTopic>.events.custom.gson: comma separated pair, where the first item +# is a class in the model that contains a gson parser, and the second is the actual gson parser in +# the class. This setting overrides the PDP-D generic framework parsers with an specific model +# provided one +# [optional] dmaap.sink.topics.<aTopic>.events.custom.jackson: comma separated pair, where the first item +# is a class in the model that contains a jackson parser, and the second is the actual jackson parser in +# the class. This setting overrides the PDP-D generic framework parsers with an specific model +# provided one +# +# 2. UEB: +# 2.1. UEB Sources Information +# 2.1.1. Topics that this controller supports over UEB. +# 2.1.1. UEB Network Information for each topic. +# 2.1.2. Decoders information for each topic to map network input to +# an object that will be injected into its appropriate drools +# sessions. +# 2.1.3. Filtering information for each decoder, to filter out from +# drools, messages that should not be processed. +# 2.2. UEB Sinks Information +# 2.2.1. Topics that this controller supports over UEB. +# 2.2.2. UEB Network Information for each topic. +# 2.2.3. Encoders information for each topic to map a model object +# to serialize network output that will be send over the +# appropriate UEB topic according to its network information. +# +# +# 2.1 UEB Sources +# +# ueb.source.topics: comma separated list of UEB topics source of events. +# ueb.source.topics.<aTopic>.servers: comma separated list of UEB servers to poll for events. +# [optional] ueb.source.topics.<aTopic>.apiKey=<API-KEY> : api key +# [optional] ueb.source.topics.<aTopic>.apiSecret=<API-SECRET> : api secret +# [optional] ueb.source.topics.<aTopic>.consumerGroup=<CONSUMER-GROUP> : consumer group +# [optional] ueb.source.topics.<aTopic>.consumerInstance=<CONSUMER-INSTANCE> : consumer instance +# ueb.source.topics.<aTopic>.events: comma separated list of classes to which an event can be mapped to, +# where <aTopic> must be declared in ueb.source.topics +# ueb.source.topics.<aTopic>.events.<eventClass>.filter: comma separated list of conditions in the form of +# pairs of "<field-name>=<field-value-regex>" values, where <field-name> identifies a field of the event, and +# <field-value-regex> is a regular expression that that field's value in the event must match +# against each particular instantiation of the event for this controller. Note that multiple +# "<field-name>=<field-value-regex>" are evaluated for acceptance by AND'ing each condition. +# Further, <aTopic> must be declared in ueb.source.topics, and +# <eventClass> in ueb.source.topics.<aTopic>.events +# ueb.source.topics.<aTopic>.events: comma separated list of classes to which an event can be mapped to, +# where <aTopic> must be declared in dmaap.source.topics +# [optional] ueb.source.topics.<aTopic>.events.<eventClass>.filter: comma separated list of conditions in the form of +# pairs of "<field-name>=<field-value-regex>" values, where <field-name> identifies a field of the event, and +# <field-value-regex> is a regular expression that that field's value in the event must match +# against each particular instantiation of the event for this controller. Note that multiple +# "<field-name>=<field-value-regex>" are evaluated for acceptance by AND'ing each condition. +# Further, <aTopic> must be declared in dmaap.source.topics, and +# <eventClass> in dmaap.source.topics.<aTopic>.events. +# [optional] ueb.source.topics.<aTopic>.events.custom.gson: comma separated pair, where the first item +# is a class in the model that contains a gson parser, and the second is the actual gson parser in +# the class. This setting overrides the PDP-D generic framework parsers with an specific model +# provided one +# [optional] ueb.source.topics.<aTopic>.events.custom.jackson: comma separated pair, where the first item +# is a class in the model that contains a jackson parser, and the second is the actual jackson parser in +# the class. This setting overrides the PDP-D generic framework parsers with an specific model +# provided one +# +# 2.1 UEB Sinks +# +# ueb.sink.topics: comma separated list of UEB topics destination of locally produced events. +# ueb.sink.topics.<aTopic>.servers: comma separated list of UEB servers to send events. +# [optional] ueb.sink.topics.<aTopic>.apiKey=<APIKEY> : api key +# [optional] ueb.sink.topics.<aTopic>.apiSecret=<APISECRET> : api secret +# [optional] ueb.sink.topics.<aTopic>.partitionKey=<PARTITIONKEY> : partition key +# ueb.sink.topics.<aTopic>.events: comma separated list of classes to which an event can be mapped to, +# where <aTopic> must be declared in ueb.sink.topics +# [optional] ueb.sink.topics.<aTopic>.events.custom.gson: comma separated pair, where the first item +# is a class in the model that contains a gson parser, and the second is the actual gson parser in +# the class. This setting overrides the PDP-D generic framework parsers with an specific model +# provided one +# [optional] ueb.sink.topics.<aTopic>.events.custom.jackson: comma separated pair, where the first item +# is a class in the model that contains a jackson parser, and the second is the actual jackson parser in +# the class. This setting overrides the PDP-D generic framework parsers with an specific model +# provided one +# +# 3. DROOLS (Maven Group Coordinates): +# +# rules.groupId: maven group id of rules jar file +# rules.artifactId: maven artifact id of rules jar file +# rules.version: comma separated list of versions supported and detected that include the drl. diff --git a/policy-management/src/main/server/config/droolsPersistence.properties b/policy-management/src/main/server/config/droolsPersistence.properties new file mode 100644 index 00000000..60793cdc --- /dev/null +++ b/policy-management/src/main/server/config/droolsPersistence.properties @@ -0,0 +1,51 @@ +### +# ============LICENSE_START======================================================= +# policy-management +# ================================================================================ +# 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========================================================= +### + +#javax.persistence.jdbc.driver = org.h2.Driver +#javax.persistence.jdbc.url = jdbc:h2:file:./sql/drools +#javax.persistence.jdbc.user = sa +#javax.persistence.jdbc.password = + +#javax.persistence.jdbc.driver=org.mariadb.jdbc.Driver +#javax.persistence.jdbc.url=jdbc:mariadb://localhost:3306/drools +#javax.persistence.jdbc.user=root +#javax.persistence.jdbc.password=policy + +javax.persistence.jdbc.driver = ${{JDBC_DRIVER}} +javax.persistence.jdbc.url = ${{JDBC_DROOLS_URL}} +javax.persistence.jdbc.user = ${{JDBC_USER}} +javax.persistence.jdbc.password = ${{JDBC_PASSWORD}} + +# Needed? +#javax.persistence.jdbc.driver = org.h2.Driver +#javax.persistence.jdbc.url = jdbc:h2:file:./sql/ncomp +#javax.persistence.jdbc.user = sa +#javax.persistence.jdbc.password = +#persistenceDisabled=false +#javax.persistence.jdbc.driver=org.mariadb.jdbc.Driver +#javax.persistence.jdbc.url=jdbc:mariadb://192.168.56.30:3306/drools +#javax.persistence.jdbc.user=patb +#javax.persistence.jdbc.password=policy + +hibernate.dataSource=org.mariadb.jdbc.MySQLDataSource + +# For testing purposes, it may be convenient to disable persistence +persistenceDisabled=false + diff --git a/policy-management/src/main/server/config/log4j.properties b/policy-management/src/main/server/config/log4j.properties new file mode 100644 index 00000000..6ad25643 --- /dev/null +++ b/policy-management/src/main/server/config/log4j.properties @@ -0,0 +1,48 @@ +### +# ============LICENSE_START======================================================= +# policy-management +# ================================================================================ +# 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========================================================= +### + +log4j.rootLogger=INFO,stdout + +log4j.logger.org.apache.http.headers=INFO,stdout +log4j.logger.org.apache.http.wire=INFO,stdout +log4j.logger.networkLogger=INFO,network + +log4j.additivity.networkLogger=false + +log4j.appender.stdout=org.apache.log4j.RollingFileAppender +log4j.appender.stdout.layout=org.apache.log4j.PatternLayout +log4j.appender.stdout.layout.ConversionPattern=%d %5p [%t] %m %C:%L%n + +log4j.appender.network=org.apache.log4j.RollingFileAppender +log4j.appender.network.File=logs/network.log +log4j.appender.network.layout=org.apache.log4j.PatternLayout +log4j.appender.network.layout.ConversionPattern=[%d|%t]%m%n%n +log4j.appender.network.MaxFileSize=50MB +log4j.appender.network.MaxBackupIndex=4 + +log4j.logger.debugLogger=INFO,debug +log4j.additivity.debugLogger=false +log4j.appender.debug=org.apache.log4j.RollingFileAppender +log4j.appender.debug.File=logs/debug.log +log4j.appender.debug.layout=org.apache.log4j.PatternLayout +log4j.appender.debug.layout.ConversionPattern=[%d|%t]%m%n%n +log4j.appender.debug.MaxFileSize=50MB +log4j.appender.debug.MaxBackupIndex=4 + diff --git a/policy-management/src/main/server/config/logback.xml b/policy-management/src/main/server/config/logback.xml new file mode 100644 index 00000000..545b6f48 --- /dev/null +++ b/policy-management/src/main/server/config/logback.xml @@ -0,0 +1,211 @@ +<!-- + ============LICENSE_START======================================================= + policy-management + ================================================================================ + 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========================================================= + --> + +<configuration scan="true" scanPeriod="3 seconds" debug="true"> + <!--<jmxConfigurator /> --> + <!-- directory path for all other type logs --> + <property name="logDir" value="logs" /> + + <!-- directory path for debugging type logs --> + <property name="debugDir" value="debug-logs" /> + + <!-- specify the component name + <ECOMP-component-name>::= "MSO" | "DCAE" | "ASDC " | "AAI" |"Policy" | "SDNC" | "AC" --> + <property name="componentName" value="Policy"></property> + + <!-- log file names --> + <property name="errorLogName" value="error" /> + <property name="metricsLogName" value="metrics" /> + <property name="auditLogName" value="audit" /> + <property name="debugLogName" value="debug" /> + <!-- modified time stamp format --> + <property name="defaultPattern" value="%X{BeginTimestamp}|%X{EndTimestamp}|%X{RequestId}|%X{ServiceInstanceId}|%thread|%X{ServerName}|%X{ServiceName}|%X{PartnerName}|%X{TargetEntity}|%X{TargetServiceName}|%X{StatusCode}|%X{ResponseCode}|%X{ResponseDescription}|%X{InstanceUUID}|%.-5level|%X{AlertSeverity}|%X{ServerIPAddress}|%X{ElapsedTime}|%X{ServerFQDN}|%X{RemoteHost}|%X{ClassName}||%X{ProcessKey}|%X{TargetVirtualEntity}|%X{CustomField1}|%X{CustomField2}|%X{CustomField3}|%X{CustomField4}|%msg%n" /> + <property name="defaultMetricPattern" value="%X{BeginTimestamp}|%X{EndTimestamp}|%X{RequestId}|%X{ServiceInstanceId}|%thread|%X{ServerName}|%X{ServiceName}|%X{PartnerName}|%X{TargetEntity}|%X{TargetServiceName}|%X{StatusCode}|%X{ResponseCode}|%X{ResponseDescription}|%X{InstanceUUID}|%.-5level|%X{AlertSeverity}|%X{ServerIPAddress}|%X{ElapsedTime}|%X{ServerFQDN}|%X{RemoteHost}|%X{ClassName}||%X{ProcessKey}|%X{TargetVirtualEntity}|%X{CustomField1}|%X{CustomField2}|%X{CustomField3}|%X{CustomField4}|%msg%n" /> + <property name="defaultAuditPattern" value="%X{BeginTimestamp}|%X{EndTimestamp}|%X{RequestId}|%X{ServiceInstanceId}|%thread|%X{ServerName}|%X{ServiceName}|%X{PartnerName}|%X{StatusCode}|%X{ResponseCode}|%X{ResponseDescription}|%X{InstanceUUID}|%.-5level|%X{AlertSeverity}|%X{ServerIPAddress}|%X{ElapsedTime}|%X{ServerFQDN}|%X{RemoteHost}|%X{ClassName}||%X{ProcessKey}|%X{TargetVirtualEntity}|%X{CustomField1}|%X{CustomField2}|%X{CustomField3}|%X{CustomField4}|%msg%n" /> + <property name="defaultErrorPattern" value="%d{yyyy-MM-dd'T'HH:mm:ss.SSS+00:00, UTC}|%X{RequestId}|%thread|%X{ServiceName}|%X{PartnerName}|%X{TargetEntity}|%X{TargetServiceName}|%X{ErrorCategory}|%X{ErrorCode}|%X{ErrorDesciption}|%msg%n" /> + + <property name="defaultPatternOld" value="%d{MM/dd-HH:mm:ss.SSS}|%logger|%X{RequestId}|%X{ServiceInstanceId}|%thread|%X{ServiceName}|%X{InstanceUUID}|%.-5level|%X{AlertSeverity}|%X{ServerIPAddress}|%X{ServerFQDN}|%X{RemoteHost}|%X{ClassName}|%X{Timer}|%msg%n" /> + + <property name="debugLoggerPattern" value="%d{yyyy-MM-dd'T'HH:mm:ss.SSS+00:00, UTC}|%X{RequestId}|%X{ClassName}|%msg%n" /> +<!-- <property name="debugLoggerPattern" value="%X{BeginTimestamp}|%X{EndTimestamp}|%X{RequestId}|%X{ServiceInstanceId}|%thread|%X{ServerName}|%X{ServiceName}|%X{PartnerName}|%X{StatusCode}|%X{ResponseCode}|%X{ResponseDescription}|%X{ServiceName}|%X{InstanceUUID}|%.-5level|%X{AlertSeverity}|%X{ServerIPAddress}|%X{ElapsedTime}|%X{ServerFQDN}|%X{RemoteHost}|%X{ClassName}||%X{ProcessKey}|%X{CustomField1}|%X{CustomField2}|%X{CustomField3}|%X{CustomField4}|%msg%n" /> --> + + <property name="debugLoggerPatternOld" value="%d{MM/dd-HH:mm:ss.SSS}|%X{RequestId}|%X{ServiceInstanceId}|%thread|%X{ServiceName}|%X{InstanceUUID}|%.-5level|%X{AlertSeverity}|%X{ServerIPAddress}|%X{ServerFQDN}|%X{RemoteHost}|%X{Timer}|[%caller{3}]|%msg%n" /> + + <property name="logDirectory" value="${logDir}/${componentName}" /> + <property name="debugLogDirectory" value="${logDir}/${componentName}" /> + + + <!-- Example evaluator filter applied against console appender --> + <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> + <encoder> + <pattern>${defaultPattern}</pattern> + </encoder> + </appender> + + <!-- ============================================================================ --> + <!-- EELF Appenders --> + <!-- ============================================================================ --> + + <!-- The EELFAppender is used to record events to the general application + log --> + + + + + <!-- EELF Audit Appender. This appender is used to record audit engine + related logging events. The audit logger and appender are specializations + of the EELF application root logger and appender. This can be used to segregate + Policy engine events from other components, or it can be eliminated to record + these events as part of the application root log. --> + + <appender name="EELFAudit" + class="ch.qos.logback.core.rolling.RollingFileAppender"> + <file>${logDirectory}/${auditLogName}.log</file> + <rollingPolicy + class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy"> + <fileNamePattern>${logDirectory}/${auditLogName}.%i.log.zip + </fileNamePattern> + <minIndex>1</minIndex> + <maxIndex>9</maxIndex> + </rollingPolicy> + <triggeringPolicy + class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy"> + <maxFileSize>5MB</maxFileSize> + </triggeringPolicy> + <encoder> + <pattern>${defaultAuditPattern}</pattern> + </encoder> + </appender> + <appender name="asyncEELFAudit" class="ch.qos.logback.classic.AsyncAppender"> + <queueSize>256</queueSize> + <appender-ref ref="EELFAudit" /> + </appender> + +<appender name="EELFMetrics" + class="ch.qos.logback.core.rolling.RollingFileAppender"> + <file>${logDirectory}/${metricsLogName}.log</file> + <rollingPolicy + class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy"> + <fileNamePattern>${logDirectory}/${metricsLogName}.%i.log.zip + </fileNamePattern> + <minIndex>1</minIndex> + <maxIndex>9</maxIndex> + </rollingPolicy> + <triggeringPolicy + class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy"> + <maxFileSize>5MB</maxFileSize> + </triggeringPolicy> + <encoder> + <!-- <pattern>"%d{HH:mm:ss.SSS} [%thread] %-5level %logger{1024} - + %msg%n"</pattern> --> + <pattern>${defaultMetricPattern}</pattern> + </encoder> + </appender> + + + <appender name="asyncEELFMetrics" class="ch.qos.logback.classic.AsyncAppender"> + <queueSize>256</queueSize> + <appender-ref ref="EELFMetrics"/> + </appender> + + <appender name="EELFError" + class="ch.qos.logback.core.rolling.RollingFileAppender"> + <file>${logDirectory}/${errorLogName}.log</file> + <rollingPolicy + class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy"> + <fileNamePattern>${logDirectory}/${errorLogName}.%i.log.zip + </fileNamePattern> + <minIndex>1</minIndex> + <maxIndex>9</maxIndex> + </rollingPolicy> + <filter class="ch.qos.logback.classic.filter.ThresholdFilter"> + <level>ERROR</level> + </filter> + <triggeringPolicy + class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy"> + <maxFileSize>5MB</maxFileSize> + </triggeringPolicy> + <encoder> + <pattern>${defaultErrorPattern}</pattern> + </encoder> + </appender> + + <appender name="asyncEELFError" class="ch.qos.logback.classic.AsyncAppender"> + <queueSize>256</queueSize> + <appender-ref ref="EELFError"/> + </appender> + + <appender name="EELFDebug" + class="ch.qos.logback.core.rolling.RollingFileAppender"> + <file>${debugLogDirectory}/${debugLogName}.log</file> + <rollingPolicy + class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy"> + <fileNamePattern>${debugLogDirectory}/${debugLogName}.%i.log.zip + </fileNamePattern> + <minIndex>1</minIndex> + <maxIndex>9</maxIndex> + </rollingPolicy> + <filter class="ch.qos.logback.classic.filter.ThresholdFilter"> + <level>INFO</level> + </filter> + <triggeringPolicy + class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy"> + <maxFileSize>5MB</maxFileSize> + </triggeringPolicy> + <encoder> + <pattern>${debugLoggerPattern}</pattern> + </encoder> + </appender> + + <appender name="asyncEELFDebug" class="ch.qos.logback.classic.AsyncAppender"> + <queueSize>256</queueSize> + <appender-ref ref="EELFDebug" /> + <includeCallerData>true</includeCallerData> + </appender> + + + <!-- ============================================================================ --> + <!-- EELF loggers --> + <!-- ============================================================================ --> + + <logger name="com.att.eelf.audit" level="info" additivity="false"> + <appender-ref ref="asyncEELFAudit" /> + </logger> + + <logger name="com.att.eelf.metrics" level="info" additivity="false"> + <appender-ref ref="asyncEELFMetrics" /> + </logger> + + <logger name="com.att.eelf.error" level="error" additivity="false"> + <appender-ref ref="asyncEELFError" /> + </logger> + + <logger name="com.att.eelf.debug" level="info" additivity="false"> + <appender-ref ref="asyncEELFDebug" /> + </logger> + + + + <root level="INFO"> + <appender-ref ref="asyncEELFDebug" /> + <appender-ref ref="asyncEELFError" /> + </root> + +</configuration> diff --git a/policy-management/src/main/server/config/makefile b/policy-management/src/main/server/config/makefile new file mode 100644 index 00000000..5a96c541 --- /dev/null +++ b/policy-management/src/main/server/config/makefile @@ -0,0 +1,9 @@ + +restart: stop start + +start: + bin/policy-management-controller start +stop: + bin/policy-management-controller stop +console: + bin/policy-management-controller console diff --git a/policy-management/src/main/server/config/policy-engine.properties b/policy-management/src/main/server/config/policy-engine.properties new file mode 100644 index 00000000..647f7367 --- /dev/null +++ b/policy-management/src/main/server/config/policy-engine.properties @@ -0,0 +1,46 @@ +### +# ============LICENSE_START======================================================= +# policy-management +# ================================================================================ +# 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========================================================= +### + +# Policy Engine Configuration + +# Configuration Channel Settings: PDPD_CONFIGURATION + +ueb.source.topics=${{PDPD_CONFIGURATION_TOPIC}} +ueb.source.topics.${{PDPD_CONFIGURATION_TOPIC}}.servers=${{PDPD_CONFIGURATION_SERVERS}} +ueb.source.topics.${{PDPD_CONFIGURATION_TOPIC}}.apiKey=${{PDPD_CONFIGURATION_API_KEY}} +ueb.source.topics.${{PDPD_CONFIGURATION_TOPIC}}.apiSecret=${{PDPD_CONFIGURATION_API_SECRET}} +ueb.source.topics.${{PDPD_CONFIGURATION_TOPIC}}.consumerGroup=${{PDPD_CONFIGURATION_CONSUMER_GROUP}} +ueb.source.topics.${{PDPD_CONFIGURATION_TOPIC}}.consumerInstance=${{PDPD_CONFIGURATION_CONSUMER_INSTANCE}} +ueb.source.topics.${{PDPD_CONFIGURATION_TOPIC}}.managed=false + +ueb.sink.topics=${{PDPD_CONFIGURATION_TOPIC}} +ueb.sink.topics.${{PDPD_CONFIGURATION_TOPIC}}.servers=${{PDPD_CONFIGURATION_SERVERS}} +ueb.sink.topics.${{PDPD_CONFIGURATION_TOPIC}}.apiKey=${{PDPD_CONFIGURATION_API_KEY}} +ueb.sink.topics.${{PDPD_CONFIGURATION_TOPIC}}.apiSecret=${{PDPD_CONFIGURATION_API_SECRET}} +ueb.sink.topics.${{PDPD_CONFIGURATION_TOPIC}}.partitionKey=${{PDPD_CONFIGURATION_PARTITION_KEY}} +ueb.sink.topics.${{PDPD_CONFIGURATION_TOPIC}}.managed=false + +http.server.services=CONFIG +http.server.services.CONFIG.host=${{ENGINE_MANAGEMENT_HOST}} +http.server.services.CONFIG.port=${{ENGINE_MANAGEMENT_PORT}} +http.server.services.CONFIG.userName=${{ENGINE_MANAGEMENT_USER}} +http.server.services.CONFIG.password=${{ENGINE_MANAGEMENT_PASSWORD}} +http.server.services.CONFIG.restPackages=org.openecomp.policy.drools.server.restful +http.server.services.CONFIG.managed=false diff --git a/policy-management/src/main/server/config/policy-healthcheck.properties b/policy-management/src/main/server/config/policy-healthcheck.properties new file mode 100644 index 00000000..51da7ece --- /dev/null +++ b/policy-management/src/main/server/config/policy-healthcheck.properties @@ -0,0 +1,23 @@ +http.server.services=HEALTHCHECK +http.server.services.HEALTHCHECK.host=0.0.0.0 +http.server.services.HEALTHCHECK.port=6969 +http.server.services.HEALTHCHECK.restClasses=org.openecomp.policy.drools.healthcheck.RestHealthCheck +http.server.services.HEALTHCHECK.managed=false + +http.client.services=PAP,PDP + +http.client.services.PAP.host=${{PAP_HOST}} +http.client.services.PAP.port=9091 +http.client.services.PAP.contextUriPath=pap/test +http.client.services.PAP.https=false +http.client.services.PAP.userName=${{PAP_USERNAME}} +http.client.services.PAP.password=${{PAP_PASSWORD}} +http.client.services.PAP.managed=true + +http.client.services.PDP.host=${{PDP_HOST}} +http.client.services.PDP.port=8081 +http.client.services.PDP.contextUriPath=pdp/test +http.client.services.PDP.https=false +http.client.services.PDP.userName=${{PDP_USERNAME}} +http.client.services.PDP.password=${{PDP_PASSWORD}} +http.client.services.PDP.managed=false diff --git a/policy-management/src/main/server/config/policyLogger.properties b/policy-management/src/main/server/config/policyLogger.properties new file mode 100644 index 00000000..4a977992 --- /dev/null +++ b/policy-management/src/main/server/config/policyLogger.properties @@ -0,0 +1,49 @@ +### +# ============LICENSE_START======================================================= +# policy-management +# ================================================================================ +# 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========================================================= +### + +################################### Set concurrentHashMap and timer info ####################### +#Timer initial delay and the delay between in milliseconds before task is to be execute. +timer.delay.time=1000 +#Timer scheduleAtFixedRate period - time in milliseconds between successive task executions. +check.interval= 30000 +#Longest time an event info can be stored in the concurrentHashMap for logging - in seconds. +event.expired.time=86400 +#Size of the concurrentHashMap which stores the event starting time, etc - when its size reaches this limit, the Timer gets executed +#to remove all expired records from this concurrentHashMap. +concurrentHashMap.limit=5000 +#Size of the concurrentHashMap - when its size drops to this point, stop the Timer +stop.check.point=2500 +################################### Set logging format ############################################# +# set EELF for EELF logging format, set LOG4J for using log4j, set SYSTEMOUT for using system.out.println +logger.type=EELF +#################################### Set level for EELF or SYSTEMOUT logging ################################## +# Set level for debug file. Set DEBUG to enable .info, .warn and .debug; set INFO for enable .info and .warn; set OFF to disable all +# Set override flag. Set TRUE for override the level setups in logback.xml. Set FALSE for using the level setups of logback.xml +override.logback.level.setup=FALSE +debugLogger.level=INFO +# Set level for metrics file. Set OFF to disable; set ON to enable +metricsLogger.level=ON +# Set level for error file. Set OFF to disable; set ON to enable +error.level=ON +# Set level for audit file. Set OFF to disable; set ON to enable +audit.level=ON +#################################### Set Policy Component ################################## +# Set DROOLS for drools PDP. Set XACML to xacml PDP +policy.component=DROOLS diff --git a/policy-management/src/main/server/config/system.properties b/policy-management/src/main/server/config/system.properties new file mode 100644 index 00000000..feffbd00 --- /dev/null +++ b/policy-management/src/main/server/config/system.properties @@ -0,0 +1,31 @@ +### +# ============LICENSE_START======================================================= +# policy-management +# ================================================================================ +# 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========================================================= +### + +# system properties passed to controller + +# start JMX server port +com.sun.management.jmxremote.port = 9991 +com.sun.management.jmxremote.authenticate = false +com.sun.management.jmxremote.ssl = false + +javax.net.ssl.keyStore=/opt/app/policy/etc/ssl/policy-keystore +javax.net.ssl.keyStorePassword = ${{KEYSTORE_PASSWD}} +javax.net.ssl.trustStore=/opt/app/policy/etc/ssl/policy-keystore +javax.net.ssl.trustStorePassword = ${{KEYSTORE_PASSWD}} diff --git a/policy-management/src/main/server/config/xacmlPersistence.properties b/policy-management/src/main/server/config/xacmlPersistence.properties new file mode 100644 index 00000000..e88d8aaf --- /dev/null +++ b/policy-management/src/main/server/config/xacmlPersistence.properties @@ -0,0 +1,43 @@ +### +# ============LICENSE_START======================================================= +# policy-management +# ================================================================================ +# 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========================================================= +### + +#javax.persistence.jdbc.driver = org.h2.Driver +#javax.persistence.jdbc.url = jdbc:h2:file:./sql/xacml +#javax.persistence.jdbc.user = sa +#javax.persistence.jdbc.password = + +#javax.persistence.jdbc.driver=org.mariadb.jdbc.Driver +#javax.persistence.jdbc.url=jdbc:mariadb://127.0.0.1:3306/xacml +#javax.persistence.jdbc.user=root +#javax.persistence.jdbc.password=policy + +javax.persistence.jdbc.driver = ${{JDBC_DRIVER}} +javax.persistence.jdbc.url = ${{JDBC_URL}} +javax.persistence.jdbc.user = ${{JDBC_USER}} +javax.persistence.jdbc.password = ${{JDBC_PASSWORD}} + +# Needed? +hibernate.dataSource=org.mariadb.jdbc.MySQLDataSource + +# For testing purposes, it may be convenient to disable persistence +persistenceDisabled=false + + + diff --git a/policy-persistence/config/policy-engine.properties b/policy-persistence/config/policy-engine.properties new file mode 100644 index 00000000..2c50ba9a --- /dev/null +++ b/policy-persistence/config/policy-engine.properties @@ -0,0 +1,33 @@ +### +# ============LICENSE_START======================================================= +# policy-persistence +# ================================================================================ +# 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========================================================= +### + +# Policy Engine Configuration + +# Configuration Channel Settings: PDPD_CONFIGURATION + +ueb.source.topics=PDPD_CONFIGURATION +ueb.source.topics.PDPD_CONFIGURATION.servers= +ueb.source.topics.PDPD_CONFIGURATION.apiKey= +ueb.source.topics.PDPD_CONFIGURATION.apiSecret= + +ueb.sink.topics=PDPD_CONFIGURATION +ueb.sink.topics.PDPD_CONFIGURATION.servers= +ueb.sink.topics.PDPD_CONFIGURATION.apiKey= +ueb.sink.topics.PDPD_CONFIGURATION.apiSecret= diff --git a/policy-persistence/config/policyLogger.properties b/policy-persistence/config/policyLogger.properties new file mode 100644 index 00000000..6ee66fd6 --- /dev/null +++ b/policy-persistence/config/policyLogger.properties @@ -0,0 +1,44 @@ +### +# ============LICENSE_START======================================================= +# policy-persistence +# ================================================================================ +# 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========================================================= +### + +################################### Set concurrentHashMap and timer info ####################### +#Timer initial delay and the delay between in milliseconds before task is to be execute. +timer.delay.time=1000 +#Timer scheduleAtFixedRate period - time in milliseconds between successive task executions. +check.interval= 30000 +#Longest time an event info can be stored in the concurrentHashMap for logging - in seconds. +event.expired.time=86400 +#Size of the concurrentHashMap which stores the event starting time, etc - when its size reaches this limit, the Timer gets executed +#to remove all expired records from this concurrentHashMap. +concurrentHashMap.limit=5000 +#Size of the concurrentHashMap - when its size drops to this point, stop the Timer +stop.check.point=2500 +################################### Set logging format ############################################# +# set EELF for EELF logging format, set LOG4J for using log4j, set SYSTEMOUT for using system.out.println +logger.type=EELF +#################################### Set level for EELF or SYSTEMOUT logging ################################## +# Set level for debug file. Set DEBUG to enable .info, .warn and .debug; set INFO for enable .info and .warn; set OFF to disable all +debugLogger.level=INFO +# Set level for metrics file. Set OFF to disable; set ON to enable +metricsLogger.level=ON +# Set level for error file. Set OFF to disable; set ON to enable +error.level=ON +# Set level for audit file. Set OFF to disable; set ON to enable +audit.level=ON diff --git a/policy-persistence/pom.xml b/policy-persistence/pom.xml new file mode 100644 index 00000000..074a9d44 --- /dev/null +++ b/policy-persistence/pom.xml @@ -0,0 +1,154 @@ +<!-- + ============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/xsd/maven-4.0.0.xsd"> + + <modelVersion>4.0.0</modelVersion> + + <parent> + <groupId>org.openecomp.policy.drools-pdp</groupId> + <artifactId>drools-pdp</artifactId> + <version>1.0.0-SNAPSHOT</version> + </parent> + + <artifactId>policy-persistence</artifactId> + + <name>policy-persistence</name> + <description>Separately loadable module with persistence code</description> + + <properties> + <maven.compiler.source>1.8</maven.compiler.source> + <maven.compiler.target>1.8</maven.compiler.target> + <cambria.version>0.2.4</cambria.version> + <dmaap.version>0.2.9</dmaap.version> + </properties> + + <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>org.openecomp.policy.drools-pdp</groupId> + <artifactId>policy-core</artifactId> + <version>1.0.0-SNAPSHOT</version> + </dependency> + <dependency> + <groupId>org.openecomp.policy.drools-pdp</groupId> + <artifactId>policy-management</artifactId> + <version>1.0.0-SNAPSHOT</version> + </dependency> + </dependencies> + +</project> diff --git a/policy-persistence/src/assembly/assemble_zip.xml b/policy-persistence/src/assembly/assemble_zip.xml new file mode 100644 index 00000000..e0e22f5b --- /dev/null +++ b/policy-persistence/src/assembly/assemble_zip.xml @@ -0,0 +1,85 @@ +<!-- + ============LICENSE_START======================================================= + policy-persistence + ================================================================================ + 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/opt</outputDirectory> + <includes> + <include>policy-persistence-${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-persistence/src/main/java/org/openecomp/policy/drools/core/DbAudit.java b/policy-persistence/src/main/java/org/openecomp/policy/drools/core/DbAudit.java new file mode 100644 index 00000000..51e92aa9 --- /dev/null +++ b/policy-persistence/src/main/java/org/openecomp/policy/drools/core/DbAudit.java @@ -0,0 +1,205 @@ +/*- + * ============LICENSE_START======================================================= + * policy-persistence + * ================================================================================ + * 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.sql.Connection; +import java.sql.DriverManager; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.util.Properties; +import java.util.UUID; + +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.drools.persistence.DroolsPersistenceProperties; + +/** + * This class audits the database + */ +public class DbAudit extends DroolsPDPIntegrityMonitor.AuditBase +{ + // get an instance of logger + private static Logger logger = FlexLogger.getLogger(DbAudit.class); + // single global instance of this audit object + static private DbAudit instance = new DbAudit(); + + // This indicates if 'CREATE TABLE IF NOT EXISTS Audit ...' should be + // invoked -- doing this avoids the need to create the table in advance. + static private boolean createTableNeeded = true; + + /** + * @return the single 'DbAudit' instance + */ + static DroolsPDPIntegrityMonitor.AuditBase getInstance() + { + return(instance); + } + + /** + * Constructor - set the name to 'Database' + */ + private DbAudit() + { + super("Database"); + } + + /** + * Invoke the audit + * + * @param properties properties to be passed to the audit + */ + @Override + public void invoke(Properties droolsPersistenceProperties) + { + logger.info("Running 'DbAudit.invoke'"); + boolean isActive = true; + String dbAuditIsActive = IntegrityMonitorProperties.getProperty("db.audit.is.active"); + logger.debug("DbAudit.invoke: dbAuditIsActive = " + dbAuditIsActive); + + if (dbAuditIsActive != null) { + try { + isActive = Boolean.parseBoolean(dbAuditIsActive.trim()); + } catch (NumberFormatException e) { + logger.warn("DbAudit.invoke: Ignoring invalid property: db.audit.is.active = " + dbAuditIsActive); + } + } + + if(!isActive){ + logger.info("DbAudit.invoke: exiting because isActive = " + isActive); + return; + } + + // fetch DB properties from properties file -- they are already known + // to exist, because they were verified by the 'IntegrityMonitor' + // constructor + String url = droolsPersistenceProperties.getProperty(DroolsPersistenceProperties.DB_URL); + String user = droolsPersistenceProperties.getProperty(DroolsPersistenceProperties.DB_USER); + String password = + droolsPersistenceProperties.getProperty(DroolsPersistenceProperties.DB_PWD); + + // connection to DB + Connection connection = null; + + // supports SQL operations + PreparedStatement statement = null; + ResultSet rs = null; + + // operation phase currently running -- used to construct an error + // message, if needed + String phase = null; + + try + { + // create connection to DB + phase = "creating connection"; + logger.info("DbAudit: Creating connection to " + url); + + connection = DriverManager.getConnection(url, user, password); + + // create audit table, if needed + if (createTableNeeded) + { + phase = "create table"; + logger.info("DbAudit: Creating 'Audit' table, if needed"); + statement = connection.prepareStatement + ("CREATE TABLE IF NOT EXISTS Audit (\n" + + " name varchar(64) DEFAULT NULL,\n" + + " UNIQUE KEY name (name)\n" + + ") DEFAULT CHARSET=latin1;"); + statement.execute(); + createTableNeeded = false; + } + + // insert an entry into the table + phase = "insert entry"; + String key = UUID.randomUUID().toString(); + statement = connection.prepareStatement + ("INSERT INTO Audit (name) VALUES (?)"); + statement.setString(1, key); + statement.executeUpdate(); + + // fetch the entry from the table + phase = "fetch entry"; + statement = connection.prepareStatement + ("SELECT name FROM Audit WHERE name = ?"); + statement.setString(1, key); + rs = statement.executeQuery(); + if (rs.first()) + { + // found entry + logger.info("DbAudit: Found key " + rs.getString(1)); + } + else + { + logger.error + ("DbAudit: can't find newly-created entry with key " + key); + setResponse("Can't find newly-created entry"); + } + + // delete entries from table + phase = "delete entry"; + statement = connection.prepareStatement + ("DELETE FROM Audit WHERE name = ?"); + statement.setString(1, key); + statement.executeUpdate(); + } + catch (Exception e) + { + String message = "DbAudit: Exception during audit, phase = " + phase; + logger.error(MessageCodes.EXCEPTION_ERROR, e, message); + setResponse(message); + } + finally + { + if (rs != null) + { + try + { + rs.close(); + } + catch (Exception e) + { + } + } + if (statement != null) + { + try + { + statement.close(); + } + catch (Exception e) + { + } + } + if (connection != null) + { + try + { + connection.close(); + } + catch (Exception e) + { + } + } + } + } +} diff --git a/policy-persistence/src/main/java/org/openecomp/policy/drools/core/DroolsPDPIntegrityMonitor.java b/policy-persistence/src/main/java/org/openecomp/policy/drools/core/DroolsPDPIntegrityMonitor.java new file mode 100644 index 00000000..2b6058fd --- /dev/null +++ b/policy-persistence/src/main/java/org/openecomp/policy/drools/core/DroolsPDPIntegrityMonitor.java @@ -0,0 +1,485 @@ +/*- + * ============LICENSE_START======================================================= + * policy-persistence + * ================================================================================ + * 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.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.net.InetSocketAddress; +import java.util.LinkedList; +import java.util.Properties; +import java.util.concurrent.Callable; + +import org.openecomp.policy.common.im.IntegrityMonitor; +import org.openecomp.policy.common.logging.flexlogger.PropertyUtil; +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.drools.persistence.DroolsPdpsElectionHandler; +import org.openecomp.policy.drools.persistence.XacmlPersistenceProperties; +import com.sun.net.httpserver.HttpExchange; +import com.sun.net.httpserver.HttpHandler; +import com.sun.net.httpserver.HttpServer; + +/** + * This class extends 'IntegrityMonitor' for use in the 'Drools PDP' + * virtual machine. The included audits are 'Database' and 'Repository'. + */ +public class DroolsPDPIntegrityMonitor extends IntegrityMonitor +{ + + // get an instance of logger + private static Logger logger = FlexLogger.getLogger(DroolsPDPIntegrityMonitor.class); + + // static global instance + static private DroolsPDPIntegrityMonitor im = null; + + // list of audits to run + static private AuditBase[] audits = + new AuditBase[]{DbAudit.getInstance(), RepositoryAudit.getInstance()}; + + // save initialization properties + private Properties droolsPersistenceProperties = null; + + /** + * Static initialization -- create Drools Integrity Monitor, and + * an HTTP server to handle REST 'test' requests + */ + static public DroolsPDPIntegrityMonitor init(String configDir) throws Exception + { + + logger.info("init: Entering and invoking PropertyUtil.getProperties() on '" + + configDir + "'"); + + // read in properties + Properties integrityMonitorProperties = + PropertyUtil.getProperties(configDir + "/IntegrityMonitor.properties"); + Properties droolsPersistenceProperties = + PropertyUtil.getProperties(configDir + "/droolsPersistence.properties"); + Properties xacmlPersistenceProperties = + PropertyUtil.getProperties(configDir + "/xacmlPersistence.properties"); + + // fetch and verify definitions of some properties + // (the 'IntegrityMonitor' constructor does some additional verification) + String resourceName = integrityMonitorProperties.getProperty("resource.name"); + String hostPort = integrityMonitorProperties.getProperty("hostPort"); + String fpMonitorInterval = integrityMonitorProperties.getProperty("fp_monitor_interval"); + String failedCounterThreshold = integrityMonitorProperties.getProperty("failed_counter_threshold"); + String testTransInterval = integrityMonitorProperties.getProperty("test_trans_interval"); + String writeFpcInterval = integrityMonitorProperties.getProperty("write_fpc_interval"); + String siteName = integrityMonitorProperties.getProperty("site_name"); + String nodeType = integrityMonitorProperties.getProperty("node_type"); + String dependencyGroups = integrityMonitorProperties.getProperty("dependency_groups"); + String droolsJavaxPersistenceJdbcDriver = droolsPersistenceProperties.getProperty("javax.persistence.jdbc.driver"); + String droolsJavaxPersistenceJdbcUrl = droolsPersistenceProperties.getProperty("javax.persistence.jdbc.url"); + String droolsJavaxPersistenceJdbcUser = droolsPersistenceProperties.getProperty("javax.persistence.jdbc.user"); + String droolsJavaxPersistenceJdbcPassword = droolsPersistenceProperties.getProperty("javax.persistence.jdbc.password"); + String xacmlJavaxPersistenceJdbcDriver = xacmlPersistenceProperties.getProperty("javax.persistence.jdbc.driver"); + String xacmlJavaxPersistenceJdbcUrl = xacmlPersistenceProperties.getProperty("javax.persistence.jdbc.url"); + String xacmlJavaxPersistenceJdbcUser = xacmlPersistenceProperties.getProperty("javax.persistence.jdbc.user"); + String xacmlJavaxPersistenceJdbcPassword = xacmlPersistenceProperties.getProperty("javax.persistence.jdbc.password"); + + if (resourceName == null) + { + logger.error("init: Missing IntegrityMonitor property: 'resource.name'"); + throw(new Exception + ("Missing IntegrityMonitor property: 'resource.name'")); + } + if (hostPort == null) + { + logger.error("init: Missing IntegrityMonitor property: 'hostPort'"); + throw(new Exception + ("Missing IntegrityMonitor property: 'hostPort'")); + } + if (fpMonitorInterval == null) + { + logger.error("init: Missing IntegrityMonitor property: 'fp_monitor_interval'"); + throw(new Exception + ("Missing IntegrityMonitor property: 'fp_monitor_interval'")); + } + if (failedCounterThreshold == null) + { + logger.error("init: Missing IntegrityMonitor property: 'failed_counter_threshold'"); + throw(new Exception + ("Missing IntegrityMonitor property: 'failed_counter_threshold'")); + } + if (testTransInterval == null) + { + logger.error("init: Missing IntegrityMonitor property: 'test_trans_interval'"); + throw(new Exception + ("Missing IntegrityMonitor property: 'test_trans_interval'")); + } + if (writeFpcInterval == null) + { + logger.error("init: Missing IntegrityMonitor property: 'write_fpc_interval'"); + throw(new Exception + ("Missing IntegrityMonitor property: 'write_fpc_interval'")); + } + if (siteName == null) + { + logger.error("init: Missing IntegrityMonitor property: 'site_name'"); + throw(new Exception + ("Missing IntegrityMonitor property: 'site_name'")); + } + if (nodeType == null) + { + logger.error("init: Missing IntegrityMonitor property: 'node_type'"); + throw(new Exception + ("Missing IntegrityMonitor property: 'node_type'")); + } + if (dependencyGroups == null) + { + logger.error("init: Missing IntegrityMonitor property: 'dependency_groups'"); + throw(new Exception + ("Missing IntegrityMonitor property: 'dependency_groups'")); + } + if (droolsJavaxPersistenceJdbcDriver == null) + { + logger.error("init: Missing IntegrityMonitor property: 'javax.persistence.jbdc.driver for drools DB'"); + throw(new Exception + ("Missing IntegrityMonitor property: 'javax.persistence.jbdc.driver for drools DB'")); + } + if (droolsJavaxPersistenceJdbcUrl == null) + { + logger.error("init: Missing IntegrityMonitor property: 'javax.persistence.jbdc.url for drools DB'"); + throw(new Exception + ("Missing IntegrityMonitor property: 'javax.persistence.jbdc.url for drools DB'")); + } + if (droolsJavaxPersistenceJdbcUser == null) + { + logger.error("init: Missing IntegrityMonitor property: 'javax.persistence.jbdc.user for drools DB'"); + throw(new Exception + ("Missing IntegrityMonitor property: 'javax.persistence.jbdc.user for drools DB'")); + } + if (droolsJavaxPersistenceJdbcPassword == null) + { + logger.error("init: Missing IntegrityMonitor property: 'javax.persistence.jbdc.password for drools DB'"); + throw(new Exception + ("Missing IntegrityMonitor property: 'javax.persistence.jbdc.password for drools DB'")); + } + if (xacmlJavaxPersistenceJdbcDriver == null) + { + logger.error("init: Missing IntegrityMonitor property: 'javax.persistence.jbdc.driver for xacml DB'"); + throw(new Exception + ("Missing IntegrityMonitor property: 'javax.persistence.jbdc.driver for xacml DB'")); + } + if (xacmlJavaxPersistenceJdbcUrl == null) + { + logger.error("init: Missing IntegrityMonitor property: 'javax.persistence.jbdc.url for xacml DB'"); + throw(new Exception + ("Missing IntegrityMonitor property: 'javax.persistence.jbdc.url for xacml DB'")); + } + if (xacmlJavaxPersistenceJdbcUser == null) + { + logger.error("init: Missing IntegrityMonitor property: 'javax.persistence.jbdc.user for xacml DB'"); + throw(new Exception + ("Missing IntegrityMonitor property: 'javax.persistence.jbdc.user for xacml DB'")); + } + if (xacmlJavaxPersistenceJdbcPassword == null) + { + logger.error("init: Missing IntegrityMonitor property: 'javax.persistence.jbdc.password for xacml DB'"); + throw(new Exception + ("Missing IntegrityMonitor property: 'javax.persistence.jbdc.password' for xacml DB'")); + } + + logger.info("init: loading consolidatedProperties"); + Properties consolidatedProperties = new Properties(); + consolidatedProperties.load(new FileInputStream(new File(configDir + "/IntegrityMonitor.properties"))); + consolidatedProperties.load(new FileInputStream(new File(configDir + "/xacmlPersistence.properties"))); + // verify that consolidatedProperties has properties from both properties files. + logger.info("init: PDP_INSTANCE_ID=" + consolidatedProperties.getProperty(IntegrityMonitorProperties.PDP_INSTANCE_ID)); + logger.info("init: DB_URL=" + consolidatedProperties.getProperty(XacmlPersistenceProperties.DB_URL)); + + // Now that we've validated the properties, create Drools Integrity Monitor + // with these properties. + im = new DroolsPDPIntegrityMonitor(resourceName, + consolidatedProperties, droolsPersistenceProperties); + logger.info("init: New DroolsPDPIntegrityMonitor instantiated, hostPort=" + hostPort); + + // determine host and port for HTTP server + int index = hostPort.lastIndexOf(':'); + InetSocketAddress addr; + + if (index < 0) + { + addr = new InetSocketAddress(Integer.valueOf(hostPort)); + } + else + { + addr = new InetSocketAddress + (hostPort.substring(0, index), + Integer.valueOf(hostPort.substring(index + 1))); + } + + // create http server + try { + logger.info("init: Starting HTTP server, addr=" + addr); + HttpServer server = HttpServer.create(addr, 0); + server.createContext("/test", new TestHandler()); + server.setExecutor(null); + server.start(); + System.out.println("init: Started server on hostPort=" + hostPort); + } catch (Exception e) { + if (PolicyContainer.isUnitTesting) { + System.out + .println("init: Caught Exception attempting to start server on hostPort=" + + hostPort + ", message=" + e.getMessage()); + } else { + throw e; + } + } + + logger.info("init: Exiting and returning DroolsPDPIntegrityMonitor"); + return im; + } + + /** + * Constructor - pass arguments to superclass, but remember properties + * @param resourceName unique name of this Integrity Monitor + * @param url the JMX URL of the MBean server + * @param properties properties used locally, as well as by + * 'IntegrityMonitor' + * @throws Exception (passed from superclass) + */ + private DroolsPDPIntegrityMonitor(String resourceName, + Properties consolidatedProperties, + Properties droolsPersistenceProperties) throws Exception { + super(resourceName, consolidatedProperties); + this.droolsPersistenceProperties = droolsPersistenceProperties; + } + + /** + * Run tests (audits) unique to Drools PDP VM (Database + Repository) + */ + @Override + public void subsystemTest() throws Exception + { + logger.info("DroolsPDPIntegrityMonitor.subsystemTest called"); + + // clear all responses (non-null values indicate an error) + for (AuditBase audit : audits) + { + audit.setResponse(null); + } + + // invoke all of the audits + for (AuditBase audit : audits) + { + try + { + // invoke the audit (responses are stored within the audit object) + audit.invoke(droolsPersistenceProperties); + } + catch (Exception e) + { + logger.error(MessageCodes.EXCEPTION_ERROR, e, + audit.getName() + " audit error"); + if (audit.getResponse() == null) + { + // if there is no current response, use the exception message + audit.setResponse(e.getMessage()); + } + } + } + + // will contain list of subsystems where the audit failed + String responseMsg = ""; + + // Loop through all of the audits, and see which ones have failed. + // NOTE: response information is stored within the audit objects + // themselves -- only one can run at a time. + for (AuditBase audit : audits) + { + String response = audit.getResponse(); + if (response != null) + { + // the audit has failed -- add subsystem and + // and 'responseValue' with the new information + responseMsg = responseMsg.concat("\n" + audit.getName() + ": " + response); + } + } + + if(!responseMsg.isEmpty()){ + throw new Exception(responseMsg); + } + } + + /* ============================================================ */ + + /** + * This is the base class for audits invoked in 'subsystemTest' + */ + static public abstract class AuditBase + { + // name of the audit + protected String name; + + // non-null indicates the error response + protected String response; + + /** + * Constructor - initialize the name, and clear the initial response + * @param name name of the audit + */ + public AuditBase(String name) + { + this.name = name; + this.response = null; + } + + /** + * @return the name of this audit + */ + public String getName() + { + return(name); + } + + /** + * @return the response String (non-null indicates the error message) + */ + public String getResponse() + { + return(response); + } + + /** + * Set the response string to the specified value + * @param value the new value of the response string (null = no errors) + */ + public void setResponse(String value) + { + response = value; + } + + /** + * Abstract method to invoke the audit + * @param droolsPersistenceProperties Used for DB access + * @throws Exception passed in by the audit + */ + abstract void invoke(Properties droolsPersistenceProperties) throws Exception; + } + + /* ============================================================ */ + + /** + * This class is the HTTP handler for the REST 'test' invocation + */ + static class TestHandler implements HttpHandler + { + /** + * Handle an incoming REST 'test' invocation + * @param ex used to pass incoming and outgoing HTTP information + */ + @Override + public void handle(HttpExchange ex) throws IOException + { + + System.out.println("TestHandler.handle: Entering"); + + // The responses are stored within the audit objects, so we need to + // invoke the audits and get responses before we handle another + // request. + synchronized(TestHandler.class) + { + // will include messages associated with subsystem failures + StringBuilder body = new StringBuilder(); + + // 200=SUCCESS, 500=failure + int responseValue = 200; + + if (im != null) + { + try + { + // call 'IntegrityMonitor.evaluateSanity()' + im.evaluateSanity(); + } + catch (Exception e) + { + // this exception isn't coming from one of the audits, + // because those are caught in 'subsystemTest()' + logger.error + (MessageCodes.EXCEPTION_ERROR, e, + "DroolsPDPIntegrityMonitor.evaluateSanity()"); + + // include exception in HTTP response + body.append("\nException: " + e + "\n"); + responseValue = 500; + } + } +/* + * Audit failures are being logged. A string will be generated which captures the + * the audit failures. This string will be included in an exception coming from im.evaluateSanity(). + * + // will contain list of subsystems where the audit failed + LinkedList<String> subsystems = new LinkedList<String>(); + + // Loop through all of the audits, and see which ones have failed. + // NOTE: response information is stored within the audit objects + // themselves -- only one can run at a time. + for (AuditBase audit : audits) + { + String response = audit.getResponse(); + if (response != null) + { + // the audit has failed -- update 'subsystems', 'body', + // and 'responseValue' with the new information + subsystems.add(audit.getName()); + body + .append('\n') + .append(audit.getName()) + .append(":\n") + .append(response) + .append('\n'); + responseValue = 500; + } + } + + if (subsystems.size() != 0) + { + // there is at least one failure -- add HTTP headers + ex.getResponseHeaders().put("X-ECOMP-SubsystemFailure", + subsystems); + } +*/ + // send response, including the contents of 'body' + // (which is empty if everything is successful) + ex.sendResponseHeaders(responseValue, body.length()); + OutputStream os = ex.getResponseBody(); + os.write(body.toString().getBytes()); + os.close(); + System.out.println("TestHandler.handle: Exiting"); + } + } + } + public static DroolsPDPIntegrityMonitor getInstance() throws Exception{ + logger.info("getInstance() called"); + if (im == null) { + String msg = "No DroolsPDPIntegrityMonitor instance exists." + + " Please use the method DroolsPDPIntegrityMonitor init(String configDir)"; + throw new Exception(msg); + }else{ + return im; + } + } +} diff --git a/policy-persistence/src/main/java/org/openecomp/policy/drools/core/IntegrityMonitorProperties.java b/policy-persistence/src/main/java/org/openecomp/policy/drools/core/IntegrityMonitorProperties.java new file mode 100644 index 00000000..d1b1ad6d --- /dev/null +++ b/policy-persistence/src/main/java/org/openecomp/policy/drools/core/IntegrityMonitorProperties.java @@ -0,0 +1,68 @@ +/*- + * ============LICENSE_START======================================================= + * policy-persistence + * ================================================================================ + * 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.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import org.openecomp.policy.common.logging.flexlogger.FlexLogger; +import org.openecomp.policy.common.logging.flexlogger.Logger; + +public class IntegrityMonitorProperties { + // get an instance of logger + private static Logger logger = FlexLogger.getLogger(IntegrityMonitorProperties.class); + + public static final String PDP_INSTANCE_ID = "resource.name"; + + public static final String PDP_CHECK_INVERVAL = "pdp.checkInterval"; + public static final String PDP_UPDATE_INTERVAL = "pdp.updateInterval"; + public static final String PDP_TIMEOUT = "pdp.timeout"; + public static final String PDP_INITIAL_WAIT_PERIOD = "pdp.initialWait"; + + public static final String SITE_NAME = "site_name"; + + private static Properties properties = null; + /* + * Initialize the parameter values from the droolsPersitence.properties file values + * + * This is designed so that the Properties object is obtained from the droolsPersistence.properties + * file and then is passed to this method to initialize the value of the parameters. + * This allows the flexibility of JUnit tests using getProperties(filename) to get the + * properties while runtime methods can use getPropertiesFromClassPath(filename). + * + */ + public static void initProperties (Properties prop){ + logger.info("IntegrityMonitorProperties.initProperties(Properties): entry"); + logger.info("\n\nIntegrityMonitorProperties.initProperties: Properties = \n" + prop + "\n\n"); + + properties = prop; + } + + public static String getProperty(String key){ + return properties.getProperty(key); + } + + public static Properties getProperties() { + return properties; + } +} diff --git a/policy-persistence/src/main/java/org/openecomp/policy/drools/core/RepositoryAudit.java b/policy-persistence/src/main/java/org/openecomp/policy/drools/core/RepositoryAudit.java new file mode 100644 index 00000000..86c672e2 --- /dev/null +++ b/policy-persistence/src/main/java/org/openecomp/policy/drools/core/RepositoryAudit.java @@ -0,0 +1,524 @@ +/*- + * ============LICENSE_START======================================================= + * policy-persistence + * ================================================================================ + * 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.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.nio.file.attribute.BasicFileAttributes; +import java.nio.file.Files; +import java.nio.file.FileVisitor; +import java.nio.file.FileVisitResult; +import java.nio.file.Path; +import java.nio.file.SimpleFileVisitor; +import java.util.LinkedList; +import java.util.Properties; +import java.util.concurrent.Callable; +import java.util.concurrent.TimeUnit; + +import org.openecomp.policy.common.logging.flexlogger.FlexLogger; +import org.openecomp.policy.common.logging.flexlogger.Logger; + + +/** + * This class audits the Maven repository + */ +public class RepositoryAudit extends DroolsPDPIntegrityMonitor.AuditBase +{ + private static final long DEFAULT_TIMEOUT = 60; // timeout in 60 seconds + + // get an instance of logger + private static Logger logger = FlexLogger.getLogger(RepositoryAudit.class); + // single global instance of this audit object + static private RepositoryAudit instance = new RepositoryAudit(); + + /** + * @return the single 'RepositoryAudit' instance + */ + static DroolsPDPIntegrityMonitor.AuditBase getInstance() + { + return(instance); + } + + /** + * Constructor - set the name to 'Repository' + */ + private RepositoryAudit() + { + super("Repository"); + } + + /** + * Invoke the audit + * + * @param properties properties to be passed to the audit + */ + @Override + public void invoke(Properties properties) + throws IOException, InterruptedException + { + logger.info("Running 'RepositoryAudit.invoke'"); + + boolean isActive = true; + String repoAuditIsActive = IntegrityMonitorProperties.getProperty("repository.audit.is.active"); + logger.debug("RepositoryAudit.invoke: repoAuditIsActive = " + repoAuditIsActive); + + if (repoAuditIsActive != null) { + try { + isActive = Boolean.parseBoolean(repoAuditIsActive.trim()); + } catch (NumberFormatException e) { + logger.warn("RepositoryAudit.invoke: Ignoring invalid property: repository.audit.is.active = " + repoAuditIsActive); + } + } + + if(!isActive){ + logger.info("RepositoryAudit.invoke: exiting because isActive = " + isActive); + return; + } + + // Fetch repository information from 'IntegrityMonitorProperties' + String repositoryId = + IntegrityMonitorProperties.getProperty("repository.audit.id"); + String repositoryUrl = + IntegrityMonitorProperties.getProperty("repository.audit.url"); + String repositoryUsername = + IntegrityMonitorProperties.getProperty("repository.audit.username"); + String repositoryPassword = + IntegrityMonitorProperties.getProperty("repository.audit.password"); + boolean upload = + (repositoryId != null && repositoryUrl != null + && repositoryUsername != null && repositoryPassword != null); + + // used to incrementally construct response as problems occur + // (empty = no problems) + StringBuilder response = new StringBuilder(); + + long timeoutInSeconds = DEFAULT_TIMEOUT; + String timeoutString = + IntegrityMonitorProperties.getProperty("repository.audit.timeout"); + if (timeoutString != null && !timeoutString.isEmpty()) + { + try + { + timeoutInSeconds = Long.valueOf(timeoutString); + } + catch (NumberFormatException e) + { + logger.error + ("RepositoryAudit: Invalid 'repository.audit.timeout' value: '" + + timeoutString + "'"); + response.append("Invalid 'repository.audit.timeout' value: '") + .append(timeoutString).append("'\n"); + setResponse(response.toString()); + } + } + + // artifacts to be downloaded + LinkedList<Artifact> artifacts = new LinkedList<Artifact>(); + + /* + * 1) create temporary directory + */ + Path dir = Files.createTempDirectory("auditRepo"); + logger.info("RepositoryAudit: temporary directory = " + dir); + + // nested 'pom.xml' file and 'repo' directory + Path pom = dir.resolve("pom.xml"); + Path repo = dir.resolve("repo"); + + /* + * 2) Create test file, and upload to repository + * (only if repository information is specified) + */ + String groupId = null; + String artifactId = null; + String version = null; + if (upload) + { + groupId = "org.openecomp.policy.audit"; + artifactId = "repository-audit"; + version = "0." + System.currentTimeMillis(); + + if (repositoryUrl.toLowerCase().contains("snapshot")) + { + // use SNAPSHOT version + version += "-SNAPSHOT"; + } + + // create text file to write + FileOutputStream fos = + new FileOutputStream(dir.resolve("repository-audit.txt").toFile()); + try + { + fos.write(version.getBytes()); + } + finally + { + fos.close(); + } + + // try to install file in repository + if (runProcess + (timeoutInSeconds, dir.toFile(), null, + "mvn", "deploy:deploy-file", + "-DrepositoryId=" + repositoryId, + "-Durl=" + repositoryUrl, + "-Dfile=repository-audit.txt", + "-DgroupId=" + groupId, + "-DartifactId=" + artifactId, + "-Dversion=" + version, + "-Dpackaging=txt", + "-DgeneratePom=false") != 0) + { + logger.error + ("RepositoryAudit: 'mvn deploy:deploy-file' failed"); + response.append("'mvn deploy:deploy-file' failed\n"); + setResponse(response.toString()); + } + else + { + logger.info + ("RepositoryAudit: 'mvn deploy:deploy-file succeeded"); + + // we also want to include this new artifact in the download + // test (steps 3 and 4) + artifacts.add(new Artifact(groupId, artifactId, version, "txt")); + } + } + + /* + * 3) create 'pom.xml' file in temporary directory + */ + artifacts.add(new Artifact("org.apache.maven/maven-embedder/3.2.2")); + + StringBuilder sb = new StringBuilder(); + sb.append + ("<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n" + + " xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd\">\n" + + "\n" + + " <modelVersion>4.0.0</modelVersion>\n" + + " <groupId>empty</groupId>\n" + + " <artifactId>empty</artifactId>\n" + + " <version>1.0-SNAPSHOT</version>\n" + + " <packaging>pom</packaging>\n" + + "\n" + + " <build>\n" + + " <plugins>\n" + + " <plugin>\n" + + " <groupId>org.apache.maven.plugins</groupId>\n" + + " <artifactId>maven-dependency-plugin</artifactId>\n" + + " <version>2.10</version>\n" + + " <executions>\n" + + " <execution>\n" + + " <id>copy</id>\n" + + " <goals>\n" + + " <goal>copy</goal>\n" + + " </goals>\n" + + " <configuration>\n" + + " <localRepositoryDirectory>") + .append(repo) + .append("</localRepositoryDirectory>\n") + .append(" <artifactItems>\n"); + for (Artifact artifact : artifacts) + { + // each artifact results in an 'artifactItem' element + sb.append + (" <artifactItem>\n" + + " <groupId>") + .append(artifact.groupId) + .append + ("</groupId>\n" + + " <artifactId>") + .append(artifact.artifactId) + .append + ("</artifactId>\n" + + " <version>") + .append(artifact.version) + .append + ("</version>\n" + + " <type>") + .append(artifact.type) + .append + ("</type>\n" + + " </artifactItem>\n"); + } + sb.append + (" </artifactItems>\n" + + " </configuration>\n" + + " </execution>\n" + + " </executions>\n" + + " </plugin>\n" + + " </plugins>\n" + + " </build>\n" + + "</project>\n"); + FileOutputStream fos = new FileOutputStream(pom.toFile()); + try + { + fos.write(sb.toString().getBytes()); + } + finally + { + fos.close(); + } + + /* + * 4) Invoke external 'mvn' process to do the downloads + */ + + // output file = ${dir}/out (this supports step '4a') + File output = dir.resolve("out").toFile(); + + // invoke process, and wait for response + int rval = runProcess + (timeoutInSeconds, dir.toFile(), output, "mvn", "compile"); + logger.info("RepositoryAudit: 'mvn' return value = " + rval); + if (rval != 0) + { + logger.error + ("RepositoryAudit: 'mvn compile' invocation failed"); + response.append("'mvn compile' invocation failed\n"); + setResponse(response.toString()); + } + + /* + * 4a) Check attempted and successful downloads from output file + * Note: at present, this step just generates log messages, + * but doesn't do any verification. + */ + if (rval == 0) + { + // place output in 'fileContents' (replacing the Return characters + // with Newline) + byte[] outputData = new byte[(int)output.length()]; + FileInputStream fis = new FileInputStream(output); + fis.read(outputData); + String fileContents = new String(outputData).replace('\r','\n'); + fis.close(); + + // generate log messages from 'Downloading' and 'Downloaded' + // messages within the 'mvn' output + int index = 0; + while ((index = fileContents.indexOf("\nDown", index)) > 0) + { + index += 5; + if (fileContents.regionMatches(index, "loading: ", 0, 9)) + { + index += 9; + int endIndex = fileContents.indexOf('\n', index); + logger.info + ("RepositoryAudit: Attempted download: '" + + fileContents.substring(index, endIndex) + "'"); + index = endIndex; + } + else if (fileContents.regionMatches(index, "loaded: ", 0, 8)) + { + index += 8; + int endIndex = fileContents.indexOf(' ', index); + logger.info + ("RepositoryAudit: Successful download: '" + + fileContents.substring(index, endIndex) + "'"); + index = endIndex; + } + } + } + + /* + * 5) Check the contents of the directory to make sure the downloads + * were successful + */ + for (Artifact artifact : artifacts) + { + if (repo.resolve(artifact.groupId.replace('.','/')) + .resolve(artifact.artifactId) + .resolve(artifact.version) + .resolve(artifact.artifactId + "-" + artifact.version + "." + + artifact.type).toFile().exists()) + { + // artifact exists, as expected + logger.info("RepositoryAudit: " + + artifact.toString() + ": exists"); + } + else + { + // Audit ERROR: artifact download failed for some reason + logger.error("RepositoryAudit: " + + artifact.toString() + ": does not exist"); + response.append("Failed to download artifact: ") + .append(artifact).append('\n'); + setResponse(response.toString()); + } + } + + /* + * 6) Use 'curl' to delete the uploaded test file + * (only if repository information is specified) + */ + if (upload) + { + if (runProcess + (timeoutInSeconds, dir.toFile(), null, + "curl", + "--request", "DELETE", + "--user", repositoryUsername + ":" + repositoryPassword, + (repositoryUrl + "/" + groupId.replace('.', '/') + "/" + + artifactId + "/" + version)) + != 0) + { + logger.error + ("RepositoryAudit: delete of uploaded artifact failed"); + response.append("delete of uploaded artifact failed\n"); + setResponse(response.toString()); + } + else + { + logger.info + ("RepositoryAudit: delete of uploaded artifact succeeded"); + artifacts.add(new Artifact(groupId, artifactId, version, "txt")); + } + } + + /* + * 7) Remove the temporary directory + */ + Files.walkFileTree + (dir, + new SimpleFileVisitor<Path>() + { + public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) + { + // logger.info("RepositoryAudit: Delete " + file); + file.toFile().delete(); + return(FileVisitResult.CONTINUE); + } + + public FileVisitResult postVisitDirectory(Path file, IOException e) + throws IOException + { + if (e == null) + { + // logger.info("RepositoryAudit: Delete " + file); + file.toFile().delete(); + return(FileVisitResult.CONTINUE); + } + else + { + throw(e); + } + } + }); + } + + /** + * Run a process, and wait for the response + * + * @param timeoutInSeconds the number of seconds to wait for the + * process to terminate + * @param directory the execution directory of the process + * (null = current directory) + * @param stdout the file to contain the standard output + * (null = discard standard output) + * @param command command and arguments + * @return the return value of the process + * @throws IOException, InterruptedException + */ + static int runProcess(long timeoutInSeconds, + File directory, File stdout, String... command) + throws IOException, InterruptedException + { + ProcessBuilder pb = new ProcessBuilder(command); + if (directory != null) + { + pb.directory(directory); + } + if (stdout != null) + { + pb.redirectOutput(stdout); + } + + Process process = pb.start(); + if (process.waitFor(timeoutInSeconds, TimeUnit.SECONDS)) + { + // process terminated before the timeout + return(process.exitValue()); + } + + // process timed out -- kill it, and return -1 + process.destroyForcibly(); + return(-1); + } + + /* ============================================================ */ + + /** + * An instance of this class exists for each artifact that we are trying + * to download. + */ + static class Artifact + { + String groupId, artifactId, version, type; + + /** + * Constructor - populate the 'Artifact' instance + * + * @param groupId groupId of artifact + * @param artifactId artifactId of artifact + * @param version version of artifact + * @param type type of the artifact (e.g. "jar") + */ + Artifact(String groupId, String artifactId, String version, String type) + { + this.groupId = groupId; + this.artifactId = artifactId; + this.version = version; + this.type = type; + } + + /** + * Constructor - populate an 'Artifact' instance + * + * @param artifact a string of the form: + * "<groupId>/<artifactId>/<version>[/<type>]" + * @throws IllegalArgumentException if 'artifact' has the incorrect format + */ + Artifact(String artifact) + { + String[] segments = artifact.split("/"); + if (segments.length != 4 && segments.length != 3) + { + throw(new IllegalArgumentException("groupId/artifactId/version/type")); + } + groupId = segments[0]; + artifactId = segments[1]; + version = segments[2]; + type = (segments.length == 4 ? segments[3] : "jar"); + } + + /** + * @return the artifact id in the form: + * "<groupId>/<artifactId>/<version>/<type>" + */ + public String toString() + { + return(groupId + "/" + artifactId + "/" + version + "/" + type); + } + } +} diff --git a/policy-persistence/src/main/java/org/openecomp/policy/drools/im/PMStandbyStateChangeNotifier.java b/policy-persistence/src/main/java/org/openecomp/policy/drools/im/PMStandbyStateChangeNotifier.java new file mode 100644 index 00000000..46e5a5e6 --- /dev/null +++ b/policy-persistence/src/main/java/org/openecomp/policy/drools/im/PMStandbyStateChangeNotifier.java @@ -0,0 +1,280 @@ +/*- + * ============LICENSE_START======================================================= + * policy-persistence + * ================================================================================ + * 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.im; + +/* + * Per MultiSite_v1-10.ppt: + * + * Extends the StateChangeNotifier class and overwrites the abstract handleStateChange() method to get state changes + * and do the following: + * + * When the Standby Status changes (from providingservice) to hotstandby or coldstandby, + * the Active/Standby selection algorithm must stand down if the PDP-D is currently the lead/active node + * and allow another PDP-D to take over. It must also call lock on all engines in the engine management. + * + * When the Standby Status changes from (hotstandby) to coldstandby, the Active/Standby algorithm must NOT assume + * the active/lead role. + * + * When the Standby Status changes (from coldstandby or providingservice) to hotstandby, + * the Active/Standby algorithm may assume the active/lead role if the active/lead fails. + * + * When the Standby Status changes to providingservice (from hotstandby or coldstandby) call unlock on all + * engines in the engine management layer. + */ +import java.util.Date; +import java.util.Timer; +import java.util.TimerTask; + +import org.openecomp.policy.common.im.StateChangeNotifier; +import org.openecomp.policy.common.im.StateManagement; +import org.openecomp.policy.drools.controller.internal.MavenDroolsController; +import org.openecomp.policy.drools.core.IntegrityMonitorProperties; +import org.openecomp.policy.drools.event.comm.TopicEndpoint; +import org.openecomp.policy.common.logging.flexlogger.FlexLogger; +import org.openecomp.policy.common.logging.flexlogger.Logger; +import org.openecomp.policy.drools.persistence.DroolsPdpsConnector; +import org.openecomp.policy.drools.persistence.PersistenceFeature; +import org.openecomp.policy.drools.system.PolicyEngine; + +/* + * Some background: + * + * Originally, there was a "StandbyStateChangeNotifier" that belonged to policy-core, and this class's handleStateChange() method + * used to take care of invoking conn.standDownPdp(). But testing revealed that when a state change to hot standby occurred + * from a demote() operation, first the PMStandbyStateChangeNotifier.handleStateChange() method would be invoked and then the + * StandbyStateChangeNotifier.handleStateChange() method would be invoked, and this ordering was creating the following problem: + * + * When PMStandbyStateChangeNotifier.handleStateChange() was invoked it would take a long time to finish, because it would result + * in SingleThreadedUebTopicSource.stop() being invoked, which can potentially do a 5 second sleep for each controller being stopped. + * Meanwhile, as these controller stoppages and their associated sleeps were occurring, the election handler would discover the + * demoted PDP in hotstandby (but still designated!) and promote it, resulting in the standbyStatus going from hotstandby + * to providingservice. So then, by the time that PMStandbyStateChangeNotifier.handleStateChange() finished its work and + * StandbyStateChangeNotifier.handleStateChange() started executing, the standbyStatus was no longer hotstandby (as effected by + * the demote), but providingservice (as reset by the election handling logic) and conn.standDownPdp() would not get called! + * + * To fix this bug, we consolidated StandbyStateChangeNotifier and PMStandbyStateChangeNotifier, with the standDownPdp() always + * being invoked prior to the TopicEndpoint.manager.lock(). In this way, when the election handling logic is invoked + * during the controller stoppages, the PDP is in hotstandby and the standdown occurs. + * + */ +public class PMStandbyStateChangeNotifier extends StateChangeNotifier { + // get an instance of logger + private static Logger logger = FlexLogger.getLogger(PMStandbyStateChangeNotifier.class); + private Timer delayActivateTimer; + private int pdpUpdateInterval; + private boolean isWaitingForActivation; + private long startTimeWaitingForActivationMs; + private long waitInterval; + private boolean isNowActivating; + + public PMStandbyStateChangeNotifier(){ + pdpUpdateInterval = Integer.parseInt(IntegrityMonitorProperties.getProperty(IntegrityMonitorProperties.PDP_UPDATE_INTERVAL)); + isWaitingForActivation = false; + startTimeWaitingForActivationMs = new Date().getTime(); + //delay the activate so the DesignatedWaiter can run twice - give it an extra 2 seconds + waitInterval = 2*pdpUpdateInterval + 2000; + isNowActivating=false; + } + + @Override + public void handleStateChange() { + /* + * A note on synchronization: This method is not synchronized because the caller, stateManagememt, + * has synchronize all of its methods. Only one stateManagement operation can occur at a time. Thus, + * only one handleStateChange() call will ever be made at a time. + */ + + logger.info("handleStateChange: Entering, message='" + + super.getMessage() + "', standbyStatus='" + + super.getStateManagement().getStandbyStatus() + "'"); + + String standbyStatus = super.getStateManagement().getStandbyStatus(); + String pdpId = IntegrityMonitorProperties + .getProperty(IntegrityMonitorProperties.PDP_INSTANCE_ID); + DroolsPdpsConnector conn = PersistenceFeature + .getDroolsPdpsConnector("ncompPU"); + + if (standbyStatus == null) { + logger.info("handleStateChange: standbyStatus is null; standing down PDP=" + pdpId); + isWaitingForActivation = false; + try{ + try{ + logger.info("handleStateChange: null: cancelling delayActivationTimer."); + delayActivateTimer.cancel(); + }catch(Exception e){ + logger.info("handleStateChange: null no delayActivationTimer existed."); + //If you end of here, there was no active timer + } + conn.standDownPdp(pdpId); + //Only want to lock the endpoints, not the controllers. + PolicyEngine.manager.deactivate(); + }catch(Exception e){ + logger.warn("handleStateChange: standbyStatus == null caught exception: " + e); + e.printStackTrace(); + } + + } else if (standbyStatus.equals("null")) { + logger.info("handleStateChange: standbyStatus equals 'null'; standing down PDP=" + pdpId); + isWaitingForActivation = false; + try{ + try{ + logger.info("handleStateChange: NULL_VALUE: cancelling delayActivationTimer."); + delayActivateTimer.cancel(); + }catch(Exception e){ + logger.info("handleStateChange: NULL_VALUE no delayActivationTimer existed."); + //If you end of here, there was no active timer + } + conn.standDownPdp(pdpId); + //Only want to lock the endpoints, not the controllers. + PolicyEngine.manager.deactivate(); + }catch(Exception e){ + logger.warn("handleStateChange: standbyStatus == \"null\" caught exception: " + e); + e.printStackTrace(); + } + } else if (standbyStatus.equals(StateManagement.HOT_STANDBY) || standbyStatus.equals(StateManagement.COLD_STANDBY)) { + logger.info("handleStateChange: standbyStatus=" + standbyStatus + "; standing down PDP=" + pdpId); + isWaitingForActivation = false; + try{ + try{ + logger.info("handleStateChange: HOT_STNDBY || COLD_STANDBY: cancelling delayActivationTimer."); + delayActivateTimer.cancel(); + }catch(Exception e){ + logger.info("handleStateChange: HOT_STANDBY || COLD_STANDBY no delayActivationTimer existed."); + //If you end of here, there was no active timer + } + //Only want to lock the endpoints, not the controllers. + conn.standDownPdp(pdpId); + PolicyEngine.manager.deactivate(); + }catch(Exception e){ + logger.warn("handleStateChange: standbyStatus == " + standbyStatus + " caught exception: " + e); + e.printStackTrace(); + } + + } else if (standbyStatus.equals(StateManagement.PROVIDING_SERVICE)) { + try{ + //UnLock all the endpoints + logger.info("handleStateChange: standbyStatus=" + standbyStatus + "; controllers must be unlocked."); + /* + * Only endpoints should be unlocked. Controllers have not been locked. + * Because, sometimes, it is possible for more than one PDP-D to become active (race conditions) + * we need to delay the activation of the topic endpoint interfaces to give the election algorithm + * time to resolve the conflict. + */ + logger.info("handleStateChange: PROVIDING_SERVICE isWaitingForActivation= " +isWaitingForActivation); + //Delay activation for 2*pdpUpdateInterval+2000 ms in case of an election handler conflict. + //You could have multiple election handlers thinking they can take over. + + // First let's check that the timer has not died + if(isWaitingForActivation){ + logger.info("handleStateChange: PROVIDING_SERVICE isWaitingForActivation = " + isWaitingForActivation); + long now = new Date().getTime(); + long waitTimeMs = now - startTimeWaitingForActivationMs; + if(waitTimeMs > 3*waitInterval){ + logger.info("handleStateChange: PROVIDING_SERVICE looks like the activation wait timer may be hung," + + " waitTimeMs = " + waitTimeMs + " and allowable waitInterval = " + waitInterval + + " Checking whether it is currently in activation. isNowActivating = " + isNowActivating); + //Now check that it is not currently executing an activation + if(!isNowActivating){ + logger.info("handleStateChange: PROVIDING_SERVICE looks like the activation wait timer died"); + // This will assure the timer is cancelled and rescheduled. + isWaitingForActivation = false; + } + } + + } + + if(!isWaitingForActivation){ + try{ + //Just in case there is an old timer hanging around + logger.info("handleStateChange: PROVIDING_SERVICE cancelling delayActivationTimer."); + delayActivateTimer.cancel(); + }catch(Exception e){ + logger.info("handleStateChange: PROVIDING_SERVICE no delayActivationTimer existed."); + //If you end of here, there was no active timer + } + delayActivateTimer = new Timer(); + //delay the activate so the DesignatedWaiter can run twice + delayActivateTimer.schedule(new DelayActivateClass(), waitInterval); + isWaitingForActivation = true; + startTimeWaitingForActivationMs = new Date().getTime(); + logger.info("handleStateChange: PROVIDING_SERVICE scheduling delayActivationTimer in " + waitInterval + " ms"); + }else{ + logger.info("handleStateChange: PROVIDING_SERVICE delayActivationTimer is waiting for activation."); + } + + }catch(Exception e){ + logger.warn("handleStateChange: PROVIDING_SERVICE standbyStatus == providingservice caught exception: " + e); + e.printStackTrace(); + } + + } else { + logger.error("handleStateChange: Unsupported standbyStatus=" + standbyStatus + "; standing down PDP=" + pdpId); + //Only want to lock the endpoints, not the controllers. + isWaitingForActivation = false; + try{ + try{ + logger.info("handleStateChange: unsupported standbystatus: cancelling delayActivationTimer."); + delayActivateTimer.cancel(); + }catch(Exception e){ + logger.info("handleStateChange: unsupported standbystatus: no delayActivationTimer existed."); + //If you end of here, there was no active timer + } + conn.standDownPdp(pdpId); + PolicyEngine.manager.deactivate(); + }catch(Exception e){ + logger.warn("handleStateChange: Unsupported standbyStatus == " + standbyStatus + "caught exception: " + e); + e.printStackTrace(); + } + } + + //if (logger.isDebugEnabled()) { + logger.info("handleStateChange: Exiting"); + //} + } + + private class DelayActivateClass extends TimerTask{ + + private Object delayActivateLock = new Object(); + + + @Override + public void run() { + isNowActivating = true; + try{ + logger.info("DelayActivateClass.run: entry"); + synchronized(delayActivateLock){ + PolicyEngine.manager.activate(); + // We want to set this to false here because the activate call can take a while + isWaitingForActivation = false; + isNowActivating = false; + } + logger.info("DelayActivateClass.run.exit"); + }catch(Exception e){ + isWaitingForActivation = false; + isNowActivating = false; + logger.warn("DelayActivateClass.run: caught an unexpected exception " + + "calling PolicyEngine.manager.activate: " + e); + System.out.println(new Date() + " DelayActivateClass.run: caught an unexpected exception"); + e.printStackTrace(); + } + } + } +} diff --git a/policy-persistence/src/main/java/org/openecomp/policy/drools/persistence/DroolsPdp.java b/policy-persistence/src/main/java/org/openecomp/policy/drools/persistence/DroolsPdp.java new file mode 100644 index 00000000..11cc8788 --- /dev/null +++ b/policy-persistence/src/main/java/org/openecomp/policy/drools/persistence/DroolsPdp.java @@ -0,0 +1,45 @@ +/*- + * ============LICENSE_START======================================================= + * policy-persistence + * ================================================================================ + * 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.persistence; + +import java.util.Date; +import java.util.List; + +public interface DroolsPdp { + + public List<DroolsSessionEntity> getSessions(); + public void addSession(DroolsSession session); + public void removeSession(DroolsSession session); + public String getPdpId(); + public boolean isDesignated(); + public int getPriority(); + public Date getUpdatedDate(); + public void setDesignated(boolean isDesignated); + public void setUpdatedDate(Date updatedDate); + public int comparePriority(DroolsPdp other); + public int comparePriority(DroolsPdp other,String previousSite); + public DroolsSession getSession(String sessionName); + public void setSessionId(String sessionName, long sessionId); + public String getSiteName(); + public void setSiteName(String siteName); + public Date getDesignatedDate(); + public void setDesignatedDate(Date designatedDate); +} diff --git a/policy-persistence/src/main/java/org/openecomp/policy/drools/persistence/DroolsPdpEntity.java b/policy-persistence/src/main/java/org/openecomp/policy/drools/persistence/DroolsPdpEntity.java new file mode 100644 index 00000000..87b58723 --- /dev/null +++ b/policy-persistence/src/main/java/org/openecomp/policy/drools/persistence/DroolsPdpEntity.java @@ -0,0 +1,171 @@ +/*- + * ============LICENSE_START======================================================= + * policy-persistence + * ================================================================================ + * 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.persistence; + +import java.io.Serializable; +import java.util.Date; +import java.util.List; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.NamedQueries; +import javax.persistence.NamedQuery; +import javax.persistence.OneToMany; +import javax.persistence.Temporal; +import javax.persistence.TemporalType; + +import org.openecomp.policy.drools.persistence.DroolsPdpObject; + +@Entity +//@Table(name="DroolsPdpEntity") + +@NamedQueries({ + @NamedQuery(name="DroolsPdpEntity.findAll", query="SELECT e FROM DroolsPdpEntity e "), + @NamedQuery(name="DroolsPdpEntity.deleteAll", query="DELETE FROM DroolsPdpEntity WHERE 1=1") +}) +public class DroolsPdpEntity extends DroolsPdpObject implements Serializable{ + + private static final long serialVersionUID = 1L; + + @Id + @Column(name="pdpId", nullable=false) + private String pdpId="-1"; + + @Column(name="designated", nullable=false) + private boolean designated=false; + + @Column(name="priority", nullable=false) + private int priority=0; + + @Temporal(TemporalType.TIMESTAMP) + @Column(name="updatedDate", nullable=false) + private Date updatedDate; + + @Temporal(TemporalType.TIMESTAMP) + @Column(name="designatedDate",nullable=false) + private Date designatedDate; + + @Column(name="site", nullable=true, length = 50) + private String site; + + + @OneToMany(mappedBy="pdpEntity") + //@OneToMany + //@JoinColumn(name="pdpId", referencedColumnName="pdpId") + //@JoinColumn(name="pdpId") + private List<DroolsSessionEntity> sessions; + + + public DroolsPdpEntity(){ + updatedDate = new Date(); + //When this is translated to a TimeStamp in MySQL, it assumes the date is relative + //to the local timezone. So, a value of Date(0) is actually Dec 31 18:00:00 CST 1969 + //which is an invalid value for the MySql TimeStamp + designatedDate = new Date(864000000); + } + + @Override + public String getPdpId() { + return this.pdpId; + } + + public void setPdpId(String pdpId) { + this.pdpId = pdpId; + } + + @Override + public boolean isDesignated() { + return this.designated; + } + + @Override + public int getPriority() { + return this.priority; + } + + public void setPriority(int priority) { + this.priority = priority; + } + + @Override + public Date getUpdatedDate() { + return this.updatedDate; + } + + @Override + public void setDesignated(boolean isDesignated) { + this.designated=isDesignated; + } + + @Override + public void setUpdatedDate(Date updatedDate) { + this.updatedDate=updatedDate; + } + + + public List<DroolsSessionEntity> getSessions() { + return sessions; + } + + public void addSession(DroolsSessionEntity session) { + sessions.add(session); + } + + public void removeSession(DroolsSessionEntity session) { + sessions.remove(session); + + } + + @Override + public void addSession(DroolsSession session) { + // TODO Auto-generated method stub + + } + + @Override + public void removeSession(DroolsSession session) { + // TODO Auto-generated method stub + + } + + @Override + public String getSiteName() { + return site; + } + + @Override + public void setSiteName(String siteName) { + site = siteName; + + } + + @Override + public Date getDesignatedDate() { + return designatedDate; + } + + @Override + public void setDesignatedDate(Date designatedDate) { + this.designatedDate = designatedDate; + } + +} diff --git a/policy-persistence/src/main/java/org/openecomp/policy/drools/persistence/DroolsPdpImpl.java b/policy-persistence/src/main/java/org/openecomp/policy/drools/persistence/DroolsPdpImpl.java new file mode 100644 index 00000000..e0f5d816 --- /dev/null +++ b/policy-persistence/src/main/java/org/openecomp/policy/drools/persistence/DroolsPdpImpl.java @@ -0,0 +1,115 @@ +/*- + * ============LICENSE_START======================================================= + * policy-persistence + * ================================================================================ + * 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.persistence; + +import java.util.Date; +import java.util.LinkedList; +import java.util.List; + + +public class DroolsPdpImpl extends DroolsPdpObject { + + private boolean designated; + private int priority; + private Date updatedDate; + private Date designatedDate; + private String pdpId; + private String site; + private List<DroolsSessionEntity> sessions; + + public DroolsPdpImpl(String pdpId, boolean designated, int priority, Date updatedDate){ + this.pdpId = pdpId; + this.designated = designated; + this.priority = priority; + this.updatedDate = updatedDate; + //When this is translated to a TimeStamp in MySQL, it assumes the date is relative + //to the local timezone. So, a value of Date(0) is actually Dec 31 18:00:00 CST 1969 + //which is an invalid value for the MySql TimeStamp + this.designatedDate = new Date(864000000); + sessions = new LinkedList<DroolsSessionEntity>(); + + } + @Override + public boolean isDesignated() { + + return designated; + } + + @Override + public int getPriority() { + return priority; + } + @Override + public void setUpdatedDate(Date date){ + this.updatedDate = date; + } + @Override + public Date getUpdatedDate() { + return updatedDate; + } + + @Override + public String getPdpId() { + return pdpId; + } + @Override + public void setDesignated(boolean isDesignated) { + this.designated = isDesignated; + + } + + + @Override + public List<DroolsSessionEntity> getSessions() { + // TODO Auto-generated method stub + return sessions; + } + @Override + public void addSession(DroolsSession session) { + + + } + @Override + public void removeSession(DroolsSession session) { + // TODO Auto-generated method stub + + } + @Override + public String getSiteName() { + return site; + } + @Override + public void setSiteName(String siteName) { + this.site = siteName; + + } + @Override + public Date getDesignatedDate() { + return designatedDate; + } + @Override + public void setDesignatedDate(Date designatedDate) { + this.designatedDate = designatedDate; + + } + + +} diff --git a/policy-persistence/src/main/java/org/openecomp/policy/drools/persistence/DroolsPdpObject.java b/policy-persistence/src/main/java/org/openecomp/policy/drools/persistence/DroolsPdpObject.java new file mode 100644 index 00000000..7a219148 --- /dev/null +++ b/policy-persistence/src/main/java/org/openecomp/policy/drools/persistence/DroolsPdpObject.java @@ -0,0 +1,97 @@ +/*- + * ============LICENSE_START======================================================= + * policy-persistence + * ================================================================================ + * 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.persistence; + + +public abstract class DroolsPdpObject implements DroolsPdp{ + + @Override + public boolean equals(Object other){ + if(other instanceof DroolsPdp){ + return this.getPdpId().equals(((DroolsPdp)other).getPdpId()); + }else{ + return false; + } + } + private int nullSafeCompare(Comparable one, Comparable two){ + if(one != null && two != null){ + return one.compareTo(two); + } + if(one == null && two != null){ + return -1; + } + if(one != null && two == null){ + return 1; + } + return 0; + } + @Override + public int comparePriority(DroolsPdp other){ + if(nullSafeCompare(this.getSiteName(),other.getSiteName()) == 0){ + if(this.getPriority() != other.getPriority()){ + return this.getPriority() - other.getPriority(); + } + return this.getPdpId().compareTo(other.getPdpId()); + } else { + return nullSafeCompare(this.getSiteName(),other.getSiteName()); + } + } + @Override + public int comparePriority(DroolsPdp other, String previousSite){ + if(previousSite == null || previousSite.equals("")){ + return comparePriority(other); + } + if(nullSafeCompare(this.getSiteName(),other.getSiteName()) == 0){ + if(this.getPriority() != other.getPriority()){ + return this.getPriority() - other.getPriority(); + } + return this.getPdpId().compareTo(other.getPdpId()); + } else { + return nullSafeCompare(this.getSiteName(),other.getSiteName()); + } + } + @Override + public DroolsSession getSession(String sessionName){ + for(DroolsSession session : getSessions()){ + if(session.getSessionName().equals(sessionName)){ + return session; + } + } + return null; + } + @Override + public void setSessionId(String sessionName, long sessionId){ + for(DroolsSession session : getSessions()){ + if(session.getSessionName().equals(sessionName)){ + session.setSessionId(sessionId); + return; + } + } + DroolsSessionEntity newSession = new DroolsSessionEntity(); + DroolsPdpEntity pdpEntityWithPdpId = new DroolsPdpEntity(); + pdpEntityWithPdpId.setPdpId(this.getPdpId()); + newSession.setPdpEntity(pdpEntityWithPdpId); + newSession.setPdpId(getPdpId()); + newSession.setSessionName(sessionName); + newSession.setSessionId(sessionId); + getSessions().add(newSession); + } +} diff --git a/policy-persistence/src/main/java/org/openecomp/policy/drools/persistence/DroolsPdpsConnector.java b/policy-persistence/src/main/java/org/openecomp/policy/drools/persistence/DroolsPdpsConnector.java new file mode 100644 index 00000000..fa75c2e7 --- /dev/null +++ b/policy-persistence/src/main/java/org/openecomp/policy/drools/persistence/DroolsPdpsConnector.java @@ -0,0 +1,67 @@ +/*- + * ============LICENSE_START======================================================= + * policy-persistence + * ================================================================================ + * 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.persistence; + +import java.util.Collection; + +public interface DroolsPdpsConnector { + + + //return a list of PDPs, NOT including this PDP + public Collection<DroolsPdp> getDroolsPdps(); + + public void update(DroolsPdp pdp); + + //determines if the DroolsPdp parameter is considered "current" or expired (has it been too long since the Pdp sent an update) + public boolean isPdpCurrent(DroolsPdp pdp); + + // Updates DESIGNATED boolean in PDP record. + public void setDesignated(DroolsPdp pdp, boolean designated); + + // Marks droolspdpentity.DESIGNATED=false, so another PDP-D will go active. + public void standDownPdp(String pdpId); + + // This is used in a JUnit test environment to manually + // insert a PDP + public void insertPdp(DroolsPdp pdp); + + // This is used in a JUnit test environment to manually + // delete a PDP + public void deletePdp(String pdpId); + + // This is used in a JUnit test environment to manually + // clear the droolspdpentity table. + public void deleteAllPdps(); + + // This is used in a JUnit test environment to manually + // clear the droolspdpentity table. + public void deleteAllSessions(); + + // This is used in a JUnit test environment to manually + // get a PDP + public DroolsPdpEntity getPdp(String pdpId); + + // Used by DroolsPdpsElectionHandler to determine if the currently designated + // PDP has failed. + public boolean hasDesignatedPdpFailed(Collection<DroolsPdp> pdps); + + +} diff --git a/policy-persistence/src/main/java/org/openecomp/policy/drools/persistence/DroolsPdpsElectionHandler.java b/policy-persistence/src/main/java/org/openecomp/policy/drools/persistence/DroolsPdpsElectionHandler.java new file mode 100644 index 00000000..82ee5d1d --- /dev/null +++ b/policy-persistence/src/main/java/org/openecomp/policy/drools/persistence/DroolsPdpsElectionHandler.java @@ -0,0 +1,948 @@ +/*- + * ============LICENSE_START======================================================= + * policy-persistence + * ================================================================================ + * 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.persistence; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Date; +import java.util.LinkedList; +import java.util.List; +import java.util.Timer; +import java.util.TimerTask; + +import org.openecomp.policy.common.im.StandbyStatusException; +import org.openecomp.policy.common.im.StateManagement; +import org.openecomp.policy.drools.core.DroolsPDPIntegrityMonitor; +import org.openecomp.policy.drools.core.IntegrityMonitorProperties; +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 DroolsPdpsElectionHandler implements ThreadRunningChecker { + // get an instance of logger + private final static Logger logger = FlexLogger.getLogger(DroolsPdpsElectionHandler.class); + private DroolsPdpsConnector pdpsConnector; + private Object pdpsConnectorLock = new Object(); + private Object checkUpdateWorkerLock = new Object(); + private Object checkWaitTimerLock = new Object(); + private Object designationWaiterLock = new Object(); + + /* + * Must be static, so it can be referenced by JpaDroolsPdpsConnector, + * without requiring a reference to the election handler instantiation. + */ + private static DroolsPdp myPdp; + + private DesignationWaiter designationWaiter; + private Timer updateWorker; + private Timer waitTimer; + private Date updateWorkerLastRunDate; + private Date waitTimerLastRunDate; + private int pdpCheckInterval; + private int pdpUpdateInterval; + private volatile boolean isDesignated; + DroolsPDPIntegrityMonitor droolsPdpIntegrityMonitor; + StateManagement stateManagement; + + public DroolsPdpsElectionHandler(DroolsPdpsConnector pdps, DroolsPdp myPdp, DroolsPDPIntegrityMonitor droolsPdpIntegrityMonitor){ + this.pdpsConnector = pdps; + DroolsPdpsElectionHandler.myPdp = myPdp; + this.isDesignated = false; + this.droolsPdpIntegrityMonitor = droolsPdpIntegrityMonitor; + this.stateManagement = droolsPdpIntegrityMonitor.getStateManager(); + pdpCheckInterval = 3000; + try{ + pdpCheckInterval = Integer.parseInt(IntegrityMonitorProperties.getProperty(IntegrityMonitorProperties.PDP_CHECK_INVERVAL)); + }catch(Exception e){ + logger.error + //System.out.println + (MessageCodes.EXCEPTION_ERROR ,e, "Could not get pdpCheckInterval property. Using default"); + } + pdpUpdateInterval = 2000; + try{ + pdpUpdateInterval = Integer.parseInt(IntegrityMonitorProperties.getProperty(IntegrityMonitorProperties.PDP_UPDATE_INTERVAL)); + }catch(Exception e){ + logger.error + //System.out.println + (MessageCodes.EXCEPTION_ERROR, e, "Could not get pdpUpdateInterval property. Using default"); + } + + Date now = new Date(); + + // Retrieve the ms since the epoch + long nowMs = now.getTime(); + + // Create the timer which will update the updateDate in DroolsPdpEntity table. + // This is the heartbeat + updateWorker = new Timer(); + + // Schedule the heartbeat to start in 100 ms and run at pdpCheckInterval ms thereafter + updateWorker.scheduleAtFixedRate(new TimerUpdateClass(), 100, pdpCheckInterval); + updateWorkerLastRunDate = new Date(nowMs + 100); + + // Create the timer which will run the election algorithm + waitTimer = new Timer(); + + // Schedule it to start in startMs ms (so it will run after the updateWorker and run at pdpUpdateInterval ms thereafter + long startMs = getDWaiterStartMs(); + designationWaiter = new DesignationWaiter(); + waitTimer.scheduleAtFixedRate(designationWaiter, startMs, pdpUpdateInterval); + waitTimerLastRunDate = new Date(nowMs + startMs); + } + + public List<DroolsSessionEntity> waitForDesignation(){ + while(isDesignated == false){ + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + return null; + } + } + return designationWaiter.getSessions(); + + } + public List<DroolsSessionEntity> getSessions(){ + return designationWaiter.getSessions(); + } + public void updateMyPdp(){ + synchronized(pdpsConnectorLock){ + myPdp.setUpdatedDate(new Date()); + pdpsConnector.update(myPdp); + } + } + + /* + * When the JpaDroolsPdpsConnector.standDown() method is invoked, it needs + * access to myPdp, so it can keep its designation status in sync with the + * DB. + */ + public static void setMyPdpDesignated(boolean designated) { + logger.debug + //System.out.println + ("setMyPdpDesignated: designated=" + designated); + myPdp.setDesignated(designated); + } + + private class DesignationWaiter extends TimerTask { + // get an instance of logger + private Logger logger = FlexLogger.getLogger(DesignationWaiter.class); + private List<DroolsSessionEntity> sessions = null; + + public List<DroolsSessionEntity> getSessions(){ + if(sessions != null){ + return sessions; + } + return new LinkedList<DroolsSessionEntity>(); + } + public void run() { + try{ + logger.debug + //System.out.println + ("DesignatedWaiter.run: Entering"); + + // just here initially so code still works + if (pdpsConnector == null) { + waitTimerLastRunDate = new Date(); + logger.info("DesignatedWaiter.run (pdpsConnector==null) waitTimerLastRunDate = " + waitTimerLastRunDate); + + return; + } + + synchronized (designationWaiterLock) { + + logger.debug + //System.out.println + ("DesignatedWaiter.run: Entering synchronized block"); + + checkUpdateWorkerTimer(); + + //It is possible that multiple PDPs are designated lead. So, we will make a list of all designated + //PDPs and then decide which one really should be designated at the end. + ArrayList<DroolsPdp> listOfDesignated = new ArrayList<DroolsPdp>(); + + Collection<DroolsPdp> pdps = pdpsConnector.getDroolsPdps(); + DroolsPdp designatedPdp = null; + DroolsPdp lowestPriorityPdp = null; + + logger.debug + //System.out.println + ("DesignatedWaiter.run: pdps.size=" + + pdps.size()); + + //This is only true if all designated PDPs have failed + boolean designatedPdpHasFailed = pdpsConnector.hasDesignatedPdpFailed(pdps); + logger.debug + //System.out.println + ("DesignatedWaiter.run: designatedPdpHasFailed=" + + designatedPdpHasFailed); + for (DroolsPdp pdp : pdps) { + logger.debug + //System.out.println + ("DesignatedWaiter.run: evaluating pdp ID: " + pdp.getPdpId()); + + /* + * Note: side effect of isPdpCurrent is that any stale but + * designated PDPs will be marked as un-designated. + */ + boolean isCurrent = pdpsConnector.isPdpCurrent(pdp); + + /* + * We can't use stateManagement.getStandbyStatus() here, because + * we need the standbyStatus, not for this PDP, but for the PDP + * being processed by this loop iteration. + */ + String standbyStatus = stateManagement.getStandbyStatus(pdp.getPdpId()); + if(standbyStatus==null){ + // Treat this case as a cold standby -- if we + // abort here, no sessions will be created in a + // single-node test environment. + standbyStatus = StateManagement.COLD_STANDBY; + } + + logger.debug + //System.out.println + ("DesignatedWaiter.run: PDP=" + + pdp.getPdpId() + ", isCurrent=" + isCurrent); + + /* + * There are 4 combinations of isDesignated and isCurrent. We will examine each one in-turn + * and evaluate the each pdp in the list of pdps against each combination. + * + * This is the first combination of isDesignated and isCurrent + */ + if (pdp.isDesignated() && isCurrent) { + //It is current, but it could have a standbystatus=coldstandby / hotstandby + //If so, we need to stand it down and demote it + if(!standbyStatus.equals(StateManagement.PROVIDING_SERVICE)){ + if(pdp.getPdpId().equals(myPdp.getPdpId())){ + logger.debug + //System.out.println + ("\n\nDesignatedWaiter.run: myPdp " + myPdp.getPdpId() + " is current and designated, " + + "butstandbystatus is not providingservice. " + + " Executing stateManagement.demote()" + "\n\n"); + // So, we must demote it + try { + //Keep the order like this. StateManagement is last since it triggers controller shutdown + //This will change isDesignated and it can enter another if(combination) below + pdpsConnector.standDownPdp(pdp.getPdpId()); + myPdp.setDesignated(false); + isDesignated = false; + if(!(standbyStatus.equals(StateManagement.HOT_STANDBY) || + standbyStatus.equals(StateManagement.COLD_STANDBY))){ + /* + * Only demote it if it appears it has not already been demoted. Don't worry + * about synching with the topic endpoint states. That is done by the + * refreshStateAudit + */ + stateManagement.demote(); + } + //update the standbystatus to check in a later combination of isDesignated and isCurrent + standbyStatus=stateManagement.getStandbyStatus(pdp.getPdpId()); + } catch (Exception e) { + logger.error + //System.out.println + ("DesignatedWaiter.run: myPdp: " + myPdp.getPdpId() + " Caught Exception attempting to demote myPdp'" + + myPdp.getPdpId() + + "', message=" + + e.getMessage()); + System.out.println(new Date() + " DesignatedWaiter.run: caught unexpected exception " + + "from stateManagement.demote()"); + e.printStackTrace(); + } + }else{ + // Don't demote a remote PDP that is current. It should catch itself + logger.debug + //System.out.println + ("\n\nDesignatedWaiter.run: myPdp " + myPdp.getPdpId() + " is current and designated, " + + "but standbystatus is not providingservice. " + + " Cannot execute stateManagement.demote() since it it is not myPdp\n\n"); + } + + }else{ + // If we get here, it is ok to be on the list + logger.debug + //System.out.println + ("DesignatedWaiter.run: PDP=" + + pdp.getPdpId() + + " is designated, current and " + standbyStatus +". Noting PDP as designated. standbyStatus=" + standbyStatus); + listOfDesignated.add(pdp); + } + + + } + + + /* + * The second combination of isDesignated and isCurrent + * + * PDP is designated but not current; it has failed. So we stand it down (it doesn't matter what + * its standbyStatus is). None of these go on the list. + */ + if (pdp.isDesignated() && !isCurrent) { + logger.info + //System.out.println + ("INFO: DesignatedWaiter.run: PDP=" + + pdp.getPdpId() + + " is currently designated but is not current; it has failed. Standing down. standbyStatus=" + standbyStatus); + + /* + * Changes designated to 0 but it is still potentially providing service + * Will affect isDesignated, so, it can enter an if(combination) below + */ + pdpsConnector.standDownPdp(pdp.getPdpId()); + + //need to change standbystatus to coldstandby + if (pdp.getPdpId().equals(myPdp.getPdpId())){ + logger.debug + //System.out.println + ("\n\nDesignatedWaiter.run: myPdp " + myPdp.getPdpId() + " is not Current. " + + " Executing stateManagement.disableFailed()" + "\n\n"); + // We found that myPdp is designated but not current + // So, we must cause it to disableFail + try { + myPdp.setDesignated(false); + //pdpsConnector.setDesignated(myPdp, false);//not needed? + isDesignated = false; + stateManagement.disableFailed(); + //stateManagement.demote(); + } catch (Exception e) { + logger.error + //System.out.println + ("DesignatedWaiter.run: myPdp: " + myPdp.getPdpId() + " Caught Exception attempting to disableFail myPdp'" + + myPdp.getPdpId() + + "', message=" + + e.getMessage()); + System.out.println(new Date() + " DesignatedWaiter.run: caught unexpected exception " + + "from stateManagement.disableFailed()"); + e.printStackTrace(); + } + } else { //it is a remote PDP that is failed + logger.debug + //System.out.println + ("\n\nDesignatedWaiter.run: PDP " + pdp.getPdpId() + " is not Current. " + + " Executing stateManagement.disableFailed(otherResourceName)" + "\n\n"); + // We found a PDP is designated but not current + // We already called standdown(pdp) which will change designated to false + // Now we need to disableFail it to get its states in synch. The standbyStatus + // should equal coldstandby + try { + stateManagement.disableFailed(pdp.getPdpId()); + //stateManagement.demote(pdp.getPdpId()); + } catch (Exception e) { + logger.error + //System.out.println + ("DesignatedWaiter.run: for PDP" + pdp.getPdpId() + + " Caught Exception attempting to disableFail(" + pdp.getPdpId() + ")'" + + pdp.getPdpId() + + "', message=" + + e.getMessage()); + System.out.println(new Date() + " DesignatedWaiter.run: caught unexpected exception " + + "from stateManagement.disableFailed()"); + e.printStackTrace(); + } + + } + continue; //we are not going to do anything else with this pdp + } + + /* + * The third combination of isDesignated and isCurrent + * /* + * If a PDP is not currently designated but is providing service (erroneous, but recoverable) or hot standby + * we can add it to the list of possible designated if all the designated have failed + */ + if (!pdp.isDesignated() && isCurrent){ + if(!(standbyStatus.equals(StateManagement.HOT_STANDBY) || + standbyStatus.equals(StateManagement.COLD_STANDBY))){ + logger.info("\n\nDesignatedWaiter.run: PDP " + pdp.getPdpId() + + " is NOT designated but IS current and" + + " has a standbystatus=" + standbyStatus); + // Since it is current, we assume it can adjust its own state. + // We will demote if it is myPdp + if(pdp.getPdpId().equals(myPdp.getPdpId())){ + //demote it + logger.info("DesignatedWaiter.run: PDP " + pdp.getPdpId() + " going to " + + "setDesignated = false and calling stateManagement.demote"); + try { + //Keep the order like this. StateManagement is last since it triggers controller shutdown + pdpsConnector.setDesignated(myPdp, false); + myPdp.setDesignated(false); + isDesignated = false; + //This is definitely not a redundant call. It is attempting to correct a problem + stateManagement.demote(); + //recheck the standbystatus + standbyStatus = stateManagement.getStandbyStatus(pdp.getPdpId()); + } catch (Exception e) { + logger.error + //System.out.println + ("DesignatedWaiter.run: myPdp: " + myPdp.getPdpId() + " Caught Exception attempting to demote myPdp'" + + myPdp.getPdpId() + + "', message=" + + e.getMessage()); + System.out.println(new Date() + " DesignatedWaiter.run: caught unexpected exception " + + "from stateManagement.demote()"); + e.printStackTrace(); + } + + } + } + if(standbyStatus.equals(StateManagement.HOT_STANDBY) && designatedPdpHasFailed){ + //add it to the list + logger.info + //System.out.println + ("INFO: DesignatedWaiter.run: PDP=" + pdp.getPdpId() + + " is not designated but is " + standbyStatus + " and designated PDP has failed. standbyStatus=" + + standbyStatus); + logger.info + //System.out.println + ("DesignatedWaiter.run: Designating PDP=" + pdp.getPdpId()); + listOfDesignated.add(pdp); + } + continue; //done with this one + } + + /* + * The fourth combination of isDesignated and isCurrent + * + * We are not going to put any of these on the list since it appears they have failed. + + * + */ + if(!pdp.isDesignated() && !isCurrent) { + logger.info + //System.out.println + ("INFO: DesignatedWaiter.run: PDP=" + + pdp.getPdpId() + ", designated=" + + pdp.isDesignated() + ", current=" + + isCurrent + + ", designatedPdpHasFailed=" + + designatedPdpHasFailed + + ", standbyStatus=" + standbyStatus); + if(!standbyStatus.equals(StateManagement.COLD_STANDBY)){ + //stand it down + //disableFail it + pdpsConnector.standDownPdp(pdp.getPdpId()); + if(pdp.getPdpId().equals(myPdp.getPdpId())){ + /* + * I don't actually know how this condition could happen, but if it did, we would want + * to declare it failed. + */ + logger.debug + //System.out.println + ("\n\nDesignatedWaiter.run: myPdp " + myPdp.getPdpId() + " is !current and !designated, " + + " Executing stateManagement.disableFailed()" + "\n\n"); + // So, we must disableFail it + try { + //Keep the order like this. StateManagement is last since it triggers controller shutdown + myPdp.setDesignated(false); + isDesignated = false; + stateManagement.disableFailed(); + //stateManagement.demote(); + } catch (Exception e) { + logger.error + //System.out.println + ("DesignatedWaiter.run: myPdp: " + myPdp.getPdpId() + " Caught Exception attempting to disableFail myPdp'" + + myPdp.getPdpId() + + "', message=" + + e.getMessage()); + System.out.println(new Date() + " DesignatedWaiter.run: caught unexpected exception " + + "from stateManagement.disableFailed()"); + e.printStackTrace(); + } + }else{//it is remote + logger.debug + //System.out.println + ("\n\nDesignatedWaiter.run: myPdp " + myPdp.getPdpId() + " is !current and !designated, " + + " Executing stateManagement.disableFailed(" + pdp.getPdpId() + ")" + "\n\n"); + // We already called standdown(pdp) which will change designated to false + // Now we need to disableFail it to get its states in sync. StandbyStatus = coldstandby + try { + stateManagement.disableFailed(pdp.getPdpId()); + //stateManagement.demote(pdp.getPdpId()); + } catch (Exception e) { + logger.error + //System.out.println + ("DesignatedWaiter.run: for PDP" + pdp.getPdpId() + + " Caught Exception attempting to disableFail(" + pdp.getPdpId() + ")'" + + pdp.getPdpId() + + "', message=" + + e.getMessage()); + System.out.println(new Date() + " DesignatedWaiter.run: caught unexpected exception " + + "from stateManagement.disableFailed()"); + e.printStackTrace(); + } + } + } + } + + + } // end pdps loop + + /* + * We have checked the four combinations of isDesignated and isCurrent. Where appropriate, + * we added the PDPs to the potential list of designated pdps + * Check if listOfDesignated is empty, has one entry or has multiple entries + * If it has multiple designated PDPs, then we must determine if myPdp is on the list and if + * it is the lowest priority. If it is on the list and it is not the lowest + * priority, it must be demoted. Then, we must find the lowest priority + * PDP so we can get the right list of sessions + */ + //we need to give priority to pdps on the same site that is currently being used + + + //we need to figure out the last pdp that was the primary so we can get the last site name and the last session numbers + DroolsPdp mostRecentPrimary = new DroolsPdpImpl(null, true, 1, new Date(0)); + mostRecentPrimary.setSiteName(null); + for(DroolsPdp pdp : pdps){ + if(pdp.getDesignatedDate().compareTo(mostRecentPrimary.getDesignatedDate()) > 0){ + mostRecentPrimary = pdp; + } + } + + if(listOfDesignated.size() > 1){ + logger.debug + //System.out.println + ("DesignatedWaiter.run: myPdp: " + myPdp.getPdpId() + " listOfDesignated.size(): " + listOfDesignated.size()); + DroolsPdp rejectedPdp = null; + DroolsPdp lowestPrioritySameSite = null; + DroolsPdp lowestPriorityDifferentSite = null; + for(DroolsPdp pdp : listOfDesignated){ + // We need to determine if another PDP is the lowest priority + if(nullSafeEquals(pdp.getSiteName(),mostRecentPrimary.getSiteName())){ + if(lowestPrioritySameSite == null){ + if(lowestPriorityDifferentSite != null){ + rejectedPdp = lowestPriorityDifferentSite; + } + lowestPrioritySameSite = pdp; + }else{ + if(pdp.getPdpId().equals((lowestPrioritySameSite.getPdpId()))){ + continue;//nothing to compare + } + if(pdp.comparePriority(lowestPrioritySameSite) <0){ + logger.debug + //System.out.println + ("\nDesignatedWaiter.run: myPdp" + myPdp.getPdpId() + " listOfDesignated pdp ID: " + pdp.getPdpId() + + " has lower priority than pdp ID: " + lowestPrioritySameSite.getPdpId()); + + //we need to reject lowestPrioritySameSite + rejectedPdp = lowestPrioritySameSite; + lowestPrioritySameSite = pdp; + } else{ + //we need to reject pdp and keep lowestPrioritySameSite + logger.debug + //System.out.println + ("\nDesignatedWaiter.run: myPdp" + myPdp.getPdpId() + " listOfDesignated pdp ID: " + pdp.getPdpId() + + " has higher priority than pdp ID: " + lowestPrioritySameSite.getPdpId()); + rejectedPdp = pdp; + } + } + } else{ + if(lowestPrioritySameSite != null){ + //if we already have a candidate for same site, we don't want to bother with different sites + rejectedPdp = pdp; + } else{ + if(lowestPriorityDifferentSite == null){ + lowestPriorityDifferentSite = pdp; + continue; + } + if(pdp.getPdpId().equals((lowestPriorityDifferentSite.getPdpId()))){ + continue;//nothing to compare + } + if(pdp.comparePriority(lowestPriorityDifferentSite) <0){ + logger.debug + //System.out.println + ("\nDesignatedWaiter.run: myPdp" + myPdp.getPdpId() + " listOfDesignated pdp ID: " + pdp.getPdpId() + + " has lower priority than pdp ID: " + lowestPriorityDifferentSite.getPdpId()); + + //we need to reject lowestPriorityDifferentSite + rejectedPdp = lowestPriorityDifferentSite; + lowestPriorityDifferentSite = pdp; + } else{ + //we need to reject pdp and keep lowestPriorityDifferentSite + logger.debug + //System.out.println + ("\nDesignatedWaiter.run: myPdp" + myPdp.getPdpId() + " listOfDesignated pdp ID: " + pdp.getPdpId() + + " has higher priority than pdp ID: " + lowestPriorityDifferentSite.getPdpId()); + rejectedPdp = pdp; + } + } + } + // If the rejectedPdp is myPdp, we need to stand it down and demote it. Each pdp is responsible + // for demoting itself + if(rejectedPdp != null && nullSafeEquals(rejectedPdp.getPdpId(),myPdp.getPdpId())){ + logger.debug + //System.out.println + ("\n\nDesignatedWaiter.run: myPdp: " + myPdp.getPdpId() + " listOfDesignated myPdp ID: " + myPdp.getPdpId() + + " is NOT the lowest priority. Executing stateManagement.demote()" + "\n\n"); + // We found that myPdp is on the listOfDesignated and it is not the lowest priority + // So, we must demote it + try { + //Keep the order like this. StateManagement is last since it triggers controller shutdown + myPdp.setDesignated(false); + pdpsConnector.setDesignated(myPdp, false); + isDesignated = false; + String standbyStatus = stateManagement.getStandbyStatus(); + if(!(standbyStatus.equals(StateManagement.HOT_STANDBY) || + standbyStatus.equals(StateManagement.COLD_STANDBY))){ + /* + * Only call demote if it is not already in the right state. Don't worry about + * synching the lower level topic endpoint states. That is done by the + * refreshStateAudit. + */ + stateManagement.demote(); + } + } catch (Exception e) { + myPdp.setDesignated(false); + pdpsConnector.setDesignated(myPdp, false); + isDesignated = false; + logger.error + //System.out.println + ("DesignatedWaiter.run: myPdp: " + myPdp.getPdpId() + " Caught Exception attempting to demote myPdp'" + + myPdp.getPdpId() + + "', message=" + + e.getMessage()); + System.out.println(new Date() + " DesignatedWaiter.run: caught unexpected exception " + + "from stateManagement.demote()"); + e.printStackTrace(); + } + } + } //end: for(DroolsPdp pdp : listOfDesignated) + if(lowestPrioritySameSite != null){ + lowestPriorityPdp = lowestPrioritySameSite; + } else { + lowestPriorityPdp = lowestPriorityDifferentSite; + } + //now we have a valid value for lowestPriorityPdp + logger.debug + //System.out.println + ("\n\nDesignatedWaiter.run: myPdp: " + myPdp.getPdpId() + " listOfDesignated found the LOWEST priority pdp ID: " + + lowestPriorityPdp.getPdpId() + + " It is now the designatedPpd from the perspective of myPdp ID: " + myPdp + "\n\n"); + designatedPdp = lowestPriorityPdp; + this.sessions = mostRecentPrimary.getSessions(); + + } else if(listOfDesignated.isEmpty()){ + logger.debug + //System.out.println + ("\nDesignatedWaiter.run: myPdp: " + myPdp.getPdpId() + " listOfDesignated is: EMPTY."); + designatedPdp = null; + } else{ //only one in listOfDesignated + logger.debug + //System.out.println + ("\nDesignatedWaiter.run: myPdp: " + myPdp.getPdpId() + " listOfDesignated has ONE entry. PDP ID: " + + listOfDesignated.get(0).getPdpId()); + designatedPdp = listOfDesignated.get(0); + this.sessions = mostRecentPrimary.getSessions(); + } + + + if (designatedPdp == null) { + logger.warn + //System.out.println + ("WARNING: DesignatedWaiter.run: No viable PDP found to be Designated. designatedPdp still null."); + // Just to be sure the parameters are correctly set + myPdp.setDesignated(false); + pdpsConnector.setDesignated(myPdp,false); + isDesignated = false; + + waitTimerLastRunDate = new Date(); + logger.info("DesignatedWaiter.run (designatedPdp == null) waitTimerLastRunDate = " + waitTimerLastRunDate); + + return; + + } else if (designatedPdp.getPdpId().equals(myPdp.getPdpId())) { + logger.debug + //System.out.println + ("DesignatedWaiter.run: designatedPdp is PDP=" + myPdp.getPdpId()); + /* + * update function expects myPdp.isDesignated to be true. + */ + try { + //Keep the order like this. StateManagement is last since it triggers controller init + myPdp.setDesignated(true); + pdpsConnector.setDesignated(myPdp, true); + isDesignated = true; + String standbyStatus = stateManagement.getStandbyStatus(); + if(!standbyStatus.equals(StateManagement.PROVIDING_SERVICE)){ + /* + * Only call promote if it is not already in the right state. Don't worry about + * synching the lower level topic endpoint states. That is done by the + * refreshStateAudit. + */ + stateManagement.promote(); + } + } catch (StandbyStatusException e) { + logger.error + //System.out.println + ("ERROR: DesignatedWaiter.run: Caught StandbyStatusException attempting to promote PDP='" + + myPdp.getPdpId() + + "', message=" + + e.getMessage()); + myPdp.setDesignated(false); + pdpsConnector.setDesignated(myPdp,false); + isDesignated = false; + //If you can't promote it, demote it + try { + String standbyStatus = stateManagement.getStandbyStatus(); + if(!(standbyStatus.equals(StateManagement.HOT_STANDBY) || + standbyStatus.equals(StateManagement.COLD_STANDBY))){ + /* + * Only call demote if it is not already in the right state. Don't worry about + * synching the lower level topic endpoint states. That is done by the + * refreshStateAudit. + */ + stateManagement.demote(); + } + } catch (Exception e1) { + logger.error + //System.out.println + ("ERROR: DesignatedWaiter.run: Caught StandbyStatusException attempting to promote then demote PDP='" + + myPdp.getPdpId() + + "', message=" + + e1.getMessage()); + System.out.println(new Date() + " DesignatedWaiter.run: caught unexpected exception " + + "from stateManagement.demote()"); + e1.printStackTrace(); + } + + } catch (Exception e) { + logger.error + //System.out.println + ("ERROR: DesignatedWaiter.run: Caught Exception attempting to promote PDP='" + + myPdp.getPdpId() + + "', message=" + + e.getMessage()); + myPdp.setDesignated(false); + pdpsConnector.setDesignated(myPdp,false); + isDesignated = false; + //If you can't promote it, demote it + try { + String standbyStatus = stateManagement.getStandbyStatus(); + if(!(standbyStatus.equals(StateManagement.HOT_STANDBY) || + standbyStatus.equals(StateManagement.COLD_STANDBY))){ + /* + * Only call demote if it is not already in the right state. Don't worry about + * synching the lower level topic endpoint states. That is done by the + * refreshStateAudit. + */ + stateManagement.demote(); + } + } catch (Exception e1) { + logger.error + //System.out.println + ("ERROR: DesignatedWaiter.run: Caught StandbyStatusException attempting to promote then demote PDP='" + + myPdp.getPdpId() + + "', message=" + + e1.getMessage()); + System.out.println(new Date() + " DesignatedWaiter.run: caught unexpected exception " + + "from stateManagement.demote()"); + e1.printStackTrace(); + } + + } + waitTimerLastRunDate = new Date(); + logger.info("DesignatedWaiter.run (designatedPdp.getPdpId().equals(myPdp.getPdpId())) waitTimerLastRunDate = " + waitTimerLastRunDate); + + return; + } + isDesignated = false; + + } // end synchronized + + logger.debug + //System.out.println + ("DesignatedWaiter.run: myPdp: " + myPdp.getPdpId() + "; Returning, isDesignated=" + isDesignated); + + Date tmpDate = new Date(); + logger.info("DesignatedWaiter.run (end of run) waitTimerLastRunDate = " + tmpDate); + + waitTimerLastRunDate = tmpDate; + + }catch(Exception e){ + logger.error("DesignatedWaiter.run caught an unexpected exception: " + e); + System.out.println(new Date() + " DesignatedWaiter.run: caught unexpected exception"); + e.printStackTrace(); + } + } // end run + } + + private class TimerUpdateClass extends TimerTask{ + + @Override + public void run() { + try{ + logger.info("TimerUpdateClass.run: entry"); + checkWaitTimer(); + synchronized(pdpsConnectorLock){ + + myPdp.setUpdatedDate(new Date()); + if(myPdp.isDesignated()){ + myPdp.setDesignatedDate(new Date()); + } + pdpsConnector.update(myPdp); + + Date tmpDate = new Date(); + logger.info("TimerUpdateClass.run: updateWorkerLastRunDate = " + tmpDate); + + updateWorkerLastRunDate = tmpDate; + } + logger.info("TimerUpdateClass.run.exit"); + }catch(Exception e){ + logger.error("TimerUpdateClass.run caught an unexpected exception: " + e); + System.out.println(new Date() + " TimerUpdateClass.run caught an unexpected exception"); + e.printStackTrace(); + } + } + } + @Override + public void checkThreadStatus() { + checkUpdateWorkerTimer(); + checkWaitTimer(); + } + + private void checkUpdateWorkerTimer(){ + synchronized(checkUpdateWorkerLock){ + try{ + logger.debug("checkUpdateWorkerTimer: entry"); + Date now = new Date(); + long nowMs = now.getTime(); + long updateWorkerMs = updateWorkerLastRunDate.getTime(); + //give it 2 second cushion + if((nowMs - updateWorkerMs) > pdpCheckInterval + 2000){ + logger.error("checkUpdateWorkerTimer: nowMs - updateWorkerMs = " + (nowMs - updateWorkerMs) + + ", exceeds pdpCheckInterval + 2000 = " + (pdpCheckInterval + 2000) + " Will reschedule updateWorker timer"); + + try{ + updateWorker.cancel(); + // Recalculate the time because this is a synchronized section and the thread could have + // been blocked. + now = new Date(); + nowMs = now.getTime(); + updateWorker = new Timer(); + // reset the updateWorkerLastRunDate + updateWorkerLastRunDate = new Date(nowMs + 100); + //execute the first time in 100 ms + updateWorker.scheduleAtFixedRate(new TimerUpdateClass(), 100, pdpCheckInterval); + logger.info("checkUpdateWorkerTimer: Scheduling updateWorker timer to start in 100 ms "); + }catch(Exception e){ + logger.error("checkUpdateWorkerTimer: Caught unexpected Exception: " + e); + System.out.println(new Date() + " checkUpdateWorkerTimer caught an unexpected exception"); + e.printStackTrace(); + // Recalculate the time because this is a synchronized section and the thread could have + // been blocked. + now = new Date(); + nowMs = now.getTime(); + updateWorker = new Timer(); + updateWorkerLastRunDate = new Date(nowMs + 100); + updateWorker.scheduleAtFixedRate(new TimerUpdateClass(), 100, pdpCheckInterval); + logger.info("checkUpdateWorkerTimer: Attempting to schedule updateWorker timer in 100 ms"); + } + + } + logger.debug("checkUpdateWorkerTimer: exit"); + }catch(Exception e){ + logger.error("checkUpdateWorkerTimer: caught unexpected exception: " + e); + System.out.println(new Date() + " checkUpdateWorkerTimer - top level - caught an unexpected exception"); + e.printStackTrace(); + } + } + } + + private void checkWaitTimer(){ + synchronized(checkWaitTimerLock){ + try{ + logger.debug("checkWaitTimer: entry"); + Date now = new Date(); + long nowMs = now.getTime(); + long waitTimerMs = waitTimerLastRunDate.getTime(); + + //give it 2 times leeway + if((nowMs - waitTimerMs) > 2*pdpUpdateInterval){ + logger.error("checkWaitTimer: nowMs - waitTimerMs = " + (nowMs - waitTimerMs) + + ", exceeds pdpUpdateInterval + 2000 = " + (2*pdpUpdateInterval) + " Will reschedule waitTimer timer"); + + + try{ + // Recalculate since the thread could have been stalled on the synchronize() + nowMs = (new Date()).getTime(); + // Time to the start of the next pdpUpdateInterval multiple + long startMs = getDWaiterStartMs(); + waitTimer.cancel(); + designationWaiter = new DesignationWaiter(); + waitTimer = new Timer(); + waitTimerLastRunDate = new Date(nowMs + startMs); + waitTimer.scheduleAtFixedRate(designationWaiter, startMs, pdpUpdateInterval); + logger.info("checkWaitTimer: Scheduling waitTimer timer to start in " + startMs + " ms"); + }catch(Exception e){ + logger.error("checkWaitTimer: Caught unexpected Exception: " + e); + System.out.println(new Date() + " checkWaitTimer caught an unexpected exception"); + e.printStackTrace(); + // Recalculate since the thread could have been stalled on the synchronize() + nowMs = (new Date()).getTime(); + // Time to the start of the next pdpUpdateInterval multiple + long startMs = getDWaiterStartMs(); + designationWaiter = new DesignationWaiter(); + waitTimer = new Timer(); + waitTimerLastRunDate = new Date(nowMs + startMs); + waitTimer.scheduleAtFixedRate(designationWaiter, startMs, pdpUpdateInterval); + logger.info("checkWaitTimer: Scheduling waitTimer timer in " + startMs + " ms"); + } + + } + logger.debug("checkWaitTimer: exit"); + }catch(Exception e){ + logger.error("checkWaitTimer: caught unexpected exception: " + e); + System.out.println(new Date() + " checkWaitTimer caught an unexpected exception"); + e.printStackTrace(); + } + } + } + + private long getDWaiterStartMs(){ + Date now = new Date(); + + // Retrieve the ms since the epoch + long nowMs = now.getTime(); + + // Time since the end of the last pdpUpdateInterval multiple + long nowModMs = nowMs % pdpUpdateInterval; + + // Time to the start of the next pdpUpdateInterval multiple + long startMs = pdpUpdateInterval - nowModMs; + + // Give the start time a minimum of a 5 second cushion + if(startMs < 5000){ + // Start at the beginning of following interval + startMs = pdpUpdateInterval + startMs; + } + return startMs; + } + + private boolean nullSafeEquals(Object one, Object two){ + if(one == null && two == null){ + return true; + } + if(one != null && two != null){ + return one.equals(two); + } + return false; + } +} diff --git a/policy-persistence/src/main/java/org/openecomp/policy/drools/persistence/DroolsPersistenceProperties.java b/policy-persistence/src/main/java/org/openecomp/policy/drools/persistence/DroolsPersistenceProperties.java new file mode 100644 index 00000000..63af53cb --- /dev/null +++ b/policy-persistence/src/main/java/org/openecomp/policy/drools/persistence/DroolsPersistenceProperties.java @@ -0,0 +1,64 @@ +/*- + * ============LICENSE_START======================================================= + * policy-persistence + * ================================================================================ + * 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.persistence; + +import java.util.Properties; + +import org.openecomp.policy.common.logging.flexlogger.FlexLogger; +import org.openecomp.policy.common.logging.flexlogger.Logger; + +public class DroolsPersistenceProperties { + // get an instance of logger + private static Logger logger = FlexLogger.getLogger(DroolsPersistenceProperties.class); + /* + * droolsPersistence.properties parameter key values + */ + public static final String DB_DRIVER = "javax.persistence.jdbc.driver"; + public static final String DB_DATA_SOURCE = "hibernate.dataSource"; + public static final String DB_URL = "javax.persistence.jdbc.url"; + public static final String DB_USER = "javax.persistence.jdbc.user"; + public static final String DB_PWD = "javax.persistence.jdbc.password"; + + private static Properties properties = null; + /* + * Initialize the parameter values from the droolsPersitence.properties file values + * + * This is designed so that the Properties object is obtained from the droolsPersistence.properties + * file and then is passed to this method to initialize the value of the parameters. + * This allows the flexibility of JUnit tests using getProperties(filename) to get the + * properties while runtime methods can use getPropertiesFromClassPath(filename). + * + */ + public static void initProperties (Properties prop){ + logger.info("DroolsPersistenceProperties.initProperties(Properties): entry"); + logger.info("\n\nDroolsPersistenceProperties.initProperties: Properties = \n" + prop + "\n\n"); + + properties = prop; + } + + public static String getProperty(String key){ + return properties.getProperty(key); + } + + public static Properties getProperties() { + return properties; + } +} diff --git a/policy-persistence/src/main/java/org/openecomp/policy/drools/persistence/DroolsSession.java b/policy-persistence/src/main/java/org/openecomp/policy/drools/persistence/DroolsSession.java new file mode 100644 index 00000000..21a480d9 --- /dev/null +++ b/policy-persistence/src/main/java/org/openecomp/policy/drools/persistence/DroolsSession.java @@ -0,0 +1,31 @@ +/*- + * ============LICENSE_START======================================================= + * policy-persistence + * ================================================================================ + * 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.persistence; + +public interface DroolsSession { + + public String getPdpId(); + public void setPdpId(String pdpId); + public String getSessionName(); + public void setSessionName(String sessionName); + public long getSessionId(); + public void setSessionId(long sessionId); +} diff --git a/policy-persistence/src/main/java/org/openecomp/policy/drools/persistence/DroolsSessionEntity.java b/policy-persistence/src/main/java/org/openecomp/policy/drools/persistence/DroolsSessionEntity.java new file mode 100644 index 00000000..89e310f0 --- /dev/null +++ b/policy-persistence/src/main/java/org/openecomp/policy/drools/persistence/DroolsSessionEntity.java @@ -0,0 +1,90 @@ +/*- + * ============LICENSE_START======================================================= + * policy-persistence + * ================================================================================ + * 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.persistence; + +import java.io.Serializable; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.ManyToOne; +@Entity +public class DroolsSessionEntity implements Serializable, DroolsSession { + @Id + @Column(name="pdpId", nullable=false) + private String pdpId="-1"; + @Id + @Column(name="sessionName", nullable=false) + private String sessionName="-1"; + + @Column(name="sessionId", nullable=false) + private long sessionId=-1L; + + @ManyToOne + private DroolsPdpEntity pdpEntity; + public DroolsSessionEntity(){ + + } + @Override + public String getPdpId() { + return pdpId; + } + @Override + public void setPdpId(String pdpId) { + this.pdpId = pdpId; + } + @Override + public String getSessionName() { + return sessionName; + } + @Override + public void setSessionName(String sessionName) { + this.sessionName = sessionName; + } + @Override + public long getSessionId() { + return sessionId; + } + + @Override + public void setSessionId(long sessionId) { + this.sessionId = sessionId; + } + public void setPdpEntity(DroolsPdpEntity pdpEntity){ + this.pdpEntity = pdpEntity; + } + @Override + public boolean equals(Object other){ + if(other instanceof DroolsSession){ + return this.getPdpId().equals(((DroolsSession)other).getPdpId()) && this.getSessionName().equals(((DroolsSession)other).getSessionName()); + }else{ + return false; + } + } + + @Override + public int hashCode(){ + String combinedId = this.getPdpId().concat(":").concat(this.getSessionName()); + return combinedId.hashCode(); + } + + +} diff --git a/policy-persistence/src/main/java/org/openecomp/policy/drools/persistence/JpaDroolsPdpsConnector.java b/policy-persistence/src/main/java/org/openecomp/policy/drools/persistence/JpaDroolsPdpsConnector.java new file mode 100644 index 00000000..ac9255a2 --- /dev/null +++ b/policy-persistence/src/main/java/org/openecomp/policy/drools/persistence/JpaDroolsPdpsConnector.java @@ -0,0 +1,688 @@ +/*- + * ============LICENSE_START======================================================= + * policy-persistence + * ================================================================================ + * 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.persistence; + +import java.util.Collection; +import java.util.Date; +import java.util.LinkedList; +import java.util.List; + +import javax.persistence.EntityManager; +import javax.persistence.EntityManagerFactory; +import javax.persistence.LockModeType; +import javax.persistence.Query; + +import org.openecomp.policy.drools.core.IntegrityMonitorProperties; +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 JpaDroolsPdpsConnector implements DroolsPdpsConnector { + + // get an instance of logger + private static Logger logger = FlexLogger.getLogger(JpaDroolsPdpsConnector.class); + private EntityManagerFactory emf; + + + //not sure if we want to use the same entity manager factory for drools session and pass it in here, or create a new one + public JpaDroolsPdpsConnector(EntityManagerFactory emf){ + this.emf = emf; + } + @Override + public Collection<DroolsPdp> getDroolsPdps() { + //return a list of all the DroolsPdps in the database + EntityManager em = emf.createEntityManager(); + try { + em.getTransaction().begin(); + Query droolsPdpsListQuery = em.createQuery("SELECT p FROM DroolsPdpEntity p"); + List<?> droolsPdpsList = droolsPdpsListQuery.setLockMode(LockModeType.PESSIMISTIC_READ).getResultList(); + LinkedList<DroolsPdp> droolsPdpsReturnList = new LinkedList<DroolsPdp>(); + for(Object o : droolsPdpsList){ + if(o instanceof DroolsPdp){ + //Make sure it is not a cached version + em.refresh((DroolsPdpEntity)o); + droolsPdpsReturnList.add((DroolsPdp)o); + if (logger.isDebugEnabled()) { + DroolsPdp droolsPdp = (DroolsPdp)o; + logger.debug("getDroolsPdps: PDP=" + droolsPdp.getPdpId() + + ", isDesignated=" + droolsPdp.isDesignated() + + ", updatedDate=" + droolsPdp.getUpdatedDate() + + ", priority=" + droolsPdp.getPriority()); + } + } + } + try{ + em.getTransaction().commit(); + }catch(Exception e){ + logger.error + (MessageCodes.EXCEPTION_ERROR, e,"Cannot commit getDroolsPdps() transaction"); + } + return droolsPdpsReturnList; + } finally { + cleanup(em, "getDroolsPdps"); + } + } + + private boolean nullSafeEquals(Object one, Object two){ + if(one == null && two == null){ + return true; + } + if(one != null && two != null){ + return one.equals(two); + } + return false; + } + + @Override + public void update(DroolsPdp pdp) { + + if (logger.isDebugEnabled()) { + logger.debug("update: Entering, pdpId=" + pdp.getPdpId()); + } + + //this is to update our own pdp in the database + EntityManager em = emf.createEntityManager(); + try { + em.getTransaction().begin(); + Query droolsPdpsListQuery = em.createQuery("SELECT p FROM DroolsPdpEntity p WHERE p.pdpId=:pdpId"); + droolsPdpsListQuery.setParameter("pdpId", pdp.getPdpId()); + List<?> droolsPdpsList = droolsPdpsListQuery.setLockMode(LockModeType.PESSIMISTIC_WRITE).getResultList(); + //em.getTransaction().begin(); + DroolsPdpEntity droolsPdpEntity; + if(droolsPdpsList.size() == 1 && (droolsPdpsList.get(0) instanceof DroolsPdpEntity)){ + droolsPdpEntity = (DroolsPdpEntity)droolsPdpsList.get(0); + //if(pdp.getSessionId() < 0){ + //if its less than 0, then we know it is not a real session number so we want to save the one that the database has for us, to avoid information loss + //pdp.setSessionId(droolsPdpEntity.getSessionId()); + //} + Date currentDate = new Date(); + long difference = currentDate.getTime()-droolsPdpEntity.getUpdatedDate().getTime(); + //just set some kind of default here + long pdpTimeout = 15000; + try{ + pdpTimeout = Long.parseLong(IntegrityMonitorProperties.getProperty(IntegrityMonitorProperties.PDP_TIMEOUT)); + }catch(Exception e){ + logger.error + (MessageCodes.EXCEPTION_ERROR, e,"Could not get PDP timeout property, using default."); + } + boolean isCurrent = difference<pdpTimeout; + if (logger.isDebugEnabled()) { + logger.debug("update: PDP=" + pdp.getPdpId() + ", isCurrent=" + + isCurrent + ", difference=" + difference + + ", pdpTimeout=" + pdpTimeout + ", designated=" + + droolsPdpEntity.isDesignated()); + } + } else { + if (logger.isDebugEnabled()) { + logger.debug("update: For PDP=" + pdp.getPdpId() + + ", instantiating new DroolsPdpEntity"); + } + droolsPdpEntity = new DroolsPdpEntity(); + em.persist(droolsPdpEntity); + droolsPdpEntity.setPdpId(pdp.getPdpId()); + } + if(droolsPdpEntity.getPriority() != pdp.getPriority()){ + droolsPdpEntity.setPriority(pdp.getPriority()); + } + if(!droolsPdpEntity.getUpdatedDate().equals(pdp.getUpdatedDate())){ + droolsPdpEntity.setUpdatedDate(pdp.getUpdatedDate()); + } + if(!droolsPdpEntity.getDesignatedDate().equals(pdp.getDesignatedDate())){ + droolsPdpEntity.setDesignatedDate(pdp.getDesignatedDate()); + } + if(!nullSafeEquals(droolsPdpEntity.getSiteName(),pdp.getSiteName())){ + droolsPdpEntity.setSiteName(pdp.getSiteName()); + } + List<DroolsSessionEntity> sessionsToAdd = new LinkedList<DroolsSessionEntity>(); + for(DroolsSessionEntity localSession : pdp.getSessions()){ + boolean found = false; + for(DroolsSessionEntity dbSession : droolsPdpEntity.getSessions()){ + if(localSession.equals(dbSession)){ + found = true; + dbSession.setSessionId(localSession.getSessionId()); + } + } + if(!found){ + sessionsToAdd.add(localSession); + } + + } + for(DroolsSessionEntity sessionToAdd : sessionsToAdd){ + em.persist(sessionToAdd); + droolsPdpEntity.getSessions().add(sessionToAdd); + } + + + if(droolsPdpEntity.isDesignated() != pdp.isDesignated()){ + if (logger.isDebugEnabled()) { + logger.debug("update: pdpId=" + pdp.getPdpId() + + ", pdp.isDesignated=" + pdp.isDesignated() + + ", droolsPdpEntity.pdpId=" + + droolsPdpEntity.getPdpId() + + ", droolsPdpEntity.isDesignated=" + + droolsPdpEntity.isDesignated()); + } + droolsPdpEntity.setDesignated(pdp.isDesignated()); + } + em.getTransaction().commit(); + } finally { + cleanup(em, "update"); + } + + if (logger.isDebugEnabled()) { + logger.debug("update: Exiting"); + } + + } + + /* + * Note: A side effect of this boolean method is that if the PDP is designated but not current, the + * droolspdpentity.DESIGNATED column will be set to false (the PDP will be un-designated, i.e. marked as + * being in standby mode) + */ + @Override + public boolean isPdpCurrent(DroolsPdp pdp) { + + boolean isCurrent = isCurrent(pdp); + + EntityManager em = emf.createEntityManager(); + try{ + if(!isCurrent && pdp.isDesignated()){ + em.getTransaction().begin(); + Query droolsPdpsListQuery = em.createQuery("SELECT p FROM DroolsPdpEntity p WHERE p.pdpId=:pdpId"); + droolsPdpsListQuery.setParameter("pdpId", pdp.getPdpId()); + List<?> droolsPdpsList = droolsPdpsListQuery.setLockMode(LockModeType.PESSIMISTIC_WRITE).getResultList(); + if(droolsPdpsList.size() == 1 && droolsPdpsList.get(0) instanceof DroolsPdpEntity){ + if (logger.isDebugEnabled()) { + logger.debug("isPdpCurrent: PDP=" + pdp.getPdpId() + " designated but not current; setting designated to false"); + } + DroolsPdpEntity droolsPdpEntity = (DroolsPdpEntity)droolsPdpsList.get(0); + droolsPdpEntity.setDesignated(false); + em.getTransaction().commit(); + } else { + logger.warn("isPdpCurrent: PDP=" + pdp.getPdpId() + " is designated but not current; however it does not have a DB entry, so cannot set DESIGNATED to false!"); + } + } else { + if (logger.isDebugEnabled()) { + logger.debug("isPdpCurrent: For PDP=" + pdp.getPdpId() + + ", designated=" + + pdp.isDesignated() + ", isCurrent=" + isCurrent); + } + } + }catch(Exception e){ + logger.error + (MessageCodes.EXCEPTION_ERROR, e,"Could not update expired record marked as designated in the database"); + } finally { + cleanup(em, "isPdpCurrent"); + } + return isCurrent; + + } + + @Override + public void setDesignated(DroolsPdp pdp, boolean designated) { + + if (logger.isDebugEnabled()) { + logger.debug("setDesignated: Entering, pdpId='" + pdp.getPdpId() + + "', designated=" + designated); + } + + EntityManager em = null; + try { + em = emf.createEntityManager(); + em.getTransaction().begin(); + Query droolsPdpsListQuery = em + .createQuery("SELECT p FROM DroolsPdpEntity p WHERE p.pdpId=:pdpId"); + droolsPdpsListQuery.setParameter("pdpId", pdp.getPdpId()); + List<?> droolsPdpsList = droolsPdpsListQuery.setLockMode( + LockModeType.PESSIMISTIC_WRITE).getResultList(); + if (droolsPdpsList.size() == 1 + && droolsPdpsList.get(0) instanceof DroolsPdpEntity) { + DroolsPdpEntity droolsPdpEntity = (DroolsPdpEntity) droolsPdpsList + .get(0); + if (logger.isDebugEnabled()) { + logger.debug("setDesignated: PDP=" + pdp.getPdpId() + + " found, designated=" + + droolsPdpEntity.isDesignated() + ", setting to " + + designated); + } + droolsPdpEntity.setDesignated(designated); + em.getTransaction().commit(); + } else { + logger.error("setDesignated: PDP=" + pdp.getPdpId() + + " not in DB; cannot update designation"); + } + } catch (Exception e) { + logger.error("setDesignated: Caught Exception, message='" + + e.getMessage() + "'"); + } finally { + cleanup(em, "setDesignated"); + } + + if (logger.isDebugEnabled()) { + logger.debug("setDesignated: Exiting"); + } + + } + + + @Override + public void standDownPdp(String pdpId) { + + logger.info("standDownPdp: Entering, pdpId='" + pdpId + "'"); + + EntityManager em = null; + try { + /* + * Start transaction. + */ + em = emf.createEntityManager(); + em.getTransaction().begin(); + + /* + * Get droolspdpentity record for this PDP and mark DESIGNATED as + * false. + */ + Query droolsPdpsListQuery = em + .createQuery("SELECT p FROM DroolsPdpEntity p WHERE p.pdpId=:pdpId"); + droolsPdpsListQuery.setParameter("pdpId", pdpId); + List<?> droolsPdpsList = droolsPdpsListQuery.setLockMode( + LockModeType.PESSIMISTIC_WRITE).getResultList(); + DroolsPdpEntity droolsPdpEntity; + if (droolsPdpsList.size() == 1 + && (droolsPdpsList.get(0) instanceof DroolsPdpEntity)) { + droolsPdpEntity = (DroolsPdpEntity) droolsPdpsList.get(0); + droolsPdpEntity.setDesignated(false); + em.persist(droolsPdpEntity); + logger.info("standDownPdp: PDP=" + pdpId + " persisted as non-designated."); + } else { + logger.error("standDownPdp: Missing record in droolspdpentity for pdpId=" + + pdpId + "; cannot stand down PDP"); + } + + /* + * End transaction. + */ + em.getTransaction().commit(); + cleanup(em, "standDownPdp"); + em = null; + + // Keep the election handler in sync with the DB + DroolsPdpsElectionHandler.setMyPdpDesignated(false); + + } catch (Exception e) { + logger.error("standDownPdp: Unexpected Exception attempting to mark DESIGNATED as false for droolspdpentity, pdpId=" + + pdpId + + ". Cannot stand down PDP; message=" + + e.getMessage()); + } finally { + cleanup(em, "standDownPdp"); + } + + logger.info("standDownPdp: Exiting"); + + } + + /* + * Determines whether or not a designated PDP has failed. + * + * Note: The update method, which is run periodically by the + * TimerUpdateClass, will un-designate a PDP that is stale. + */ + @Override + public boolean hasDesignatedPdpFailed(Collection<DroolsPdp> pdps) { + + if (logger.isDebugEnabled()) { + logger.debug("hasDesignatedPdpFailed: Entering, pdps.size()=" + + pdps.size()); + } + + boolean failed = true; + boolean foundDesignatedPdp = false; + + for (DroolsPdp pdp : pdps) { + + /* + * Normally, the update method will un-designate any stale PDP, but + * we check here to see if the PDP has gone stale since the update + * method was run. + * + * Even if we determine that the designated PDP is current, we keep + * going (we don't break), so we can get visibility into the other + * PDPs, when in DEBUG mode. + */ + if (pdp.isDesignated() && isCurrent(pdp)) { + if (logger.isDebugEnabled()) { + logger.debug("hasDesignatedPdpFailed: Designated PDP=" + + pdp.getPdpId() + " is current"); + } + failed = false; + foundDesignatedPdp = true; + } else if (pdp.isDesignated() && !isCurrent(pdp)) { + logger.error("hasDesignatedPdpFailed: Designated PDP=" + + pdp.getPdpId() + " has failed"); + foundDesignatedPdp = true; + } else { + if (logger.isDebugEnabled()) { + logger.debug("hasDesignatedPdpFailed: PDP=" + + pdp.getPdpId() + " is not designated"); + } + } + } + + if (logger.isDebugEnabled()) { + logger.debug("hasDesignatedPdpFailed: Exiting and returning, foundDesignatedPdp=" + + foundDesignatedPdp); + } + return failed; + } + + + private boolean isCurrent(DroolsPdp pdp) { + + if (logger.isDebugEnabled()) { + logger.debug("isCurrent: Entering, pdpId=" + + pdp.getPdpId()); + } + + boolean current = false; + + // Return if the current PDP is considered "current" based on whatever + // time box that may be. + // If the the PDP is not current, we should mark it as not primary in + // the database + Date currentDate = new Date(); + long difference = currentDate.getTime() + - pdp.getUpdatedDate().getTime(); + // just set some kind of default here + long pdpTimeout = 15000; + try { + pdpTimeout = Long.parseLong(IntegrityMonitorProperties + .getProperty(IntegrityMonitorProperties.PDP_TIMEOUT)); + if (logger.isDebugEnabled()) { + logger.debug("isCurrent: pdp.timeout=" + pdpTimeout); + } + } catch (Exception e) { + logger.error + (MessageCodes.EXCEPTION_ERROR, e, + "isCurrent: Could not get PDP timeout property, using default."); + } + current = difference < pdpTimeout; + + if (logger.isDebugEnabled()) { + logger.debug("isCurrent: Exiting, difference=" + + difference + ", pdpTimeout=" + pdpTimeout + + "; returning current=" + current); + } + + return current; + } + + + /* + * Currently this method is only used in a JUnit test environment. Gets a + * PDP record from droolspdpentity table. + */ + @Override + public DroolsPdpEntity getPdp(String pdpId) { + + if (logger.isDebugEnabled()) { + logger.debug("getPdp: Entering and getting PDP with pdpId='" + pdpId + + "'"); + } + + DroolsPdpEntity droolsPdpEntity = null; + + EntityManager em = null; + try { + em = emf.createEntityManager(); + em.getTransaction().begin(); + Query droolsPdpsListQuery = em + .createQuery("SELECT p FROM DroolsPdpEntity p WHERE p.pdpId=:pdpId"); + droolsPdpsListQuery.setParameter("pdpId", pdpId); + List<?> droolsPdpsList = droolsPdpsListQuery.setLockMode( + LockModeType.PESSIMISTIC_WRITE).getResultList(); + if (droolsPdpsList.size() == 1 + && droolsPdpsList.get(0) instanceof DroolsPdpEntity) { + droolsPdpEntity = (DroolsPdpEntity) droolsPdpsList.get(0); + if (logger.isDebugEnabled()) { + logger.debug("getPdp: PDP=" + pdpId + + " found, isDesignated=" + + droolsPdpEntity.isDesignated() + ", updatedDate=" + + droolsPdpEntity.getUpdatedDate() + ", priority=" + + droolsPdpEntity.getPriority()); + } + + // Make sure the droolsPdpEntity is not a cached version + em.refresh(droolsPdpEntity); + + em.getTransaction().commit(); + } else { + logger.error("getPdp: PDP=" + pdpId + " not found!?"); + } + } catch (Exception e) { + logger.error + (MessageCodes.EXCEPTION_ERROR, e,"getPdp: Caught Exception attempting to get PDP, message='" + + e.getMessage() + "'"); + } finally { + cleanup(em, "getPdp"); + } + + if (logger.isDebugEnabled()) { + logger.debug("getPdp: Returning droolsPdpEntity=" + droolsPdpEntity); + } + return droolsPdpEntity; + + } + + /* + * Normally this method should only be used in a JUnit test environment. + * Manually inserts a PDP record in droolspdpentity table. + */ + @Override + public void insertPdp(DroolsPdp pdp) { + + logger.info("insertPdp: Entering and manually inserting PDP"); + + /* + * Start transaction + */ + EntityManager em = emf.createEntityManager(); + try { + em.getTransaction().begin(); + + /* + * Insert record. + */ + DroolsPdpEntity droolsPdpEntity = new DroolsPdpEntity(); + em.persist(droolsPdpEntity); + droolsPdpEntity.setPdpId(pdp.getPdpId()); + droolsPdpEntity.setDesignated(pdp.isDesignated()); + droolsPdpEntity.setPriority(pdp.getPriority()); + droolsPdpEntity.setUpdatedDate(pdp.getUpdatedDate()); + droolsPdpEntity.setSiteName(pdp.getSiteName()); + + /* + * End transaction. + */ + em.getTransaction().commit(); + } finally { + cleanup(em, "insertPdp"); + } + + logger.info("insertPdp: Exiting"); + + } + + /* + * Normally this method should only be used in a JUnit test environment. + * Manually deletes all PDP records in droolspdpentity table. + */ + @Override + public void deleteAllPdps() { + + logger.info("deleteAllPdps: Entering"); + + /* + * Start transaction + */ + EntityManager em = emf.createEntityManager(); + try { + em.getTransaction().begin(); + + Query droolsPdpsListQuery = em + .createQuery("SELECT p FROM DroolsPdpEntity p"); + @SuppressWarnings("unchecked") + List<DroolsPdp> droolsPdpsList = droolsPdpsListQuery.setLockMode( + LockModeType.NONE).getResultList(); + logger.info("deleteAllPdps: Deleting " + droolsPdpsList.size() + " PDPs"); + for (DroolsPdp droolsPdp : droolsPdpsList) { + String pdpId = droolsPdp.getPdpId(); + deletePdp(pdpId); + } + + /* + * End transaction. + */ + em.getTransaction().commit(); + } finally { + cleanup(em, "deleteAllPdps"); + } + + logger.info("deleteAllPdps: Exiting"); + + } + + /* + * Normally this method should only be used in a JUnit test environment. + * Manually deletes a PDP record in droolspdpentity table. + */ + @Override + public void deletePdp(String pdpId) { + + logger.info("deletePdp: Entering and manually deleting pdpId='" + pdpId + + "'"); + + /* + * Start transaction + */ + EntityManager em = emf.createEntityManager(); + try { + em.getTransaction().begin(); + + /* + * Delete record. + */ + DroolsPdpEntity droolsPdpEntity = em.find(DroolsPdpEntity.class, pdpId); + if (droolsPdpEntity != null) { + logger.info("deletePdp: Removing PDP"); + em.remove(droolsPdpEntity); + } else { + logger.info("deletePdp: PDP with ID='" + pdpId + + "' not currently in DB"); + } + + /* + * End transaction. + */ + em.getTransaction().commit(); + } finally { + cleanup(em, "deletePdp"); + } + + logger.info("deletePdp: Exiting"); + + } + + /* + * Normally this method should only be used in a JUnit test environment. + * Manually deletes all records in droolsessionentity table. + */ + @Override + public void deleteAllSessions() { + + logger.info("deleteAllSessions: Entering"); + + /* + * Start transaction + */ + EntityManager em = emf.createEntityManager(); + + try { + em.getTransaction().begin(); + + Query droolsSessionListQuery = em + .createQuery("SELECT p FROM DroolsSessionEntity p"); + @SuppressWarnings("unchecked") + List<DroolsSession> droolsSessionsList = droolsSessionListQuery.setLockMode( + LockModeType.NONE).getResultList(); + logger.info("deleteAllSessions: Deleting " + droolsSessionsList.size() + " Sessions"); + for (DroolsSession droolsSession : droolsSessionsList) { + logger.info("deleteAllSessions: Deleting droolsSession with pdpId=" + + droolsSession.getPdpId() + " and sessionId=" + + droolsSession.getSessionId()); + em.remove(droolsSession); + } + + /* + * End transaction. + */ + em.getTransaction().commit(); + } finally { + cleanup(em, "deleteAllSessions"); + } + logger.info("deleteAllSessions: Exiting"); + + } + + + /* + * Close the specified EntityManager, rolling back any pending transaction + * + * @param em the EntityManager to close ('null' is OK) + * @param method the invoking Java method (used for log messages) + */ + private static void cleanup(EntityManager em, String method) + { + if (em != null) { + if (em.isOpen()) { + if (em.getTransaction().isActive()) { + // there is an active EntityTransaction -- roll it back + try { + em.getTransaction().rollback(); + } catch (Exception e) { + logger.error(method + ": Caught Exception attempting to rollback EntityTransaction, message='" + + e.getMessage() + "'"); + } + } + + // now, close the EntityManager + try { + em.close(); + } catch (Exception e) { + logger.error(method + ": Caught Exception attempting to close EntityManager, message='" + + e.getMessage() + "'"); + } + } + } + } +} diff --git a/policy-persistence/src/main/java/org/openecomp/policy/drools/persistence/PersistenceFeature.java b/policy-persistence/src/main/java/org/openecomp/policy/drools/persistence/PersistenceFeature.java new file mode 100644 index 00000000..e2c7f402 --- /dev/null +++ b/policy-persistence/src/main/java/org/openecomp/policy/drools/persistence/PersistenceFeature.java @@ -0,0 +1,614 @@ +/*- + * ============LICENSE_START======================================================= + * policy-persistence + * ================================================================================ + * 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.persistence; + +import java.io.IOException; +import java.util.Date; +import java.util.HashMap; +import java.util.Map; +import java.util.Properties; + +import javax.persistence.EntityManagerFactory; +import javax.persistence.Persistence; + +import org.eclipse.persistence.config.PersistenceUnitProperties; +import org.kie.api.KieServices; +import org.kie.api.runtime.Environment; +import org.kie.api.runtime.EnvironmentName; +import org.kie.api.runtime.KieSession; +import org.kie.api.runtime.KieSessionConfiguration; +import org.openecomp.policy.common.ia.IntegrityAudit; +import org.openecomp.policy.common.ia.IntegrityAuditProperties; +import org.openecomp.policy.common.im.StateManagement; +import org.openecomp.policy.common.logging.eelf.MessageCodes; +import org.openecomp.policy.common.logging.flexlogger.FlexLogger; +import org.openecomp.policy.common.logging.flexlogger.Logger; +import org.openecomp.policy.common.logging.flexlogger.PropertyUtil; +import org.openecomp.policy.drools.core.DroolsPDPIntegrityMonitor; +import org.openecomp.policy.drools.core.FeatureAPI; +import org.openecomp.policy.drools.core.IntegrityMonitorProperties; +import org.openecomp.policy.drools.core.PolicyContainer; +import org.openecomp.policy.drools.core.PolicySession; +import org.openecomp.policy.drools.im.PMStandbyStateChangeNotifier; +import org.openecomp.policy.drools.system.PolicyEngine; + +import bitronix.tm.Configuration; +import bitronix.tm.TransactionManagerServices; +import bitronix.tm.resource.jdbc.PoolingDataSource; + +/** + * If this feature is supported, there is a single instance of it. + * It adds persistence to Drools sessions, but it is also intertwined with + * active/standby state management and IntegrityMonitor. For now, they are + * all treated as a single feature, but it would be nice to separate them. + * + * The bulk of the code here was once in other classes, such as + * 'PolicyContainer' and 'Main'. It was moved here as part of making this + * a separate optional feature. + */ +public class PersistenceFeature implements FeatureAPI +{ + // get an instance of logger + private static Logger logger = + FlexLogger.getLogger(PersistenceFeature.class); + + // 'KieServices' singleton + static private KieServices kieServices = KieServices.Factory.get(); + + private static DroolsPdp myPdp; + private static Object myPdpSync = new Object(); + private static DroolsPdpsElectionHandler electionHandler; + + // indicates whether persistence has been disabled + private static boolean persistenceDisabled = false; + + /* + * Used by JUnit testing to verify whether or not audit is running. + */ + private static IntegrityAudit integrityAudit = null; + + /** + * Lookup the adjunct for this feature that is associated with the + * specified PolicyContainer. If not found, create one. + * + * @param policyContainer the container whose adjunct we are looking up, + * and possibly creating + * @return the associated 'ContainerAdjunct' instance, which may be new + */ + private ContainerAdjunct getContainerAdjunct(PolicyContainer policyContainer) + { + Object rval = policyContainer.getAdjunct(this); + if (rval == null || ! (rval instanceof ContainerAdjunct)) + { + // adjunct does not exist, or has the wrong type (should never happen) + rval = new ContainerAdjunct(policyContainer); + policyContainer.setAdjunct(this, rval); + } + return((ContainerAdjunct)rval); + } + + /**************************/ + /* 'FeatureAPI' interface */ + /**************************/ + + /** + * {@inheritDoc} + */ + @Override + public int getSequenceNumber() + { + return(1); + } + + /** + * {@inheritDoc} + */ + @Override + public void globalInit(String args[], String configDir) + { + // Initialization code associated with 'PolicyContainer' + DroolsPDPIntegrityMonitor droolsPdpIntegrityMonitor = null; + try + { + droolsPdpIntegrityMonitor = DroolsPDPIntegrityMonitor.init(configDir); + } + catch (Exception e) + { + logger.error(MessageCodes.EXCEPTION_ERROR, e, + "main", "DroolsPDPIntegrityMonitor.init()"); + } + + initializePersistence(configDir, droolsPdpIntegrityMonitor); + + // 1. Start Integrity Monitor (unless it was specifically disabled in the CORE layer + + + if (persistenceDisabled) { + System.out.println("WARNING: Starting Engine with Persistance disabled"); + logger.warn("Starting Engine with Persistance disabled"); + } else { + DroolsPDPIntegrityMonitor im = null; + //At this point the DroolsPDPIntegrityMonitor instance must exist + try { + im = DroolsPDPIntegrityMonitor.getInstance(); + } catch (Exception e1) { + String msg = "policy-core startup failed to get DroolsPDPIntegrityMonitor instance: \n" + e1; + System.out.println(msg); + e1.printStackTrace(); + } + //Now get the StateManagement instance so we can register our observer + StateManagement sm = im.getStateManager(); + + //Create an instance of the Observer + PMStandbyStateChangeNotifier pmNotifier = new PMStandbyStateChangeNotifier(); + + //Register the PMStandbyStateChangeNotifier Observer + sm.addObserver(pmNotifier); + } + } + + /** + * This is a hook to create a new persistent KieSession. + * + * {@inheritDoc} + */ + @Override + public KieSession activatePolicySession + (PolicyContainer policyContainer, String name, String kieBaseName) + { + return(getContainerAdjunct(policyContainer) + .newPersistentKieSession(name, kieBaseName)); + } + + /** + * {@inheritDoc} + */ + @Override + public void disposeKieSession(PolicySession policySession) + { + // TODO: There should be one data source per session + getContainerAdjunct(policySession.getPolicyContainer()) + .disposeKieSession(); + } + + /** + * {@inheritDoc} + */ + @Override + public void destroyKieSession(PolicySession policySession) + { + // TODO: There should be one data source per session + getContainerAdjunct(policySession.getPolicyContainer()) + .destroyKieSession(); + } + + + /** + * {@inheritDoc} + */ + @Override + public void beforeStartEngine() + { + return; + } + + /** + * {@inheritDoc} + */ + @Override + public void afterStartEngine() + { + PolicyEngine.manager.lock(); + } + + /** + * {@inheritDoc} + */ + @Override + public void beforeShutdownEngine() + { + return; + } + + /** + * {@inheritDoc} + */ + @Override + public void beforeCreateController(String name, Properties properties) + { + return; + } + + /** + * {@inheritDoc} + */ + @Override + public void afterCreateController(String name) + { + return; + } + + /** + * {@inheritDoc} + */ + @Override + public void afterShutdownEngine() + { + return; + } + + /** + * {@inheritDoc} + */ + @Override + public void beforeStartController(String name) + { + return; + } + + /** + * {@inheritDoc} + */ + @Override + public void afterStartController(String name) + { + return; + } + + /** + * {@inheritDoc} + */ + @Override + public boolean isPersistenceEnabled() + { + return(!persistenceDisabled); + } + + /**************************/ + + /** + * @return 'true' if Drools persistence is disabled, and 'false' if not + */ + static public boolean getPersistenceDisabled() + { + return(persistenceDisabled); + } + + /** + * Read in the persistence properties, determine whether persistence is + * enabled or disabled, and initialize persistence if enabled. + */ + private static void initializePersistence(String configDir, DroolsPDPIntegrityMonitor droolsPdpIntegrityMonitor) + { + + try { + Properties pDrools = PropertyUtil.getProperties(configDir + + "/droolsPersistence.properties"); + DroolsPersistenceProperties.initProperties(pDrools); + Properties pXacml = PropertyUtil.getProperties(configDir + + "/xacmlPersistence.properties"); + XacmlPersistenceProperties.initProperties(pXacml); + if ("true".equals(pDrools.getProperty("persistenceDisabled"))) { + // 'persistenceDisabled' only relates to the 'drools' + // database. The fact that integrityMonitor/xacml depends upon + // persistence is an implementation detail there (which can't + // currently be disabled), and doesn't directly affect + // 'policy-core'. + persistenceDisabled = true; + } + } catch (IOException e1) { + logger.error(MessageCodes.MISS_PROPERTY_ERROR, e1, + "initializePersistence"); + } + + /* + * Might as well handle the Integrity Monitor properties here, too. + */ + try { + Properties pIm = + PropertyUtil.getProperties(configDir + "/IntegrityMonitor.properties"); + IntegrityMonitorProperties.initProperties(pIm); + logger.info("initializePersistence: resourceName=" + IntegrityMonitorProperties.getProperty(IntegrityMonitorProperties.PDP_INSTANCE_ID)); + } catch (IOException e1) { + logger.error(MessageCodes.MISS_PROPERTY_ERROR, e1, "initializePersistence"); + } + + + if (persistenceDisabled) { + // The persistence design is tied to 'DroolsPdpsElectionHandler', + // so we should bypass that as well. This also means that we + // won't get active/standby notifications, so we need to go + // into the 'active' state in order to have any 'PolicySession' + // instances. + return; + } + + DroolsPdpsConnector conn = getDroolsPdpsConnector("ncompPU"); + String uniquePdpId = IntegrityMonitorProperties.getProperty(IntegrityMonitorProperties.PDP_INSTANCE_ID); + if(uniquePdpId == null){ + throw new NullPointerException(); + } + + /* + * In a JUnit test environment, one or more PDPs may already have been + * inserted in the DB, so we need to check for this. + */ + DroolsPdp existingPdp = conn.getPdp(uniquePdpId); + if (existingPdp != null) { + System.out.println("Found existing PDP record, pdpId=" + + existingPdp.getPdpId() + ", isDesignated=" + + existingPdp.isDesignated() + ", updatedDate=" + + existingPdp.getUpdatedDate()); + myPdp = existingPdp; + } + + /* + * Kick off integrity audit for Drools DB. + */ + startIntegrityAudit(configDir); + + synchronized(myPdpSync){ + if(myPdp == null){ + + myPdp = new DroolsPdpImpl(uniquePdpId,false,4,new Date()); + } + if(myPdp != null){ + String site_name = ""; + site_name = IntegrityMonitorProperties.getProperty(IntegrityMonitorProperties.SITE_NAME); + if (site_name == null) { + site_name = ""; + }else{ + site_name = site_name.trim(); + } + myPdp.setSiteName(site_name); + } + if(electionHandler == null){ + electionHandler = new DroolsPdpsElectionHandler(conn,myPdp,droolsPdpIntegrityMonitor); + } + } + Configuration bitronixConfiguration = TransactionManagerServices.getConfiguration(); + bitronixConfiguration.setJournal(null); + bitronixConfiguration.setServerId(uniquePdpId); + System.out.println("\n\nThis controller is a standby, waiting to be chosen as primary...\n\n"); + logger.info("\n\nThis controller is a standby, waiting to be chosen as primary...\n\n"); + } + + private static void startIntegrityAudit(String configDir) { + + logger.info("startIntegrityAudit: Entering, configDir='" + configDir + + "'"); + + /* + * Initialize Integrity Audit properties. file. + */ + try { + + String resourceName = IntegrityMonitorProperties + .getProperty(IntegrityMonitorProperties.PDP_INSTANCE_ID); + + /* + * Load properties for auditing of Drools DB. + */ + Properties droolsPia = PropertyUtil.getProperties(configDir + + "/IntegrityMonitor.properties"); + + /* + * Supplement properties specific to the IntegrityMonitor (e.g. + * site_name, node_type, resource.name) with properties specific to + * persisting Drools DB entities (see + * ../policy-core/src/main/resources/persistence.xml) + * + * Note: integrity_audit_period_seconds is defined in + * IntegrityMonitor.properties, rather than creating a whole new + * "IntegrityAudit.properties" file for just one property. + */ + droolsPia + .setProperty( + IntegrityAuditProperties.DB_DRIVER, + DroolsPersistenceProperties + .getProperty(DroolsPersistenceProperties.DB_DRIVER)); + droolsPia.setProperty(IntegrityAuditProperties.DB_PWD, + DroolsPersistenceProperties + .getProperty(DroolsPersistenceProperties.DB_PWD)); + droolsPia.setProperty(IntegrityAuditProperties.DB_URL, + DroolsPersistenceProperties + .getProperty(DroolsPersistenceProperties.DB_URL)); + droolsPia.setProperty(IntegrityAuditProperties.DB_USER, + DroolsPersistenceProperties + .getProperty(DroolsPersistenceProperties.DB_USER)); + + /* + * Start audit for Drools DB. + */ + integrityAudit = new IntegrityAudit( + resourceName, "ncompPU", droolsPia); + integrityAudit.startAuditThread(); + + } catch (IOException e1) { + logger.error( + MessageCodes.MISS_PROPERTY_ERROR, + e1, + "initializePersistence: IntegrityAuditProperties: " + + e1.getMessage()); + } catch (Exception e2) { + logger.error( + MessageCodes.EXCEPTION_ERROR, + e2, + "initializePersistence: IntegrityAuditProperties: " + + e2.getMessage()); + } + + logger.debug("startIntegrityAudit: Exiting"); + + } + + /* + * Moved code to instantiate a JpaDroolsPdpsConnector object from main() to + * this method, so it can also be accessed from StandbyStateChangeNotifier + * class. + */ + public static DroolsPdpsConnector getDroolsPdpsConnector(String pu) { + + Map<String, Object> propMap = new HashMap<String, Object>(); + propMap.put("javax.persistence.jdbc.driver", DroolsPersistenceProperties + .getProperty(DroolsPersistenceProperties.DB_DRIVER)); + propMap.put("javax.persistence.jdbc.url", + DroolsPersistenceProperties.getProperty(DroolsPersistenceProperties.DB_URL)); + propMap.put("javax.persistence.jdbc.user", DroolsPersistenceProperties + .getProperty(DroolsPersistenceProperties.DB_USER)); + propMap.put("javax.persistence.jdbc.password", + DroolsPersistenceProperties.getProperty(DroolsPersistenceProperties.DB_PWD)); + + EntityManagerFactory emf = Persistence.createEntityManagerFactory( + pu, propMap); + DroolsPdpsConnector conn = new JpaDroolsPdpsConnector(emf); + + return conn; + } + + /* + * IntegrityAudit instance is needed by JUnit testing to ascertain whether + * or not audit is running. + */ + public static IntegrityAudit getIntegrityAudit() { + + return integrityAudit; + + } + + /* ============================================================ */ + + /** + * Each instance of this class is a logical extension of a 'PolicyContainer' + * instance. It's reference is stored in the 'adjuncts' table within the + * 'PolicyContainer', and will be garbage-collected with the container. + */ + class ContainerAdjunct + { + // this is the 'PolicyContainer' instance that this adjunct is extending + private PolicyContainer policyContainer; + private PoolingDataSource ds = null; + + /** + * Constructor - initialize a new 'ContainerAdjunct' + * + * @param policyContainer the 'PolicyContainer' instance this adjunct + * is extending + */ + ContainerAdjunct(PolicyContainer policyContainer) + { + this.policyContainer = policyContainer; + } + + /** + * Create a new persistent KieSession. If there is already a corresponding + * entry in the database, it is used to initialize the KieSession. If not, + * a completely new session is created. + * + * @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 with persistence enabled (if persistence is + * disabled, 'null' is returned + */ + private KieSession newPersistentKieSession(String name, String kieBaseName) + { + if (persistenceDisabled) + { + return(null); + } + long desiredSessionId = -1; + synchronized (myPdpSync) { + + + + for(DroolsSession droolsSession : electionHandler.getSessions()){ + if(droolsSession.getSessionName().equals(name)){ + desiredSessionId = droolsSession.getSessionId(); + } + } + } + System.out.println("\n\nThis controller is primary... coming up with session "+desiredSessionId+"\n\n"); + logger.info("\n\nThis controller is primary... coming up with session "+desiredSessionId+"\n\n"); + Map<String, Object> props = new HashMap<String, Object>(); + props.put("URL", DroolsPersistenceProperties.getProperty(DroolsPersistenceProperties.DB_URL)); + props.put("user", DroolsPersistenceProperties.getProperty(DroolsPersistenceProperties.DB_USER)); + props.put("password", DroolsPersistenceProperties.getProperty(DroolsPersistenceProperties.DB_PWD)); + props.put("dataSource",DroolsPersistenceProperties.getProperty(DroolsPersistenceProperties.DB_DATA_SOURCE)); + logger.info("getPolicySession:session does not exist -- attempt to create one with name " + name); + // session does not exist -- attempt to create one + System.getProperties().put("java.naming.factory.initial","bitronix.tm.jndi.BitronixInitialContextFactory"); + Environment env = kieServices.newEnvironment(); + //kContainer.newKieBase(null); + ds = new PoolingDataSource(); + ds.setUniqueName("jdbc/BitronixJTADataSource"+name); + ds.setClassName( (String)props.remove("dataSource")); + //ds.setClassName( "org.h2.Driver" ); + ds.setMaxPoolSize( 3 ); + ds.setIsolationLevel("SERIALIZABLE"); + ds.setAllowLocalTransactions( true ); + //ds.getDriverProperties().put( "user", "sa" ); + //ds.getDriverProperties().put( "password", "" ); + //ds.getDriverProperties().put( "URL", "jdbc:h2:tcp://localhost/drools" ); + ds.getDriverProperties().putAll(props); + ds.init(); + Properties emfProperties = new Properties(); + emfProperties.setProperty(PersistenceUnitProperties.JTA_DATASOURCE, "jdbc/BitronixJTADataSource"+name); + env.set(EnvironmentName.ENTITY_MANAGER_FACTORY, Persistence.createEntityManagerFactory("ncompsessionsPU",emfProperties)); + env.set(EnvironmentName.TRANSACTION_MANAGER,TransactionManagerServices.getTransactionManager()); + KieSessionConfiguration kConf = KieServices.Factory.get().newKieSessionConfiguration(); + KieSession kieSession; + try{ + kieSession = kieServices.getStoreServices().loadKieSession(desiredSessionId, policyContainer.getKieContainer().getKieBase(kieBaseName), kConf, env); + System.out.println("LOADING We can load session "+desiredSessionId+", going to create a new one"); + logger.info("LOADING We can load session "+desiredSessionId+", going to create a new one"); + }catch(Exception e){ + System.out.println("LOADING We cannot load session "+desiredSessionId+", going to create a new one"); + + logger.info("LOADING We cannot load session "+desiredSessionId+", going to create a new one"); + kieSession = kieServices.getStoreServices().newKieSession(policyContainer.getKieContainer().getKieBase(kieBaseName), null, env); + System.out.println("LOADING CREATED "+kieSession.getIdentifier()); + logger.info("LOADING CREATED "+kieSession.getIdentifier()); + } + synchronized (myPdpSync) { + myPdp.setSessionId(name,kieSession.getIdentifier()); + electionHandler.updateMyPdp(); + } + return(kieSession); + } + + private void disposeKieSession() + { + if (ds != null) + { + ds.close(); + ds = null; + } + } + + private void destroyKieSession() + { + // does the same thing as 'dispose' + disposeKieSession(); + } + } +} diff --git a/policy-persistence/src/main/java/org/openecomp/policy/drools/persistence/ThreadRunningChecker.java b/policy-persistence/src/main/java/org/openecomp/policy/drools/persistence/ThreadRunningChecker.java new file mode 100644 index 00000000..ccec824c --- /dev/null +++ b/policy-persistence/src/main/java/org/openecomp/policy/drools/persistence/ThreadRunningChecker.java @@ -0,0 +1,26 @@ +/*- + * ============LICENSE_START======================================================= + * policy-persistence + * ================================================================================ + * 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.persistence; + +public interface ThreadRunningChecker { + public void checkThreadStatus(); + +} diff --git a/policy-persistence/src/main/java/org/openecomp/policy/drools/persistence/XacmlPersistenceProperties.java b/policy-persistence/src/main/java/org/openecomp/policy/drools/persistence/XacmlPersistenceProperties.java new file mode 100644 index 00000000..7e2388e5 --- /dev/null +++ b/policy-persistence/src/main/java/org/openecomp/policy/drools/persistence/XacmlPersistenceProperties.java @@ -0,0 +1,65 @@ +/*- + * ============LICENSE_START======================================================= + * policy-persistence + * ================================================================================ + * 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.persistence; + +import java.util.Properties; + +import org.openecomp.policy.common.logging.flexlogger.FlexLogger; +import org.openecomp.policy.common.logging.flexlogger.Logger; + + +public class XacmlPersistenceProperties { + // get an instance of logger + private static Logger logger = FlexLogger.getLogger(XacmlPersistenceProperties.class); + /* + * xacmlPersistence.properties parameter key values + */ + public static final String DB_DRIVER = "javax.persistence.jdbc.driver"; + public static final String DB_DATA_SOURCE = "hibernate.dataSource"; + public static final String DB_URL = "javax.persistence.jdbc.url"; + public static final String DB_USER = "javax.persistence.jdbc.user"; + public static final String DB_PWD = "javax.persistence.jdbc.password"; + + private static Properties properties = null; + /* + * Initialize the parameter values from the droolsPersitence.properties file values + * + * This is designed so that the Properties object is obtained from the xacmlPersistence.properties + * file and then is passed to this method to initialize the value of the parameters. + * This allows the flexibility of JUnit tests using getProperties(filename) to get the + * properties while runtime methods can use getPropertiesFromClassPath(filename). + * + */ + public static void initProperties (Properties prop){ + logger.info("XacmlPersistenceProperties.initProperties(Properties): entry"); + logger.info("\n\nXacmlPersistenceProperties.initProperties: Properties = \n" + prop + "\n\n"); + + properties = prop; + } + + public static String getProperty(String key){ + return properties.getProperty(key); + } + + public static Properties getProperties() { + return properties; + } +} diff --git a/policy-persistence/src/main/resources/META-INF/services/org.openecomp.policy.drools.core.FeatureAPI b/policy-persistence/src/main/resources/META-INF/services/org.openecomp.policy.drools.core.FeatureAPI new file mode 100644 index 00000000..540a4bd4 --- /dev/null +++ b/policy-persistence/src/main/resources/META-INF/services/org.openecomp.policy.drools.core.FeatureAPI @@ -0,0 +1 @@ +org.openecomp.policy.drools.persistence.PersistenceFeature diff --git a/policy-persistence/src/test/java/org/openecomp/policy/drools/controller/test/IntegrityAuditIntegrationTest.java b/policy-persistence/src/test/java/org/openecomp/policy/drools/controller/test/IntegrityAuditIntegrationTest.java new file mode 100644 index 00000000..6b654732 --- /dev/null +++ b/policy-persistence/src/test/java/org/openecomp/policy/drools/controller/test/IntegrityAuditIntegrationTest.java @@ -0,0 +1,279 @@ +/*- + * ============LICENSE_START======================================================= + * policy-persistence + * ================================================================================ + * 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.controller.test; + +import static org.junit.Assert.assertTrue; + +import java.io.File; +import java.io.FileInputStream; +import java.util.Date; +import java.util.Properties; + +import javax.persistence.EntityManager; +import javax.persistence.EntityManagerFactory; +import javax.persistence.EntityTransaction; +import javax.persistence.Persistence; + +import org.junit.After; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Ignore; +import org.junit.Test; + +import org.openecomp.policy.common.logging.eelf.PolicyLogger; +import org.openecomp.policy.common.ia.IntegrityAudit; +import org.openecomp.policy.common.im.AdministrativeStateException; +import org.openecomp.policy.common.im.IntegrityMonitor; +import org.openecomp.policy.common.im.StandbyStatusException; +import org.openecomp.policy.common.im.StateManagement; +import org.openecomp.policy.drools.core.DroolsPDPIntegrityMonitor; +import org.openecomp.policy.drools.core.IntegrityMonitorProperties; +import org.openecomp.policy.drools.core.PolicyContainer; +import org.openecomp.policy.drools.im.PMStandbyStateChangeNotifier; +import org.openecomp.policy.drools.persistence.DroolsPdpEntity; +import org.openecomp.policy.drools.persistence.DroolsPdpImpl; +import org.openecomp.policy.drools.persistence.DroolsPdpsConnector; +import org.openecomp.policy.drools.persistence.JpaDroolsPdpsConnector; +import org.openecomp.policy.drools.persistence.DroolsPersistenceProperties; +import org.openecomp.policy.drools.persistence.PersistenceFeature; +import org.openecomp.policy.drools.persistence.XacmlPersistenceProperties; +import org.openecomp.policy.drools.system.Main; +import org.openecomp.policy.drools.system.PolicyEngine; + +/* + * Cloned from StandbyStateManagement.java in support of US673632. + * See MultiSite_v1-10.ppt, slide 38 + */ +public class IntegrityAuditIntegrationTest { + + + public static final String INTEGRITY_MONITOR_PROPERTIES_FILE="src/test/server/config/IntegrityMonitor.properties"; + + /* + * Currently, the DroolsPdpsElectionHandler.DesignationWaiter is invoked every ten seconds, starting + * at ten seconds after the minute boundary (e.g. 13:05:10). So, an 80 second sleep should be + * sufficient to ensure that we wait for the DesignationWaiter to do its job, before + * checking the results. + */ + private long sleepTime = 80000; + + /* + * Sleep 5 seconds after each test to allow interrupt (shutdown) recovery. + */ + private long interruptRecoveryTime = 5000; + + /* + * See the IntegrityMonitor.getJmxUrl() method for the rationale behind this jmx related processing. + */ + @BeforeClass + public static void setUpClass() throws Exception { + + PolicyLogger.info("setUpClass: Entering"); + + String userDir = System.getProperty("user.dir"); + PolicyLogger.debug("setUpClass: userDir=" + userDir); + System.setProperty("com.sun.management.jmxremote.port", "9980"); + System.setProperty("com.sun.management.jmxremote.authenticate","false"); + + // Make sure path to config directory is set correctly in PolicyContainer.main + // Also make sure we ignore HTTP server failures resulting from port conflicts. + PolicyContainer.isUnitTesting = true; + + /* + * Setting isUnitTesting to true ensures + * + * 1) That we load test version of properties files + * + * and + * + * 2) that we use dbAuditSimulate() method, because all we care about + * for this JUnit testing is that the audits are executed. + */ + IntegrityAudit.isUnitTesting = true; + + initializeDb(); + + PolicyLogger.info("setUpClass: Exiting"); + + } + + @AfterClass + public static void tearDownClass() throws Exception { + + } + + @Before + public void setUp() throws Exception { + + } + + @After + public void tearDown() throws Exception { + + } + + + /* + * Verifies that audit thread starts successfully. + */ + //@Ignore + @Test + public void testAuditInit() throws Exception { + + PolicyLogger.debug("\n\ntestAuditInit: Entering\n\n"); + + PolicyLogger.debug("testAuditInit: Reading IntegrityMonitorProperties"); + Properties integrityMonitorProperties = new Properties(); + integrityMonitorProperties.load(new FileInputStream(new File( + INTEGRITY_MONITOR_PROPERTIES_FILE))); + IntegrityMonitorProperties.initProperties(integrityMonitorProperties); + String thisPdpId = IntegrityMonitorProperties + .getProperty(IntegrityMonitorProperties.PDP_INSTANCE_ID); + + PolicyLogger.debug("testAuditInit: Reading xacmlPersistenceProperties"); + Properties xacmlPersistenceProperties = new Properties(); + xacmlPersistenceProperties.load(new FileInputStream(new File( + "src/test/server/config/xacmlPersistence.properties"))); + XacmlPersistenceProperties.initProperties(xacmlPersistenceProperties); + + PolicyLogger.debug("testAuditInit: Creating emfXacml"); + EntityManagerFactory emfXacml = Persistence.createEntityManagerFactory( + "junitXacmlPU", xacmlPersistenceProperties); + + PolicyLogger.debug("testAuditInit: Reading droolsPersistenceProperties"); + Properties droolsPersistenceProperties = new Properties(); + droolsPersistenceProperties.load(new FileInputStream(new File( + "src/test/server/config/droolsPersistence.properties"))); + DroolsPersistenceProperties.initProperties(droolsPersistenceProperties); + + PolicyLogger.debug("testAuditInit: Creating emfDrools"); + EntityManagerFactory emfDrools = Persistence.createEntityManagerFactory( + "junitDroolsPU", droolsPersistenceProperties); + + DroolsPdpsConnector conn = new JpaDroolsPdpsConnector(emfDrools); + + PolicyLogger.debug("testAuditInit: Cleaning up tables"); + conn.deleteAllSessions(); + conn.deleteAllPdps(); + + /* + * Insert this PDP as designated. Initial standby state will be + * either null or cold standby. + */ + PolicyLogger.debug("testAuditInit: Inserting PDP=" + thisPdpId + " as designated"); + DroolsPdpImpl pdp = new DroolsPdpImpl(thisPdpId, true, 4, new Date()); + conn.insertPdp(pdp); + DroolsPdpEntity droolsPdpEntity = conn.getPdp(thisPdpId); + PolicyLogger.debug("testAuditInit: After insertion, PDP=" + thisPdpId + " has DESIGNATED=" + + droolsPdpEntity.isDesignated()); + assertTrue(droolsPdpEntity.isDesignated() == true); + + PolicyLogger.debug("testAuditInit: Instantiating stateManagement object"); + StateManagement sm = new StateManagement(emfXacml, "dummy"); + sm.deleteAllStateManagementEntities(); + sm = new StateManagement(emfXacml, thisPdpId); + PMStandbyStateChangeNotifier pmStandbyStateChangeNotifier = new PMStandbyStateChangeNotifier(); + sm.addObserver(pmStandbyStateChangeNotifier); + + PolicyLogger.debug("testAuditInit: Running policy-management.Main class, designated=" + + conn.getPdp(thisPdpId).isDesignated()); + PolicyManagementRunner policyManagementRunner = new PolicyManagementRunner(); + policyManagementRunner.start(); + + PolicyLogger.debug("testAuditInit: Runner started; Sleeping " + + interruptRecoveryTime + "ms before promoting PDP=" + + thisPdpId); + Thread.sleep(interruptRecoveryTime); + + IntegrityAudit integrityAudit = PersistenceFeature.getIntegrityAudit(); + PolicyLogger.debug("testAuditInit: isThreadInitialized=" + integrityAudit.isThreadInitialized()); + assertTrue("AuditThread not initialized!?",integrityAudit.isThreadInitialized()); + + PolicyLogger.debug("testAuditInit: Stopping auditThread"); + integrityAudit.stopAuditThread(); + Thread.sleep(1000); + //This will interrupt thread. However, the thread will not die. It keeps on ticking and trying to + //run the audit. + assertTrue("AuditThread not still running after stopAuditThread invoked!?",integrityAudit.isThreadInitialized()); + + PolicyLogger.debug("testAuditInit: Stopping policyManagementRunner"); + policyManagementRunner.stopRunner(); + + PolicyLogger.debug("\n\ntestAuditInit: Exiting\n\n"); + Thread.sleep(interruptRecoveryTime); + + } + + /* + * This method initializes and cleans the DB so that PDP-D will be able to + * store IntegrityAuditEntity in the DB. + */ + public static void initializeDb(){ + + PolicyLogger.debug("initializeDb: Entering"); + + Properties cleanProperties = new Properties(); + cleanProperties.put(DroolsPersistenceProperties.DB_DRIVER,"org.h2.Driver"); + cleanProperties.put(DroolsPersistenceProperties.DB_URL, "jdbc:h2:file:./sql/drools"); + cleanProperties.put(DroolsPersistenceProperties.DB_USER, "sa"); + cleanProperties.put(DroolsPersistenceProperties.DB_PWD, ""); + //EntityManagerFactory emf = Persistence.createEntityManagerFactory("schemaPU", cleanProperties); + EntityManagerFactory emf = Persistence.createEntityManagerFactory("junitDroolsPU", cleanProperties); + + EntityManager em = emf.createEntityManager(); + // Start a transaction + EntityTransaction et = em.getTransaction(); + + et.begin(); + + // Clean up the DB + em.createQuery("Delete from IntegrityAuditEntity").executeUpdate(); + + // commit transaction + et.commit(); + em.close(); + + PolicyLogger.debug("initializeDb: Exiting"); + } + + private class PolicyManagementRunner extends Thread { + + public void run() { + PolicyLogger.info("PolicyManagementRunner.run: Entering"); + String args[] = { "src/main/server/config" }; + try { + Main.main(args); + } catch (Exception e) { + PolicyLogger + .info("PolicyManagementRunner.run: Exception thrown from Main.main(), message=" + + e.getMessage()); + } + PolicyLogger.info("PolicyManagementRunner.run: Exiting"); + } + + public void stopRunner() { + PolicyEngine.manager.shutdown(); + } + + } + +} diff --git a/policy-persistence/src/test/java/org/openecomp/policy/drools/controller/test/ResiliencyTestCases.java b/policy-persistence/src/test/java/org/openecomp/policy/drools/controller/test/ResiliencyTestCases.java new file mode 100644 index 00000000..f58d304e --- /dev/null +++ b/policy-persistence/src/test/java/org/openecomp/policy/drools/controller/test/ResiliencyTestCases.java @@ -0,0 +1,1267 @@ +/*- + * ============LICENSE_START======================================================= + * policy-persistence + * ================================================================================ + * 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.controller.test; + +import static org.junit.Assert.assertTrue; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.util.Date; +import java.util.Properties; + +import javax.persistence.EntityManager; +import javax.persistence.EntityManagerFactory; +import javax.persistence.EntityTransaction; +import javax.persistence.Persistence; + +import org.junit.After; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Ignore; +import org.junit.Test; + +import org.openecomp.policy.common.logging.eelf.PolicyLogger; +import org.openecomp.policy.common.im.AdministrativeStateException; +import org.openecomp.policy.common.im.IntegrityMonitor; +import org.openecomp.policy.common.im.StandbyStatusException; +import org.openecomp.policy.common.im.StateManagement; +import org.openecomp.policy.drools.core.DroolsPDPIntegrityMonitor; +import org.openecomp.policy.drools.core.IntegrityMonitorProperties; +import org.openecomp.policy.drools.core.PolicyContainer; +import org.openecomp.policy.drools.im.PMStandbyStateChangeNotifier; +import org.openecomp.policy.drools.persistence.DroolsPdp; +import org.openecomp.policy.drools.persistence.DroolsPdpEntity; +import org.openecomp.policy.drools.persistence.DroolsPdpImpl; +import org.openecomp.policy.drools.persistence.DroolsPdpsConnector; +import org.openecomp.policy.drools.persistence.JpaDroolsPdpsConnector; +import org.openecomp.policy.drools.persistence.DroolsPersistenceProperties; +import org.openecomp.policy.drools.persistence.XacmlPersistenceProperties; +import org.openecomp.policy.drools.system.Main; +import org.openecomp.policy.drools.system.PolicyEngine; + +import org.apache.commons.lang3.time.DateUtils; + +/* + * Cloned from StandbyStateManagement.java in support of US673632. + * See MultiSite_v1-10.ppt, slide 38 + */ +public class ResiliencyTestCases { + + /* + * Currently, the DroolsPdpsElectionHandler.DesignationWaiter is invoked every ten seconds, starting + * at ten seconds after the minute boundary (e.g. 13:05:10). So, an 80 second sleep should be + * sufficient to ensure that we wait for the DesignationWaiter to do its job, before + * checking the results. + */ + long sleepTime = 80000; + + /* + * DroolsPdpsElectionHandler runs every ten seconds, so a 15 second sleep should be + * plenty to ensure it has time to re-promote this PDP. + */ + long electionWaitSleepTime = 15000; + + /* + * Sleep 5 seconds after each test to allow interrupt (shutdown) recovery. + */ + long interruptRecoveryTime = 5000; + + /* + * See the IntegrityMonitor.getJmxUrl() method for the rationale behind this jmx related processing. + */ + @BeforeClass + public static void setUpClass() throws Exception { + + String userDir = System.getProperty("user.dir"); + PolicyLogger.debug("setUpClass: userDir=" + userDir); + System.setProperty("com.sun.management.jmxremote.port", "9980"); + System.setProperty("com.sun.management.jmxremote.authenticate","false"); + + // Make sure path to config directory is set correctly in PolicyContainer.main + // Also make sure we ignore HTTP server failures resulting from port conflicts. + PolicyContainer.isUnitTesting = true; + + } + + @AfterClass + public static void tearDownClass() throws Exception { + } + + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + + } + + public void cleanDroolsDB() throws Exception{ + PolicyLogger.debug("\n\ncleanDroolsDB: Entering\n\n"); + + PolicyLogger.debug("cleanDroolsDB: Reading droolsPersistenceProperties"); + Properties droolsPersistenceProperties = new Properties(); + droolsPersistenceProperties.load(new FileInputStream(new File( + "src/test/server/config/droolsPersistence.properties"))); + + PolicyLogger.debug("cleanDroolsDB: Creating emfDrools"); + EntityManagerFactory emf = Persistence.createEntityManagerFactory( + "junitDroolsPU", droolsPersistenceProperties); + + PolicyLogger.debug("cleanDroolsDB: Cleaning up tables"); + + EntityManager em = emf.createEntityManager(); + EntityTransaction et = em.getTransaction(); + et.begin(); + + // Make sure the DB is clean + PolicyLogger.debug("cleanDroolsDB: clean DroolsPdpEntity"); + em.createQuery("DELETE FROM DroolsPdpEntity").executeUpdate(); + PolicyLogger.debug("cleanDroolsDB: clean DroolsSessionEntity"); + em.createQuery("DELETE FROM DroolsSessionEntity").executeUpdate(); + + em.flush(); + PolicyLogger.debug("cleanDroolsDB: after flush"); + + et.commit(); + + PolicyLogger.debug("\n\ncleanDroolsDB: Exiting\n\n"); + } + + public void cleanXacmlDB() throws Exception { + PolicyLogger.debug("\n\ncleanXacmlDB: Entering\n\n"); + + PolicyLogger.debug("cleanXacmlDB: Reading IntegrityMonitorProperties"); + + PolicyLogger.debug("cleanXacmlDB: Reading xacmlPersistenceProperties"); + Properties xacmlPersistenceProperties = new Properties(); + xacmlPersistenceProperties.load(new FileInputStream(new File( + "src/test/server/config/xacmlPersistence.properties"))); + + PolicyLogger.debug("cleanXacmlDB: Creating emf"); + EntityManagerFactory emf = Persistence.createEntityManagerFactory( + "junitXacmlPU", xacmlPersistenceProperties); + + EntityManager em = emf.createEntityManager(); + EntityTransaction et = em.getTransaction(); + et.begin(); + + // Make sure the DB is clean + PolicyLogger.debug("cleanXacmlDB: clean StateManagementEntity"); + em.createQuery("DELETE FROM StateManagementEntity").executeUpdate(); + PolicyLogger.debug("cleanXacmlDB: clean ResourceRegistrationEntity"); + em.createQuery("DELETE FROM ResourceRegistrationEntity").executeUpdate(); + PolicyLogger.debug("cleanXacmlDB: clean ForwardProgressEntity"); + em.createQuery("DELETE FROM ForwardProgressEntity").executeUpdate(); + + em.flush(); + PolicyLogger.debug("cleandXacmlDB: after flush"); + + et.commit(); + + PolicyLogger.debug("\n\ncleanXacmlDB: Exiting\n\n"); + + } + + @Ignore + @Test + public void singleNodeTests() throws Exception{ + //snNewInstall(); + snNewInstallBadDepData(); + /*snRecoveryFromBadDepData(); + snLock(); + snLockRestart(); + snUnlock(); + snUnlockRestart();*/ + } + + @Ignore + @Test + public void twoNodeTests() throws Exception{ + tnNewInstall(); + tnLockActive(); + tnUnlockColdStandby(); + tnFailActive(); + tnRecoverFailed(); + } + + @Ignore + @Test + public void twoSitesTwoNodesPerSiteTests() throws Exception{ + tstnNewInstall(); + tstnLock1Site1(); + tstnLock2Site1(); + tstnFailActiveSite2(); + tstnRecoverFailedSite2(); + tstnUnlockSite1(); + tstnFailSite2(); + } + + + /* + * Single Node Tests + */ + public void snNewInstall() throws Exception{ + PolicyLogger.debug("\n\nsnNewInstall: Entry\n\n"); + cleanDroolsDB(); + cleanXacmlDB(); + + //******************************************* + + PolicyLogger.debug("snNewInstall: Reading IntegrityMonitorProperties"); + Properties integrityMonitorProperties = new Properties(); + integrityMonitorProperties.load(new FileInputStream(new File( + "src/test/server/config/IntegrityMonitor.properties"))); + IntegrityMonitorProperties.initProperties(integrityMonitorProperties); + String thisPdpId = IntegrityMonitorProperties + .getProperty(IntegrityMonitorProperties.PDP_INSTANCE_ID); + + PolicyLogger.debug("snNewInstall: Reading xacmlPersistenceProperties"); + Properties xacmlPersistenceProperties = new Properties(); + xacmlPersistenceProperties.load(new FileInputStream(new File( + "src/test/server/config/xacmlPersistence.properties"))); + XacmlPersistenceProperties.initProperties(xacmlPersistenceProperties); + + PolicyLogger.debug("snNewInstall: Creating emfXacml"); + EntityManagerFactory emfXacml = Persistence.createEntityManagerFactory( + "junitXacmlPU", xacmlPersistenceProperties); + + PolicyLogger.debug("snNewInstall: Reading droolsPersistenceProperties"); + Properties droolsPersistenceProperties = new Properties(); + droolsPersistenceProperties.load(new FileInputStream(new File( + "src/test/server/config/droolsPersistence.properties"))); + DroolsPersistenceProperties.initProperties(droolsPersistenceProperties); + + PolicyLogger.debug("snNewInstall: Creating emfDrools"); + EntityManagerFactory emfDrools = Persistence.createEntityManagerFactory( + "junitDroolsPU", droolsPersistenceProperties); + + DroolsPdpsConnector conn = new JpaDroolsPdpsConnector(emfDrools); + + PolicyLogger.debug("snNewInstall: Inserting PDP=" + thisPdpId + " as designated"); + DroolsPdp pdp = new DroolsPdpImpl(thisPdpId, true, 4, new Date()); + conn.insertPdp(pdp); + DroolsPdpEntity droolsPdpEntity = conn.getPdp(thisPdpId); + PolicyLogger.debug("snNewInstall: After insertion, DESIGNATED=" + + droolsPdpEntity.isDesignated() + " for PDP=" + thisPdpId); + assertTrue(droolsPdpEntity.isDesignated() == true); + + /* + * When the Standby Status changes (from providingservice) to hotstandby + * or coldstandby,the Active/Standby selection algorithm must stand down + * if thePDP-D is currently the lead/active node and allow another PDP-D + * to take over. + * + * It must also call lock on all engines in the engine management. + * + */ + PolicyLogger.debug("snNewInstall: Instantiating stateManagement object"); + StateManagement sm = new StateManagement(emfXacml, thisPdpId); + PMStandbyStateChangeNotifier pmStandbyStateChangeNotifier = new PMStandbyStateChangeNotifier(); + sm.addObserver(pmStandbyStateChangeNotifier); + + // Artificially putting a PDP into service is really a two step process, 1) + // inserting it as designated and 2) promoting it so that its standbyStatus + // is providing service. + + PolicyLogger.debug("snNewInstall: Running policy-management.Main class"); + PolicyManagementRunner policyManagementRunner = new PolicyManagementRunner(); + policyManagementRunner.start(); + + PolicyLogger.debug("snNewInstall: Runner started; Sleeping " + + interruptRecoveryTime + "ms before promoting PDP=" + + thisPdpId); + Thread.sleep(interruptRecoveryTime); + + PolicyLogger.debug("snNewInstall: Promoting PDP=" + thisPdpId); + sm.promote(); + + String standbyStatus = sm.getStandbyStatus(thisPdpId); + PolicyLogger.debug("snNewInstall: Before locking, PDP=" + thisPdpId + " has standbyStatus=" + + standbyStatus); + + PolicyLogger.debug("snNewInstall: Locking sm"); + sm.lock(); + + Thread.sleep(interruptRecoveryTime); + /* + * Verify that the PDP is no longer designated. + */ + droolsPdpEntity = conn.getPdp(thisPdpId); + PolicyLogger.debug("snNewInstall: After lock sm.lock() invoked, DESIGNATED=" + + droolsPdpEntity.isDesignated() + " for PDP=" + thisPdpId); + assertTrue(droolsPdpEntity.isDesignated() == false); + + PolicyLogger.debug("snNewInstall: Stopping policyManagementRunner"); + policyManagementRunner.stopRunner(); + + PolicyLogger.debug("\n\nsnNewInstall: Exiting\n\n"); + Thread.sleep(interruptRecoveryTime); + + //******************************************** + + PolicyLogger.debug("\n\nsnNewInstall: Exit\n\n"); + } + + public void snNewInstallBadDepData() throws Exception{ + PolicyLogger.debug("\n\nsnNewInstallBadDepData: Entry\n\n"); + cleanDroolsDB(); + cleanXacmlDB(); + + //******************************************* + + PolicyLogger.debug("snNewInstallBadDepData: Reading IntegrityMonitor_BadDependencyData.properties"); + Properties integrityMonitorProperties = new Properties(); + integrityMonitorProperties.load(new FileInputStream(new File( + "src/test/server/config/IntegrityMonitor_BadDependencyData.properties"))); + IntegrityMonitorProperties.initProperties(integrityMonitorProperties); + String thisPdpId = IntegrityMonitorProperties + .getProperty(IntegrityMonitorProperties.PDP_INSTANCE_ID); + + PolicyLogger.debug("snNewInstallBadDepData: Reading xacmlPersistenceProperties"); + Properties xacmlPersistenceProperties = new Properties(); + xacmlPersistenceProperties.load(new FileInputStream(new File( + "src/test/server/config/xacmlPersistence.properties"))); + XacmlPersistenceProperties.initProperties(xacmlPersistenceProperties); + + PolicyLogger.debug("snNewInstallBadDepData: Creating emfXacml"); + EntityManagerFactory emfXacml = Persistence.createEntityManagerFactory( + "junitXacmlPU", xacmlPersistenceProperties); + + PolicyLogger.debug("snNewInstallBadDepData: Reading droolsPersistenceProperties"); + Properties droolsPersistenceProperties = new Properties(); + droolsPersistenceProperties.load(new FileInputStream(new File( + "src/test/server/config/droolsPersistence.properties"))); + DroolsPersistenceProperties.initProperties(droolsPersistenceProperties); + + PolicyLogger.debug("snNewInstallBadDepData: Creating emfDrools"); + EntityManagerFactory emfDrools = Persistence.createEntityManagerFactory( + "junitDroolsPU", droolsPersistenceProperties); + + DroolsPdpsConnector conn = new JpaDroolsPdpsConnector(emfDrools); + + PolicyLogger.debug("snNewInstallBadDepData: Inserting PDP=" + thisPdpId + " as designated"); + DroolsPdp pdp = new DroolsPdpImpl(thisPdpId, true, 4, new Date()); + conn.insertPdp(pdp); + DroolsPdpEntity droolsPdpEntity = conn.getPdp(thisPdpId); + //PolicyLogger.debug + System.out.println + ("\n\nsnNewInstallBadDepData: After insertion, DESIGNATED=" + + droolsPdpEntity.isDesignated() + " for PDP=" + thisPdpId + "\n\n********************"); + assertTrue(droolsPdpEntity.isDesignated() == true); + + /* + * When the Standby Status changes (from providingservice) to hotstandby + * or coldstandby,the Active/Standby selection algorithm must stand down + * if thePDP-D is currently the lead/active node and allow another PDP-D + * to take over. + */ + PolicyLogger.debug("snNewInstall: Instantiating stateManagement object"); + StateManagement sm = new StateManagement(emfXacml, thisPdpId); + PMStandbyStateChangeNotifier pmStandbyStateChangeNotifier = new PMStandbyStateChangeNotifier(); + sm.addObserver(pmStandbyStateChangeNotifier); + + // Artificially putting a PDP into service is really a two step process, 1) + // inserting it as designated and 2) promoting it so that its standbyStatus + // is providing service. + + PolicyLogger.debug("snNewInstall: Running policy-management.Main class"); + PolicyManagementRunner policyManagementRunner = new PolicyManagementRunner(); + policyManagementRunner.start(); + + PolicyLogger.debug("snNewInstall: Runner started; Sleeping " + + interruptRecoveryTime + "ms before promoting PDP=" + + thisPdpId); + Thread.sleep(interruptRecoveryTime); + + PolicyLogger.debug("snNewInstall: Promoting PDP=" + thisPdpId); + sm.promote(); + + String standbyStatus = sm.getStandbyStatus(thisPdpId); + PolicyLogger.debug("snNewInstall: Before locking, PDP=" + thisPdpId + " has standbyStatus=" + + standbyStatus); + + /* + * Verify that the PDP is no longer designated. + */ + droolsPdpEntity = conn.getPdp(thisPdpId); + PolicyLogger.debug("snNewInstall: After lock sm.lock() invoked, DESIGNATED=" + + droolsPdpEntity.isDesignated() + " for PDP=" + thisPdpId); + assertTrue(droolsPdpEntity.isDesignated() == false); + + PolicyLogger.debug("snNewInstall: Stopping policyManagementRunner"); + policyManagementRunner.stopRunner(); + + PolicyLogger.debug("\n\nsnNewInstall: Exiting\n\n"); + Thread.sleep(interruptRecoveryTime); + + //******************************************** + + PolicyLogger.debug("\n\nsnNewInstallBadDepData: Exit\n\n"); + } + + public void snRecoveryFromBadDepData() throws Exception{ + + } + + public void snLock() throws Exception { + + } + + public void snLockRestart() throws Exception { + + } + + public void snUnlock() throws Exception { + + } + + public void snUnlockRestart() throws Exception { + + } + + /* + * Two Nodes tests + */ + public void tnNewInstall() throws Exception { + + } + + public void tnLockActive() throws Exception { + + } + + public void tnUnlockColdStandby() throws Exception { + + } + + public void tnFailActive() throws Exception { + + } + + public void tnRecoverFailed() throws Exception { + + } + + /* + * Two Sites, Two Nodes Each Site tests + */ + + public void tstnNewInstall() throws Exception { + + } + + public void tstnLock1Site1() throws Exception { + + } + + public void tstnLock2Site1() throws Exception { + + } + + public void tstnFailActiveSite2() throws Exception { + + } + + public void tstnRecoverFailedSite2() throws Exception { + + } + + public void tstnUnlockSite1() throws Exception { + + } + + public void tstnFailSite2() throws Exception { + + } + + + @Ignore + @Test + public void testColdStandby() throws Exception { + + PolicyLogger.debug("\n\ntestColdStandby: Entering\n\n"); + + PolicyLogger.debug("testColdStandby: Reading IntegrityMonitorProperties"); + Properties integrityMonitorProperties = new Properties(); + integrityMonitorProperties.load(new FileInputStream(new File( + "src/test/server/config/IntegrityMonitor.properties"))); + IntegrityMonitorProperties.initProperties(integrityMonitorProperties); + String thisPdpId = IntegrityMonitorProperties + .getProperty(IntegrityMonitorProperties.PDP_INSTANCE_ID); + + PolicyLogger.debug("testColdStandby: Reading xacmlPersistenceProperties"); + Properties xacmlPersistenceProperties = new Properties(); + xacmlPersistenceProperties.load(new FileInputStream(new File( + "src/test/server/config/xacmlPersistence.properties"))); + XacmlPersistenceProperties.initProperties(xacmlPersistenceProperties); + + PolicyLogger.debug("testColdStandby: Creating emfXacml"); + EntityManagerFactory emfXacml = Persistence.createEntityManagerFactory( + "junitXacmlPU", xacmlPersistenceProperties); + + PolicyLogger.debug("testColdStandby: Reading droolsPersistenceProperties"); + Properties droolsPersistenceProperties = new Properties(); + droolsPersistenceProperties.load(new FileInputStream(new File( + "src/test/server/config/droolsPersistence.properties"))); + DroolsPersistenceProperties.initProperties(droolsPersistenceProperties); + + PolicyLogger.debug("testColdStandby: Creating emfDrools"); + EntityManagerFactory emfDrools = Persistence.createEntityManagerFactory( + "junitDroolsPU", droolsPersistenceProperties); + + DroolsPdpsConnector conn = new JpaDroolsPdpsConnector(emfDrools); + + PolicyLogger.debug("testColdStandby: Cleaning up tables"); + conn.deleteAllSessions(); + conn.deleteAllPdps(); + + PolicyLogger.debug("testColdStandby: Inserting PDP=" + thisPdpId + " as designated"); + DroolsPdp pdp = new DroolsPdpImpl(thisPdpId, true, 4, new Date()); + conn.insertPdp(pdp); + DroolsPdpEntity droolsPdpEntity = conn.getPdp(thisPdpId); + PolicyLogger.debug("testColdStandby: After insertion, DESIGNATED=" + + droolsPdpEntity.isDesignated() + " for PDP=" + thisPdpId); + assertTrue(droolsPdpEntity.isDesignated() == true); + + /* + * When the Standby Status changes (from providingservice) to hotstandby + * or coldstandby,the Active/Standby selection algorithm must stand down + * if thePDP-D is currently the lead/active node and allow another PDP-D + * to take over. + * + * It must also call lock on all engines in the engine management. + * + * Yes, this is kludgy, but we have a chicken and egg problem here: we + * need a StateManagement object to invoke the + * deleteAllStateManagementEntities method. + */ + PolicyLogger.debug("testColdStandby: Instantiating stateManagement object"); + StateManagement sm = new StateManagement(emfXacml, "dummy"); + sm.deleteAllStateManagementEntities(); + sm = new StateManagement(emfXacml, thisPdpId); + PMStandbyStateChangeNotifier pmStandbyStateChangeNotifier = new PMStandbyStateChangeNotifier(); + sm.addObserver(pmStandbyStateChangeNotifier); + + // Artificially putting a PDP into service is really a two step process, 1) + // inserting it as designated and 2) promoting it so that its standbyStatus + // is providing service. + + PolicyLogger.debug("testColdStandby: Running policy-management.Main class"); + PolicyManagementRunner policyManagementRunner = new PolicyManagementRunner(); + policyManagementRunner.start(); + + PolicyLogger.debug("testColdStandby: Runner started; Sleeping " + + interruptRecoveryTime + "ms before promoting PDP=" + + thisPdpId); + Thread.sleep(interruptRecoveryTime); + + PolicyLogger.debug("testColdStandby: Promoting PDP=" + thisPdpId); + sm.promote(); + + String standbyStatus = sm.getStandbyStatus(thisPdpId); + PolicyLogger.debug("testColdStandby: Before locking, PDP=" + thisPdpId + " has standbyStatus=" + + standbyStatus); + + PolicyLogger.debug("testColdStandby: Locking sm"); + sm.lock(); + + Thread.sleep(interruptRecoveryTime); + /* + * Verify that the PDP is no longer designated. + */ + droolsPdpEntity = conn.getPdp(thisPdpId); + PolicyLogger.debug("testColdStandby: After lock sm.lock() invoked, DESIGNATED=" + + droolsPdpEntity.isDesignated() + " for PDP=" + thisPdpId); + assertTrue(droolsPdpEntity.isDesignated() == false); + + PolicyLogger.debug("testColdStandby: Stopping policyManagementRunner"); + policyManagementRunner.stopRunner(); + + PolicyLogger.debug("\n\ntestColdStandby: Exiting\n\n"); + Thread.sleep(interruptRecoveryTime); + + } + + /* + * Tests hot standby when there is only one PDP. + */ + @Ignore + @Test + public void testHotStandby1() throws Exception { + + PolicyLogger.debug("\n\ntestHotStandby1: Entering\n\n"); + + PolicyLogger.debug("testHotStandby1: Reading IntegrityMonitorProperties"); + Properties integrityMonitorProperties = new Properties(); + integrityMonitorProperties.load(new FileInputStream(new File( + "src/test/server/config/IntegrityMonitor.properties"))); + IntegrityMonitorProperties.initProperties(integrityMonitorProperties); + String thisPdpId = IntegrityMonitorProperties + .getProperty(IntegrityMonitorProperties.PDP_INSTANCE_ID); + + PolicyLogger.debug("testHotStandby1: Reading xacmlPersistenceProperties"); + Properties xacmlPersistenceProperties = new Properties(); + xacmlPersistenceProperties.load(new FileInputStream(new File( + "src/test/server/config/xacmlPersistence.properties"))); + XacmlPersistenceProperties.initProperties(xacmlPersistenceProperties); + + PolicyLogger.debug("testHotStandby1: Creating emfXacml"); + EntityManagerFactory emfXacml = Persistence.createEntityManagerFactory( + "junitXacmlPU", xacmlPersistenceProperties); + + PolicyLogger.debug("testHotStandby1: Reading droolsPersistenceProperties"); + Properties droolsPersistenceProperties = new Properties(); + droolsPersistenceProperties.load(new FileInputStream(new File( + "src/test/server/config/droolsPersistence.properties"))); + DroolsPersistenceProperties.initProperties(droolsPersistenceProperties); + + PolicyLogger.debug("testHotStandby1: Creating emfDrools"); + EntityManagerFactory emfDrools = Persistence.createEntityManagerFactory( + "junitDroolsPU", droolsPersistenceProperties); + + DroolsPdpsConnector conn = new JpaDroolsPdpsConnector(emfDrools); + + PolicyLogger.debug("testHotStandby1: Cleaning up tables"); + conn.deleteAllSessions(); + conn.deleteAllPdps(); + + /* + * Insert this PDP as not designated. Initial standby state will be + * either null or cold standby. Demoting should transit state to + * hot standby. + */ + PolicyLogger.debug("testHotStandby1: Inserting PDP=" + thisPdpId + " as not designated"); + Date yesterday = DateUtils.addDays(new Date(), -1); + DroolsPdpImpl pdp = new DroolsPdpImpl(thisPdpId, false, 4, yesterday); + conn.insertPdp(pdp); + DroolsPdpEntity droolsPdpEntity = conn.getPdp(thisPdpId); + PolicyLogger.debug("testHotStandby1: After insertion, PDP=" + thisPdpId + " has DESIGNATED=" + + droolsPdpEntity.isDesignated()); + assertTrue(droolsPdpEntity.isDesignated() == false); + + PolicyLogger.debug("testHotStandby1: Instantiating stateManagement object"); + StateManagement sm = new StateManagement(emfXacml, "dummy"); + sm.deleteAllStateManagementEntities(); + sm = new StateManagement(emfXacml, thisPdpId); + PMStandbyStateChangeNotifier pmStandbyStateChangeNotifier = new PMStandbyStateChangeNotifier(); + sm.addObserver(pmStandbyStateChangeNotifier); + + PolicyLogger.debug("testHotStandby1: Demoting PDP=" + thisPdpId); + // demoting should cause state to transit to hotstandby + sm.demote(); + + PolicyLogger.debug("testHotStandby1: Running policy-management.Main class"); + PolicyManagementRunner policyManagementRunner = new PolicyManagementRunner(); + policyManagementRunner.start(); + + PolicyLogger.debug("testHotStandby1: Sleeping " + + sleepTime + + "ms, to allow JpaDroolsPdpsConnector time to check droolspdpentity table"); + Thread.sleep(sleepTime); + + /* + * Verify that this formerly un-designated PDP in HOT_STANDBY is now designated and providing service. + */ + droolsPdpEntity = conn.getPdp(thisPdpId); + PolicyLogger.debug("testHotStandby1: After sm.demote() invoked, DESIGNATED=" + + droolsPdpEntity.isDesignated() + " for PDP=" + thisPdpId); + assertTrue(droolsPdpEntity.isDesignated() == true); + String standbyStatus = sm.getStandbyStatus(thisPdpId); + PolicyLogger.debug("testHotStandby1: After demotion, PDP=" + thisPdpId + " has standbyStatus=" + + standbyStatus); + assertTrue(standbyStatus != null && standbyStatus.equals(StateManagement.PROVIDING_SERVICE)); + + PolicyLogger.debug("testHotStandby1: Stopping policyManagementRunner"); + policyManagementRunner.stopRunner(); + + PolicyLogger.debug("\n\ntestHotStandby1: Exiting\n\n"); + Thread.sleep(interruptRecoveryTime); + + } + + /* + * Tests hot standby when two PDPs are involved. + */ + @Ignore + @Test + public void testHotStandby2() throws Exception { + + PolicyLogger.debug("\n\ntestHotStandby2: Entering\n\n"); + + PolicyLogger.debug("testHotStandby2: Reading IntegrityMonitorProperties"); + Properties integrityMonitorProperties = new Properties(); + integrityMonitorProperties.load(new FileInputStream(new File( + "src/test/server/config/IntegrityMonitor.properties"))); + IntegrityMonitorProperties.initProperties(integrityMonitorProperties); + String thisPdpId = IntegrityMonitorProperties + .getProperty(IntegrityMonitorProperties.PDP_INSTANCE_ID); + + PolicyLogger.debug("testHotStandby2: Reading xacmlPersistenceProperties"); + Properties xacmlPersistenceProperties = new Properties(); + xacmlPersistenceProperties.load(new FileInputStream(new File( + "src/test/server/config/xacmlPersistence.properties"))); + XacmlPersistenceProperties.initProperties(xacmlPersistenceProperties); + + PolicyLogger.debug("testHotStandby2: Creating emfXacml"); + EntityManagerFactory emfXacml = Persistence.createEntityManagerFactory( + "junitXacmlPU", xacmlPersistenceProperties); + + PolicyLogger.debug("testHotStandby2: Reading droolsPersistenceProperties"); + Properties droolsPersistenceProperties = new Properties(); + droolsPersistenceProperties.load(new FileInputStream(new File( + "src/test/server/config/droolsPersistence.properties"))); + DroolsPersistenceProperties.initProperties(droolsPersistenceProperties); + + PolicyLogger.debug("testHotStandby2: Creating emfDrools"); + EntityManagerFactory emfDrools = Persistence.createEntityManagerFactory( + "junitDroolsPU", droolsPersistenceProperties); + + DroolsPdpsConnector conn = new JpaDroolsPdpsConnector(emfDrools); + + PolicyLogger.debug("testHotStandby2: Cleaning up tables"); + conn.deleteAllSessions(); + conn.deleteAllPdps(); + + /* + * Insert a PDP that's designated but not current. + */ + String activePdpId = "pdp2"; + PolicyLogger.debug("testHotStandby2: Inserting PDP=" + activePdpId + " as stale, designated PDP"); + Date yesterday = DateUtils.addDays(new Date(), -1); + DroolsPdp pdp = new DroolsPdpImpl(activePdpId, true, 4, yesterday); + conn.insertPdp(pdp); + DroolsPdpEntity droolsPdpEntity = conn.getPdp(activePdpId); + PolicyLogger.debug("testHotStandby2: After insertion, PDP=" + activePdpId + ", which is not current, has DESIGNATED=" + + droolsPdpEntity.isDesignated()); + assertTrue(droolsPdpEntity.isDesignated() == true); + + /* + * Promote the designated PDP. + * + * We have a chicken and egg problem here: we need a StateManagement + * object to invoke the deleteAllStateManagementEntities method. + */ + PolicyLogger.debug("testHotStandy2: Promoting PDP=" + activePdpId); + StateManagement sm = new StateManagement(emfXacml, "dummy"); + sm.deleteAllStateManagementEntities(); + sm = new StateManagement(emfXacml, activePdpId); + PMStandbyStateChangeNotifier pmStandbyStateChangeNotifier = new PMStandbyStateChangeNotifier(); + sm.addObserver(pmStandbyStateChangeNotifier); + + // Artificially putting a PDP into service is really a two step process, 1) + // inserting it as designated and 2) promoting it so that its standbyStatus + // is providing service. + + /* + * Insert this PDP as not designated. Initial standby state will be + * either null or cold standby. Demoting should transit state to + * hot standby. + */ + PolicyLogger.debug("testHotStandby2: Inserting PDP=" + thisPdpId + " as not designated"); + pdp = new DroolsPdpImpl(thisPdpId, false, 4, yesterday); + conn.insertPdp(pdp); + droolsPdpEntity = conn.getPdp(thisPdpId); + PolicyLogger.debug("testHotStandby2: After insertion, PDP=" + thisPdpId + " has DESIGNATED=" + + droolsPdpEntity.isDesignated()); + assertTrue(droolsPdpEntity.isDesignated() == false); + + PolicyLogger.debug("testHotStandby2: Demoting PDP=" + thisPdpId); + StateManagement sm2 = new StateManagement(emfXacml, thisPdpId); + sm2.addObserver(pmStandbyStateChangeNotifier); + + PolicyLogger.debug("testHotStandby2: Running policy-management.Main class"); + PolicyManagementRunner policyManagementRunner = new PolicyManagementRunner(); + policyManagementRunner.start(); + + PolicyLogger.debug("testHotStandby2: Runner started; Sleeping " + + interruptRecoveryTime + "ms before promoting/demoting"); + Thread.sleep(interruptRecoveryTime); + + PolicyLogger.debug("testHotStandby2: Runner started; promoting PDP=" + activePdpId); + sm.promote(); + String standbyStatus = sm.getStandbyStatus(activePdpId); + PolicyLogger.debug("testHotStandby2: After promoting, PDP=" + activePdpId + " has standbyStatus=" + + standbyStatus); + + // demoting PDP should ensure that state transits to hotstandby + PolicyLogger.debug("testHotStandby2: Runner started; demoting PDP=" + thisPdpId); + sm2.demote(); + standbyStatus = sm.getStandbyStatus(thisPdpId); + PolicyLogger.debug("testHotStandby2: After demoting, PDP=" + thisPdpId + " has standbyStatus=" + + standbyStatus); + + PolicyLogger.debug("testHotStandby2: Sleeping " + + sleepTime + + "ms, to allow JpaDroolsPdpsConnector time to check droolspdpentity table"); + Thread.sleep(sleepTime); + + /* + * Verify that this PDP, demoted to HOT_STANDBY, is now + * re-designated and providing service. + */ + droolsPdpEntity = conn.getPdp(thisPdpId); + PolicyLogger.debug("testHotStandby2: After demoting PDP=" + activePdpId + + ", DESIGNATED=" + droolsPdpEntity.isDesignated() + + " for PDP=" + thisPdpId); + assertTrue(droolsPdpEntity.isDesignated() == true); + standbyStatus = sm2.getStandbyStatus(thisPdpId); + PolicyLogger.debug("testHotStandby2: After demoting PDP=" + activePdpId + + ", PDP=" + thisPdpId + " has standbyStatus=" + standbyStatus); + assertTrue(standbyStatus != null + && standbyStatus.equals(StateManagement.PROVIDING_SERVICE)); + + PolicyLogger.debug("testHotStandby2: Stopping policyManagementRunner"); + policyManagementRunner.stopRunner(); + + PolicyLogger.debug("\n\ntestHotStandby2: Exiting\n\n"); + Thread.sleep(interruptRecoveryTime); + + } + + /* + * 1) Inserts and designates this PDP, then verifies that startTransaction + * is successful. + * + * 2) Demotes PDP, and verifies that because there is only one PDP, it will + * be immediately re-promoted, thus allowing startTransaction to be + * successful. + * + * 3) Locks PDP and verifies that startTransaction results in + * AdministrativeStateException. + * + * 4) Unlocks PDP and verifies that startTransaction results in + * StandbyStatusException. + * + * 5) Promotes PDP and verifies that startTransaction is once again + * successful. + */ + @Ignore + @Test + public void testLocking1() throws Exception { + + PolicyLogger.debug("testLocking1: Reading IntegrityMonitorProperties"); + Properties integrityMonitorProperties = new Properties(); + integrityMonitorProperties.load(new FileInputStream(new File( + "src/test/server/config/IntegrityMonitor.properties"))); + IntegrityMonitorProperties.initProperties(integrityMonitorProperties); + String thisPdpId = IntegrityMonitorProperties + .getProperty(IntegrityMonitorProperties.PDP_INSTANCE_ID); + + PolicyLogger.debug("testLocking1: Reading xacmlPersistenceProperties"); + Properties xacmlPersistenceProperties = new Properties(); + xacmlPersistenceProperties.load(new FileInputStream(new File( + "src/test/server/config/xacmlPersistence.properties"))); + XacmlPersistenceProperties.initProperties(xacmlPersistenceProperties); + + PolicyLogger.debug("testLocking1: Creating emfXacml"); + EntityManagerFactory emfXacml = Persistence.createEntityManagerFactory( + "junitXacmlPU", xacmlPersistenceProperties); + + PolicyLogger.debug("testLocking1: Reading droolsPersistenceProperties"); + Properties droolsPersistenceProperties = new Properties(); + droolsPersistenceProperties.load(new FileInputStream(new File( + "src/test/server/config/droolsPersistence.properties"))); + DroolsPersistenceProperties.initProperties(droolsPersistenceProperties); + + PolicyLogger.debug("testLocking1: Creating emfDrools"); + EntityManagerFactory emfDrools = Persistence.createEntityManagerFactory( + "junitDroolsPU", droolsPersistenceProperties); + + DroolsPdpsConnector conn = new JpaDroolsPdpsConnector(emfDrools); + + PolicyLogger.debug("testLocking1: Cleaning up tables"); + conn.deleteAllSessions(); + conn.deleteAllPdps(); + + /* + * Insert this PDP as designated. Initial standby state will be + * either null or cold standby. + */ + PolicyLogger.debug("testLocking1: Inserting PDP=" + thisPdpId + " as designated"); + DroolsPdpImpl pdp = new DroolsPdpImpl(thisPdpId, true, 4, new Date()); + conn.insertPdp(pdp); + DroolsPdpEntity droolsPdpEntity = conn.getPdp(thisPdpId); + PolicyLogger.debug("testLocking1: After insertion, PDP=" + thisPdpId + " has DESIGNATED=" + + droolsPdpEntity.isDesignated()); + assertTrue(droolsPdpEntity.isDesignated() == true); + + PolicyLogger.debug("testLocking1: Instantiating stateManagement object"); + StateManagement sm = new StateManagement(emfXacml, "dummy"); + sm.deleteAllStateManagementEntities(); + sm = new StateManagement(emfXacml, thisPdpId); + PMStandbyStateChangeNotifier pmStandbyStateChangeNotifier = new PMStandbyStateChangeNotifier(); + sm.addObserver(pmStandbyStateChangeNotifier); + + PolicyLogger.debug("testLocking1: Running policy-management.Main class, designated=" + + conn.getPdp(thisPdpId).isDesignated()); + PolicyManagementRunner policyManagementRunner = new PolicyManagementRunner(); + policyManagementRunner.start(); + + PolicyLogger.debug("testLocking1: Runner started; Sleeping " + + interruptRecoveryTime + "ms before promoting PDP=" + + thisPdpId); + Thread.sleep(interruptRecoveryTime); + + PolicyLogger.debug("testLocking1: Promoting PDP=" + thisPdpId); + sm.promote(); + + PolicyLogger.debug("testLocking1: Sleeping " + + sleepTime + + "ms, to allow time for policy-management.Main class to come up, designated=" + + conn.getPdp(thisPdpId).isDesignated()); + Thread.sleep(sleepTime); + + PolicyLogger.debug("testLocking1: Waking up and invoking startTransaction on active PDP=" + + thisPdpId + + ", designated=" + + conn.getPdp(thisPdpId).isDesignated()); + DroolsPDPIntegrityMonitor droolsPdpIntegrityMonitor = (DroolsPDPIntegrityMonitor) IntegrityMonitor + .getInstance(); + try { + droolsPdpIntegrityMonitor.startTransaction(); + droolsPdpIntegrityMonitor.endTransaction(); + PolicyLogger.debug("testLocking1: As expected, transaction successful"); + } catch (AdministrativeStateException e) { + PolicyLogger.error("testLocking1: Unexpectedly caught AdministrativeStateException, message=" + e.getMessage()); + assertTrue(false); + } catch (StandbyStatusException e) { + PolicyLogger.error("testLocking1: Unexpectedly caught StandbyStatusException, message=" + e.getMessage()); + assertTrue(false); + } catch (Exception e) { + PolicyLogger.error("testLocking1: Unexpectedly caught Exception, message=" + e.getMessage()); + assertTrue(false); + } + + // demoting should cause state to transit to hotstandby, followed by re-promotion, + // since there is only one PDP. + PolicyLogger.debug("testLocking1: demoting PDP=" + thisPdpId); + sm = droolsPdpIntegrityMonitor.getStateManager(); + sm.demote(); + + PolicyLogger.debug("testLocking1: sleeping" + electionWaitSleepTime + + " to allow election handler to re-promote PDP=" + thisPdpId); + Thread.sleep(electionWaitSleepTime); + + PolicyLogger.debug("testLocking1: Invoking startTransaction on re-promoted PDP=" + + thisPdpId + + ", designated=" + + conn.getPdp(thisPdpId).isDesignated()); + try { + droolsPdpIntegrityMonitor.startTransaction(); + droolsPdpIntegrityMonitor.endTransaction(); + PolicyLogger.debug("testLocking1: As expected, transaction successful"); + } catch (AdministrativeStateException e) { + PolicyLogger.error("testLocking1: Unexpectedly caught AdministrativeStateException, message=" + e.getMessage()); + assertTrue(false); + } catch (StandbyStatusException e) { + PolicyLogger.error("testLocking1: Unexpectedly caught StandbyStatusException, message=" + e.getMessage()); + assertTrue(false); + } catch (Exception e) { + PolicyLogger.error("testLocking1: Unexpectedly caught Exception, message=" + e.getMessage()); + assertTrue(false); + } + + // locking should cause state to transit to cold standby + PolicyLogger.debug("testLocking1: locking PDP=" + thisPdpId); + sm.lock(); + + // Just to avoid any race conditions, sleep a little after locking + PolicyLogger.debug("testLocking1: Sleeping a few millis after locking, to avoid race condition"); + Thread.sleep(100); + + PolicyLogger.debug("testLocking1: Invoking startTransaction on locked PDP=" + + thisPdpId + + ", designated=" + + conn.getPdp(thisPdpId).isDesignated()); + try { + droolsPdpIntegrityMonitor.startTransaction(); + PolicyLogger.error("testLocking1: startTransaction unexpectedly successful"); + assertTrue(false); + } catch (AdministrativeStateException e) { + PolicyLogger.debug("testLocking1: As expected, caught AdministrativeStateException, message=" + e.getMessage()); + } catch (StandbyStatusException e) { + PolicyLogger.error("testLocking1: Unexpectedly caught StandbyStatusException, message=" + e.getMessage()); + assertTrue(false); + } catch (Exception e) { + PolicyLogger.error("testLocking1: Unexpectedly caught Exception, message=" + e.getMessage()); + assertTrue(false); + } finally { + droolsPdpIntegrityMonitor.endTransaction(); + } + + // unlocking should cause state to transit to hot standby + PolicyLogger.debug("testLocking1: unlocking PDP=" + thisPdpId); + sm.unlock(); + + // Just to avoid any race conditions, sleep a little after locking + PolicyLogger.debug("testLocking1: Sleeping a few millis after unlocking, to avoid race condition"); + Thread.sleep(100); + + PolicyLogger.debug("testLocking1: Invoking startTransaction on unlocked PDP=" + + thisPdpId + + ", designated=" + + conn.getPdp(thisPdpId).isDesignated()); + try { + droolsPdpIntegrityMonitor.startTransaction(); + PolicyLogger.error("testLocking1: startTransaction unexpectedly successful"); + assertTrue(false); + } catch (AdministrativeStateException e) { + PolicyLogger.error("testLocking1: Unexpectedly caught AdministrativeStateException, message=" + e.getMessage()); + assertTrue(false); + } catch (StandbyStatusException e) { + PolicyLogger.debug("testLocking1: As expected, caught StandbyStatusException, message=" + e.getMessage()); + } catch (Exception e) { + PolicyLogger.error("testLocking1: Unexpectedly caught Exception, message=" + e.getMessage()); + assertTrue(false); + } finally { + droolsPdpIntegrityMonitor.endTransaction(); + } + + // promoting should cause state to transit to providing service + PolicyLogger.debug("testLocking1: promoting PDP=" + thisPdpId); + sm.promote(); + + // Just to avoid any race conditions, sleep a little after promoting + PolicyLogger.debug("testLocking1: Sleeping a few millis after promoting, to avoid race condition"); + Thread.sleep(100); + + PolicyLogger.debug("testLocking1: Invoking startTransaction on promoted PDP=" + + thisPdpId + + ", designated=" + + conn.getPdp(thisPdpId).isDesignated()); + try { + droolsPdpIntegrityMonitor.startTransaction(); + droolsPdpIntegrityMonitor.endTransaction(); + PolicyLogger.debug("testLocking1: As expected, transaction successful"); + } catch (AdministrativeStateException e) { + PolicyLogger.error("testLocking1: Unexpectedly caught AdministrativeStateException, message=" + e.getMessage()); + assertTrue(false); + } catch (StandbyStatusException e) { + PolicyLogger.error("testLocking1: Unexpectedly caught StandbyStatusException, message=" + e.getMessage()); + assertTrue(false); + } catch (Exception e) { + PolicyLogger.error("testLocking1: Unexpectedly caught Exception, message=" + e.getMessage()); + assertTrue(false); + } + + PolicyLogger.debug("testLocking1: Stopping policyManagementRunner"); + policyManagementRunner.stopRunner(); + + PolicyLogger.debug("\n\ntestLocking1: Exiting\n\n"); + Thread.sleep(interruptRecoveryTime); + + } + + /* + * 1) Inserts and designates this PDP, then verifies that startTransaction + * is successful. + * + * 2) Inserts another PDP in hotstandby. + * + * 3) Demotes this PDP, and verifies 1) that other PDP is not promoted (because one + * PDP cannot promote another PDP) and 2) that this PDP is re-promoted. + */ + @Ignore + @Test + public void testLocking2() throws Exception { + + PolicyLogger.debug("\n\ntestLocking2: Entering\n\n"); + + PolicyLogger.debug("testLocking2: Reading IntegrityMonitorProperties"); + Properties integrityMonitorProperties = new Properties(); + integrityMonitorProperties.load(new FileInputStream(new File( + "src/test/server/config/IntegrityMonitor.properties"))); + IntegrityMonitorProperties.initProperties(integrityMonitorProperties); + String thisPdpId = IntegrityMonitorProperties + .getProperty(IntegrityMonitorProperties.PDP_INSTANCE_ID); + + PolicyLogger.debug("testLocking2: Reading xacmlPersistenceProperties"); + Properties xacmlPersistenceProperties = new Properties(); + xacmlPersistenceProperties.load(new FileInputStream(new File( + "src/test/server/config/xacmlPersistence.properties"))); + XacmlPersistenceProperties.initProperties(xacmlPersistenceProperties); + + PolicyLogger.debug("testLocking2: Creating emfXacml"); + EntityManagerFactory emfXacml = Persistence.createEntityManagerFactory( + "junitXacmlPU", xacmlPersistenceProperties); + + PolicyLogger.debug("testLocking2: Reading droolsPersistenceProperties"); + Properties droolsPersistenceProperties = new Properties(); + droolsPersistenceProperties.load(new FileInputStream(new File( + "src/test/server/config/droolsPersistence.properties"))); + DroolsPersistenceProperties.initProperties(droolsPersistenceProperties); + + PolicyLogger.debug("testLocking2: Creating emfDrools"); + EntityManagerFactory emfDrools = Persistence.createEntityManagerFactory( + "junitDroolsPU", droolsPersistenceProperties); + + DroolsPdpsConnector conn = new JpaDroolsPdpsConnector(emfDrools); + + PolicyLogger.debug("testLocking2: Cleaning up tables"); + conn.deleteAllSessions(); + conn.deleteAllPdps(); + + /* + * Insert this PDP as designated. Initial standby state will be + * either null or cold standby. Demoting should transit state to + * hot standby. + */ + PolicyLogger.debug("testLocking2: Inserting PDP=" + thisPdpId + " as designated"); + DroolsPdpImpl pdp = new DroolsPdpImpl(thisPdpId, true, 3, new Date()); + conn.insertPdp(pdp); + DroolsPdpEntity droolsPdpEntity = conn.getPdp(thisPdpId); + PolicyLogger.debug("testLocking2: After insertion, PDP=" + thisPdpId + " has DESIGNATED=" + + droolsPdpEntity.isDesignated()); + assertTrue(droolsPdpEntity.isDesignated() == true); + + PolicyLogger.debug("testLocking2: Instantiating stateManagement object and promoting PDP=" + thisPdpId); + StateManagement sm = new StateManagement(emfXacml, "dummy"); + sm.deleteAllStateManagementEntities(); + sm = new StateManagement(emfXacml, thisPdpId); + PMStandbyStateChangeNotifier pmStandbyStateChangeNotifier = new PMStandbyStateChangeNotifier(); + sm.addObserver(pmStandbyStateChangeNotifier); + + /* + * Insert another PDP as not designated. Initial standby state will be + * either null or cold standby. Demoting should transit state to + * hot standby. + */ + String standbyPdpId = "pdp2"; + PolicyLogger.debug("testLocking2: Inserting PDP=" + standbyPdpId + " as not designated"); + Date yesterday = DateUtils.addDays(new Date(), -1); + pdp = new DroolsPdpImpl(standbyPdpId, false, 4, yesterday); + conn.insertPdp(pdp); + droolsPdpEntity = conn.getPdp(standbyPdpId); + PolicyLogger.debug("testLocking2: After insertion, PDP=" + standbyPdpId + " has DESIGNATED=" + + droolsPdpEntity.isDesignated()); + assertTrue(droolsPdpEntity.isDesignated() == false); + + PolicyLogger.debug("testLocking2: Demoting PDP=" + standbyPdpId); + StateManagement sm2 = new StateManagement(emfXacml, standbyPdpId); + sm2.addObserver(pmStandbyStateChangeNotifier); + + PolicyLogger.debug("testLocking2: Running policy-management.Main class"); + PolicyManagementRunner policyManagementRunner = new PolicyManagementRunner(); + policyManagementRunner.start(); + + PolicyLogger.debug("testLocking2: Runner started; Sleeping " + + interruptRecoveryTime + "ms before promoting/demoting"); + Thread.sleep(interruptRecoveryTime); + + PolicyLogger.debug("testLocking2: Promoting PDP=" + thisPdpId); + sm.promote(); + + // demoting PDP should ensure that state transits to hotstandby + PolicyLogger.debug("testLocking2: Demoting PDP=" + standbyPdpId); + sm2.demote(); + + PolicyLogger.debug("testLocking2: Sleeping " + + sleepTime + + "ms, to allow time for policy-management.Main class to come up"); + Thread.sleep(sleepTime); + + PolicyLogger.debug("testLocking2: Waking up and invoking startTransaction on active PDP=" + + thisPdpId + + ", designated=" + + conn.getPdp(thisPdpId).isDesignated()); + DroolsPDPIntegrityMonitor droolsPdpIntegrityMonitor = (DroolsPDPIntegrityMonitor) IntegrityMonitor + .getInstance(); + try { + droolsPdpIntegrityMonitor.startTransaction(); + droolsPdpIntegrityMonitor.endTransaction(); + PolicyLogger.debug("testLocking2: As expected, transaction successful"); + } catch (AdministrativeStateException e) { + PolicyLogger.error("testLocking2: Unexpectedly caught AdministrativeStateException, message=" + e.getMessage()); + assertTrue(false); + } catch (StandbyStatusException e) { + PolicyLogger.error("testLocking2: Unexpectedly caught StandbyStatusException, message=" + e.getMessage()); + assertTrue(false); + } catch (Exception e) { + PolicyLogger.error("testLocking2: Unexpectedly caught Exception, message=" + e.getMessage()); + assertTrue(false); + } + + // demoting should cause state to transit to hotstandby followed by re-promotion. + PolicyLogger.debug("testLocking2: demoting PDP=" + thisPdpId); + sm = droolsPdpIntegrityMonitor.getStateManager(); + sm.demote(); + + PolicyLogger.debug("testLocking2: sleeping" + electionWaitSleepTime + + " to allow election handler to re-promote PDP=" + thisPdpId); + Thread.sleep(electionWaitSleepTime); + + PolicyLogger.debug("testLocking2: Waking up and invoking startTransaction on re-promoted PDP=" + + thisPdpId + ", designated=" + + conn.getPdp(thisPdpId).isDesignated()); + try { + droolsPdpIntegrityMonitor.startTransaction(); + droolsPdpIntegrityMonitor.endTransaction(); + PolicyLogger.debug("testLocking2: As expected, transaction successful"); + } catch (AdministrativeStateException e) { + PolicyLogger.error("testLocking2: Unexpectedly caught AdministrativeStateException, message=" + e.getMessage()); + assertTrue(false); + } catch (StandbyStatusException e) { + PolicyLogger.error("testLocking2: Unexpectedly caught StandbyStatusException, message=" + e.getMessage()); + assertTrue(false); + } catch (Exception e) { + PolicyLogger.error("testLocking2: Unexpectedly caught Exception, message=" + e.getMessage()); + assertTrue(false); + } + + PolicyLogger.debug("testLocking2: Verifying designated status for PDP=" + + standbyPdpId); + boolean standbyPdpDesignated = conn.getPdp(standbyPdpId).isDesignated(); + assertTrue(standbyPdpDesignated == false); + + PolicyLogger.debug("testLocking2: Stopping policyManagementRunner"); + policyManagementRunner.stopRunner(); + + PolicyLogger.debug("\n\ntestLocking2: Exiting\n\n"); + Thread.sleep(interruptRecoveryTime); + + } + + private class PolicyManagementRunner extends Thread { + + public void run() { + PolicyLogger.debug("PolicyManagementRunner.run: Entering"); + String args[] = { "src/main/server/config" }; + try { + Main.main(args); + } catch (Exception e) { + PolicyLogger + .debug("PolicyManagementRunner.run: Exception thrown from Main.main(), message=" + + e.getMessage()); + } + PolicyLogger.debug("PolicyManagementRunner.run: Exiting"); + } + + public void stopRunner() { + PolicyEngine.manager.shutdown(); + } + + } + +} diff --git a/policy-persistence/src/test/java/org/openecomp/policy/drools/controller/test/StandbyStateManagementTest.java b/policy-persistence/src/test/java/org/openecomp/policy/drools/controller/test/StandbyStateManagementTest.java new file mode 100644 index 00000000..af649866 --- /dev/null +++ b/policy-persistence/src/test/java/org/openecomp/policy/drools/controller/test/StandbyStateManagementTest.java @@ -0,0 +1,887 @@ +/*- + * ============LICENSE_START======================================================= + * policy-persistence + * ================================================================================ + * 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.controller.test; + +import static org.junit.Assert.assertTrue; + +import java.io.File; +import java.io.FileInputStream; +import java.util.Date; +import java.util.Properties; + +import javax.persistence.EntityManagerFactory; +import javax.persistence.Persistence; + +import org.junit.After; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Ignore; +import org.junit.Test; + +import org.openecomp.policy.common.logging.eelf.PolicyLogger; +import org.openecomp.policy.common.im.AdministrativeStateException; +import org.openecomp.policy.common.im.IntegrityMonitor; +import org.openecomp.policy.common.im.StandbyStatusException; +import org.openecomp.policy.common.im.StateManagement; +import org.openecomp.policy.drools.core.DroolsPDPIntegrityMonitor; +import org.openecomp.policy.drools.core.IntegrityMonitorProperties; +import org.openecomp.policy.drools.core.PolicyContainer; +import org.openecomp.policy.drools.im.PMStandbyStateChangeNotifier; +import org.openecomp.policy.drools.persistence.DroolsPdp; +import org.openecomp.policy.drools.persistence.DroolsPdpEntity; +import org.openecomp.policy.drools.persistence.DroolsPdpImpl; +import org.openecomp.policy.drools.persistence.DroolsPdpsConnector; +import org.openecomp.policy.drools.persistence.JpaDroolsPdpsConnector; +import org.openecomp.policy.drools.persistence.DroolsPersistenceProperties; +import org.openecomp.policy.drools.persistence.XacmlPersistenceProperties; +import org.openecomp.policy.drools.system.Main; +import org.openecomp.policy.drools.system.PolicyEngine; + +import org.apache.commons.lang3.time.DateUtils; + +/* + * Cloned from StandbyStateManagement.java in support of US673632. + * See MultiSite_v1-10.ppt, slide 38 + */ +public class StandbyStateManagementTest { + + /* + * Currently, the DroolsPdpsElectionHandler.DesignationWaiter is invoked every ten seconds, starting + * at ten seconds after the minute boundary (e.g. 13:05:10). So, an 80 second sleep should be + * sufficient to ensure that we wait for the DesignationWaiter to do its job, before + * checking the results. + */ + long sleepTime = 80000; + + /* + * DroolsPdpsElectionHandler runs every ten seconds, so a 15 second sleep should be + * plenty to ensure it has time to re-promote this PDP. + */ + long electionWaitSleepTime = 15000; + + /* + * Sleep 5 seconds after each test to allow interrupt (shutdown) recovery. + */ + long interruptRecoveryTime = 5000; + + /* + * See the IntegrityMonitor.getJmxUrl() method for the rationale behind this jmx related processing. + */ + @BeforeClass + public static void setUpClass() throws Exception { + + String userDir = System.getProperty("user.dir"); + PolicyLogger.debug("setUpClass: userDir=" + userDir); + System.setProperty("com.sun.management.jmxremote.port", "9980"); + System.setProperty("com.sun.management.jmxremote.authenticate","false"); + + // Make sure path to config directory is set correctly in PolicyContainer.main + // Also make sure we ignore HTTP server failures resulting from port conflicts. + PolicyContainer.isUnitTesting = true; + + } + + @AfterClass + public static void tearDownClass() throws Exception { + } + + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + + } + + @Ignore + @Test + public void testColdStandby() throws Exception { + + PolicyLogger.debug("\n\ntestColdStandby: Entering\n\n"); + + PolicyLogger.debug("testColdStandby: Reading IntegrityMonitorProperties"); + Properties integrityMonitorProperties = new Properties(); + integrityMonitorProperties.load(new FileInputStream(new File( + "src/test/server/config/IntegrityMonitor.properties"))); + IntegrityMonitorProperties.initProperties(integrityMonitorProperties); + String thisPdpId = IntegrityMonitorProperties + .getProperty(IntegrityMonitorProperties.PDP_INSTANCE_ID); + + PolicyLogger.debug("testColdStandby: Reading xacmlPersistenceProperties"); + Properties xacmlPersistenceProperties = new Properties(); + xacmlPersistenceProperties.load(new FileInputStream(new File( + "src/test/server/config/xacmlPersistence.properties"))); + XacmlPersistenceProperties.initProperties(xacmlPersistenceProperties); + + PolicyLogger.debug("testColdStandby: Creating emfXacml"); + EntityManagerFactory emfXacml = Persistence.createEntityManagerFactory( + "junitXacmlPU", xacmlPersistenceProperties); + + PolicyLogger.debug("testColdStandby: Reading droolsPersistenceProperties"); + Properties droolsPersistenceProperties = new Properties(); + droolsPersistenceProperties.load(new FileInputStream(new File( + "src/test/server/config/droolsPersistence.properties"))); + DroolsPersistenceProperties.initProperties(droolsPersistenceProperties); + + PolicyLogger.debug("testColdStandby: Creating emfDrools"); + EntityManagerFactory emfDrools = Persistence.createEntityManagerFactory( + "junitDroolsPU", droolsPersistenceProperties); + + DroolsPdpsConnector conn = new JpaDroolsPdpsConnector(emfDrools); + + PolicyLogger.debug("testColdStandby: Cleaning up tables"); + conn.deleteAllSessions(); + conn.deleteAllPdps(); + + PolicyLogger.debug("testColdStandby: Inserting PDP=" + thisPdpId + " as designated"); + DroolsPdp pdp = new DroolsPdpImpl(thisPdpId, true, 4, new Date()); + conn.insertPdp(pdp); + DroolsPdpEntity droolsPdpEntity = conn.getPdp(thisPdpId); + PolicyLogger.debug("testColdStandby: After insertion, DESIGNATED=" + + droolsPdpEntity.isDesignated() + " for PDP=" + thisPdpId); + assertTrue(droolsPdpEntity.isDesignated() == true); + + /* + * When the Standby Status changes (from providingservice) to hotstandby + * or coldstandby,the Active/Standby selection algorithm must stand down + * if thePDP-D is currently the lead/active node and allow another PDP-D + * to take over. + * + * It must also call lock on all engines in the engine management. + * + * Yes, this is kludgy, but we have a chicken and egg problem here: we + * need a StateManagement object to invoke the + * deleteAllStateManagementEntities method. + */ + PolicyLogger.debug("testColdStandby: Instantiating stateManagement object"); + StateManagement sm = new StateManagement(emfXacml, "dummy"); + sm.deleteAllStateManagementEntities(); + sm = new StateManagement(emfXacml, thisPdpId); + PMStandbyStateChangeNotifier pmStandbyStateChangeNotifier = new PMStandbyStateChangeNotifier(); + sm.addObserver(pmStandbyStateChangeNotifier); + + // Artificially putting a PDP into service is really a two step process, 1) + // inserting it as designated and 2) promoting it so that its standbyStatus + // is providing service. + + PolicyLogger.debug("testColdStandby: Running policy-management.Main class"); + PolicyManagementRunner policyManagementRunner = new PolicyManagementRunner(); + policyManagementRunner.start(); + + PolicyLogger.debug("testColdStandby: Runner started; Sleeping " + + interruptRecoveryTime + "ms before promoting PDP=" + + thisPdpId); + Thread.sleep(interruptRecoveryTime); + + PolicyLogger.debug("testColdStandby: Promoting PDP=" + thisPdpId); + sm.promote(); + + String standbyStatus = sm.getStandbyStatus(thisPdpId); + PolicyLogger.debug("testColdStandby: Before locking, PDP=" + thisPdpId + " has standbyStatus=" + + standbyStatus); + + PolicyLogger.debug("testColdStandby: Locking sm"); + sm.lock(); + + Thread.sleep(interruptRecoveryTime); + /* + * Verify that the PDP is no longer designated. + */ + droolsPdpEntity = conn.getPdp(thisPdpId); + PolicyLogger.debug("testColdStandby: After lock sm.lock() invoked, DESIGNATED=" + + droolsPdpEntity.isDesignated() + " for PDP=" + thisPdpId); + assertTrue(droolsPdpEntity.isDesignated() == false); + + PolicyLogger.debug("testColdStandby: Stopping policyManagementRunner"); + policyManagementRunner.stopRunner(); + + PolicyLogger.debug("\n\ntestColdStandby: Exiting\n\n"); + Thread.sleep(interruptRecoveryTime); + + } + + /* + * Tests hot standby when there is only one PDP. + */ + @Ignore + @Test + public void testHotStandby1() throws Exception { + + PolicyLogger.debug("\n\ntestHotStandby1: Entering\n\n"); + + PolicyLogger.debug("testHotStandby1: Reading IntegrityMonitorProperties"); + Properties integrityMonitorProperties = new Properties(); + integrityMonitorProperties.load(new FileInputStream(new File( + "src/test/server/config/IntegrityMonitor.properties"))); + IntegrityMonitorProperties.initProperties(integrityMonitorProperties); + String thisPdpId = IntegrityMonitorProperties + .getProperty(IntegrityMonitorProperties.PDP_INSTANCE_ID); + + PolicyLogger.debug("testHotStandby1: Reading xacmlPersistenceProperties"); + Properties xacmlPersistenceProperties = new Properties(); + xacmlPersistenceProperties.load(new FileInputStream(new File( + "src/test/server/config/xacmlPersistence.properties"))); + XacmlPersistenceProperties.initProperties(xacmlPersistenceProperties); + + PolicyLogger.debug("testHotStandby1: Creating emfXacml"); + EntityManagerFactory emfXacml = Persistence.createEntityManagerFactory( + "junitXacmlPU", xacmlPersistenceProperties); + + PolicyLogger.debug("testHotStandby1: Reading droolsPersistenceProperties"); + Properties droolsPersistenceProperties = new Properties(); + droolsPersistenceProperties.load(new FileInputStream(new File( + "src/test/server/config/droolsPersistence.properties"))); + DroolsPersistenceProperties.initProperties(droolsPersistenceProperties); + + PolicyLogger.debug("testHotStandby1: Creating emfDrools"); + EntityManagerFactory emfDrools = Persistence.createEntityManagerFactory( + "junitDroolsPU", droolsPersistenceProperties); + + DroolsPdpsConnector conn = new JpaDroolsPdpsConnector(emfDrools); + + PolicyLogger.debug("testHotStandby1: Cleaning up tables"); + conn.deleteAllSessions(); + conn.deleteAllPdps(); + + /* + * Insert this PDP as not designated. Initial standby state will be + * either null or cold standby. Demoting should transit state to + * hot standby. + */ + PolicyLogger.debug("testHotStandby1: Inserting PDP=" + thisPdpId + " as not designated"); + Date yesterday = DateUtils.addDays(new Date(), -1); + DroolsPdpImpl pdp = new DroolsPdpImpl(thisPdpId, false, 4, yesterday); + conn.insertPdp(pdp); + DroolsPdpEntity droolsPdpEntity = conn.getPdp(thisPdpId); + PolicyLogger.debug("testHotStandby1: After insertion, PDP=" + thisPdpId + " has DESIGNATED=" + + droolsPdpEntity.isDesignated()); + assertTrue(droolsPdpEntity.isDesignated() == false); + + PolicyLogger.debug("testHotStandby1: Instantiating stateManagement object"); + StateManagement sm = new StateManagement(emfXacml, "dummy"); + sm.deleteAllStateManagementEntities(); + sm = new StateManagement(emfXacml, thisPdpId); + PMStandbyStateChangeNotifier pmStandbyStateChangeNotifier = new PMStandbyStateChangeNotifier(); + sm.addObserver(pmStandbyStateChangeNotifier); + + PolicyLogger.debug("testHotStandby1: Demoting PDP=" + thisPdpId); + // demoting should cause state to transit to hotstandby + sm.demote(); + + PolicyLogger.debug("testHotStandby1: Running policy-management.Main class"); + PolicyManagementRunner policyManagementRunner = new PolicyManagementRunner(); + policyManagementRunner.start(); + + PolicyLogger.debug("testHotStandby1: Sleeping " + + sleepTime + + "ms, to allow JpaDroolsPdpsConnector time to check droolspdpentity table"); + Thread.sleep(sleepTime); + + /* + * Verify that this formerly un-designated PDP in HOT_STANDBY is now designated and providing service. + */ + droolsPdpEntity = conn.getPdp(thisPdpId); + PolicyLogger.debug("testHotStandby1: After sm.demote() invoked, DESIGNATED=" + + droolsPdpEntity.isDesignated() + " for PDP=" + thisPdpId); + assertTrue(droolsPdpEntity.isDesignated() == true); + String standbyStatus = sm.getStandbyStatus(thisPdpId); + PolicyLogger.debug("testHotStandby1: After demotion, PDP=" + thisPdpId + " has standbyStatus=" + + standbyStatus); + assertTrue(standbyStatus != null && standbyStatus.equals(StateManagement.PROVIDING_SERVICE)); + + PolicyLogger.debug("testHotStandby1: Stopping policyManagementRunner"); + policyManagementRunner.stopRunner(); + + PolicyLogger.debug("\n\ntestHotStandby1: Exiting\n\n"); + Thread.sleep(interruptRecoveryTime); + + } + + /* + * Tests hot standby when two PDPs are involved. + */ + @Ignore + @Test + public void testHotStandby2() throws Exception { + + PolicyLogger.info("\n\ntestHotStandby2: Entering\n\n"); + + PolicyLogger.info("testHotStandby2: Reading IntegrityMonitorProperties"); + Properties integrityMonitorProperties = new Properties(); + integrityMonitorProperties.load(new FileInputStream(new File( + "src/test/server/config/IntegrityMonitor.properties"))); + IntegrityMonitorProperties.initProperties(integrityMonitorProperties); + String thisPdpId = IntegrityMonitorProperties + .getProperty(IntegrityMonitorProperties.PDP_INSTANCE_ID); + + PolicyLogger.info("testHotStandby2: Reading xacmlPersistenceProperties"); + Properties xacmlPersistenceProperties = new Properties(); + xacmlPersistenceProperties.load(new FileInputStream(new File( + "src/test/server/config/xacmlPersistence.properties"))); + XacmlPersistenceProperties.initProperties(xacmlPersistenceProperties); + + PolicyLogger.info("testHotStandby2: Creating emfXacml"); + EntityManagerFactory emfXacml = Persistence.createEntityManagerFactory( + "junitXacmlPU", xacmlPersistenceProperties); + + PolicyLogger.info("testHotStandby2: Reading droolsPersistenceProperties"); + Properties droolsPersistenceProperties = new Properties(); + droolsPersistenceProperties.load(new FileInputStream(new File( + "src/test/server/config/droolsPersistence.properties"))); + DroolsPersistenceProperties.initProperties(droolsPersistenceProperties); + + PolicyLogger.info("testHotStandby2: Creating emfDrools"); + EntityManagerFactory emfDrools = Persistence.createEntityManagerFactory( + "junitDroolsPU", droolsPersistenceProperties); + + DroolsPdpsConnector conn = new JpaDroolsPdpsConnector(emfDrools); + + PolicyLogger.info("testHotStandby2: Cleaning up tables"); + conn.deleteAllSessions(); + conn.deleteAllPdps(); + + /* + * Insert a PDP that's designated but not current. + */ + String activePdpId = "pdp2"; + PolicyLogger.info("testHotStandby2: Inserting PDP=" + activePdpId + " as stale, designated PDP"); + Date yesterday = DateUtils.addDays(new Date(), -1); + DroolsPdp pdp = new DroolsPdpImpl(activePdpId, true, 4, yesterday); + conn.insertPdp(pdp); + DroolsPdpEntity droolsPdpEntity = conn.getPdp(activePdpId); + PolicyLogger.info("testHotStandby2: After insertion, PDP=" + activePdpId + ", which is not current, has DESIGNATED=" + + droolsPdpEntity.isDesignated()); + assertTrue(droolsPdpEntity.isDesignated() == true); + + /* + * Promote the designated PDP. + * + * We have a chicken and egg problem here: we need a StateManagement + * object to invoke the deleteAllStateManagementEntities method. + */ + PolicyLogger.info("testHotStandy2: Promoting PDP=" + activePdpId); + StateManagement sm = new StateManagement(emfXacml, "dummy"); + sm.deleteAllStateManagementEntities(); + sm = new StateManagement(emfXacml, activePdpId);//pdp2 + PMStandbyStateChangeNotifier pmStandbyStateChangeNotifier = new PMStandbyStateChangeNotifier(); + sm.addObserver(pmStandbyStateChangeNotifier); + + // Artificially putting a PDP into service is really a two step process, 1) + // inserting it as designated and 2) promoting it so that its standbyStatus + // is providing service. + + /* + * Insert this PDP as not designated. Initial standby state will be + * either null or cold standby. Demoting should transit state to + * hot standby. + */ + PolicyLogger.info("testHotStandby2: Inserting PDP=" + thisPdpId + " as not designated"); + pdp = new DroolsPdpImpl(thisPdpId, false, 4, yesterday); + conn.insertPdp(pdp); + droolsPdpEntity = conn.getPdp(thisPdpId); + PolicyLogger.info("testHotStandby2: After insertion, PDP=" + thisPdpId + " has DESIGNATED=" + + droolsPdpEntity.isDesignated()); + assertTrue(droolsPdpEntity.isDesignated() == false); + + PolicyLogger.info("testHotStandby2: Demoting PDP=" + thisPdpId);//pdp1 + StateManagement sm2 = new StateManagement(emfXacml, thisPdpId); + sm2.addObserver(pmStandbyStateChangeNotifier); + + PolicyLogger.info("testHotStandby2: Running policy-management.Main class"); + PolicyManagementRunner policyManagementRunner = new PolicyManagementRunner(); //pdp1 + policyManagementRunner.start(); + + PolicyLogger.info("testHotStandby2: Runner started; Sleeping " + + interruptRecoveryTime + "ms before promoting/demoting"); + Thread.sleep(interruptRecoveryTime); + + PolicyLogger.info("testHotStandby2: Runner started; promoting PDP=" + activePdpId);//pdpd2xs + //at this point, the newly created pdp will have set the state to disabled/failed/cold standby + //because it is stale. So, it cannot be promoted. We need to call sm.enableNotFailed() so we + //can promote it and demote the other pdp - else the other pdp will just spring back to providingservice + sm.enableNotFailed();//pdp1 + sm.promote(); + String standbyStatus = sm.getStandbyStatus(activePdpId); + PolicyLogger.info("testHotStandby2: After promoting, PDP=" + activePdpId + " has standbyStatus=" + + standbyStatus); + + // demoting PDP should ensure that state transits to hotstandby + PolicyLogger.info("testHotStandby2: Runner started; demoting PDP=" + thisPdpId); + sm2.demote();//pdp1 + standbyStatus = sm.getStandbyStatus(thisPdpId); + PolicyLogger.info("testHotStandby2: After demoting, PDP=" + thisPdpId + " has standbyStatus=" + + standbyStatus); + + PolicyLogger.info("testHotStandby2: Sleeping " + + sleepTime + + "ms, to allow JpaDroolsPdpsConnector time to check droolspdpentity table"); + Thread.sleep(sleepTime); + + /* + * Verify that this PDP, demoted to HOT_STANDBY, is now + * re-designated and providing service. + */ + droolsPdpEntity = conn.getPdp(thisPdpId); + PolicyLogger.info("testHotStandby2: After demoting PDP=" + activePdpId + + ", DESIGNATED=" + droolsPdpEntity.isDesignated() + + " for PDP=" + thisPdpId); + assertTrue(droolsPdpEntity.isDesignated() == true); + standbyStatus = sm2.getStandbyStatus(thisPdpId); + PolicyLogger.info("testHotStandby2: After demoting PDP=" + activePdpId + + ", PDP=" + thisPdpId + " has standbyStatus=" + standbyStatus); + assertTrue(standbyStatus != null + && standbyStatus.equals(StateManagement.PROVIDING_SERVICE)); + + PolicyLogger.info("testHotStandby2: Stopping policyManagementRunner"); + policyManagementRunner.stopRunner(); + + PolicyLogger.info("\n\ntestHotStandby2: Exiting\n\n"); + Thread.sleep(interruptRecoveryTime); + + } + + /* + * 1) Inserts and designates this PDP, then verifies that startTransaction + * is successful. + * + * 2) Demotes PDP, and verifies that because there is only one PDP, it will + * be immediately re-promoted, thus allowing startTransaction to be + * successful. + * + * 3) Locks PDP and verifies that startTransaction results in + * AdministrativeStateException. + * + * 4) Unlocks PDP and verifies that startTransaction results in + * StandbyStatusException. + * + * 5) Promotes PDP and verifies that startTransaction is once again + * successful. + */ + @Ignore + @Test + public void testLocking1() throws Exception { + + PolicyLogger.debug("testLocking1: Reading IntegrityMonitorProperties"); + Properties integrityMonitorProperties = new Properties(); + integrityMonitorProperties.load(new FileInputStream(new File( + "src/test/server/config/IntegrityMonitor.properties"))); + IntegrityMonitorProperties.initProperties(integrityMonitorProperties); + String thisPdpId = IntegrityMonitorProperties + .getProperty(IntegrityMonitorProperties.PDP_INSTANCE_ID); + + PolicyLogger.debug("testLocking1: Reading xacmlPersistenceProperties"); + Properties xacmlPersistenceProperties = new Properties(); + xacmlPersistenceProperties.load(new FileInputStream(new File( + "src/test/server/config/xacmlPersistence.properties"))); + XacmlPersistenceProperties.initProperties(xacmlPersistenceProperties); + + PolicyLogger.debug("testLocking1: Creating emfXacml"); + EntityManagerFactory emfXacml = Persistence.createEntityManagerFactory( + "junitXacmlPU", xacmlPersistenceProperties); + + PolicyLogger.debug("testLocking1: Reading droolsPersistenceProperties"); + Properties droolsPersistenceProperties = new Properties(); + droolsPersistenceProperties.load(new FileInputStream(new File( + "src/test/server/config/droolsPersistence.properties"))); + DroolsPersistenceProperties.initProperties(droolsPersistenceProperties); + + PolicyLogger.debug("testLocking1: Creating emfDrools"); + EntityManagerFactory emfDrools = Persistence.createEntityManagerFactory( + "junitDroolsPU", droolsPersistenceProperties); + + DroolsPdpsConnector conn = new JpaDroolsPdpsConnector(emfDrools); + + PolicyLogger.debug("testLocking1: Cleaning up tables"); + conn.deleteAllSessions(); + conn.deleteAllPdps(); + + /* + * Insert this PDP as designated. Initial standby state will be + * either null or cold standby. + */ + PolicyLogger.debug("testLocking1: Inserting PDP=" + thisPdpId + " as designated"); + DroolsPdpImpl pdp = new DroolsPdpImpl(thisPdpId, true, 4, new Date()); + conn.insertPdp(pdp); + DroolsPdpEntity droolsPdpEntity = conn.getPdp(thisPdpId); + PolicyLogger.debug("testLocking1: After insertion, PDP=" + thisPdpId + " has DESIGNATED=" + + droolsPdpEntity.isDesignated()); + assertTrue(droolsPdpEntity.isDesignated() == true); + + PolicyLogger.debug("testLocking1: Instantiating stateManagement object"); + StateManagement sm = new StateManagement(emfXacml, "dummy"); + sm.deleteAllStateManagementEntities(); + sm = new StateManagement(emfXacml, thisPdpId); + PMStandbyStateChangeNotifier pmStandbyStateChangeNotifier = new PMStandbyStateChangeNotifier(); + sm.addObserver(pmStandbyStateChangeNotifier); + + PolicyLogger.debug("testLocking1: Running policy-management.Main class, designated=" + + conn.getPdp(thisPdpId).isDesignated()); + PolicyManagementRunner policyManagementRunner = new PolicyManagementRunner(); + policyManagementRunner.start(); + + PolicyLogger.debug("testLocking1: Runner started; Sleeping " + + interruptRecoveryTime + "ms before promoting PDP=" + + thisPdpId); + Thread.sleep(interruptRecoveryTime); + + PolicyLogger.debug("testLocking1: Promoting PDP=" + thisPdpId); + sm.promote(); + + PolicyLogger.debug("testLocking1: Sleeping " + + sleepTime + + "ms, to allow time for policy-management.Main class to come up, designated=" + + conn.getPdp(thisPdpId).isDesignated()); + Thread.sleep(sleepTime); + + PolicyLogger.debug("testLocking1: Waking up and invoking startTransaction on active PDP=" + + thisPdpId + + ", designated=" + + conn.getPdp(thisPdpId).isDesignated()); + DroolsPDPIntegrityMonitor droolsPdpIntegrityMonitor = (DroolsPDPIntegrityMonitor) IntegrityMonitor + .getInstance(); + try { + droolsPdpIntegrityMonitor.startTransaction(); + droolsPdpIntegrityMonitor.endTransaction(); + PolicyLogger.debug("testLocking1: As expected, transaction successful"); + } catch (AdministrativeStateException e) { + PolicyLogger.error("testLocking1: Unexpectedly caught AdministrativeStateException, message=" + e.getMessage()); + assertTrue(false); + } catch (StandbyStatusException e) { + PolicyLogger.error("testLocking1: Unexpectedly caught StandbyStatusException, message=" + e.getMessage()); + assertTrue(false); + } catch (Exception e) { + PolicyLogger.error("testLocking1: Unexpectedly caught Exception, message=" + e.getMessage()); + assertTrue(false); + } + + // demoting should cause state to transit to hotstandby, followed by re-promotion, + // since there is only one PDP. + PolicyLogger.debug("testLocking1: demoting PDP=" + thisPdpId); + sm = droolsPdpIntegrityMonitor.getStateManager(); + sm.demote(); + + PolicyLogger.debug("testLocking1: sleeping" + electionWaitSleepTime + + " to allow election handler to re-promote PDP=" + thisPdpId); + Thread.sleep(electionWaitSleepTime); + + PolicyLogger.debug("testLocking1: Invoking startTransaction on re-promoted PDP=" + + thisPdpId + + ", designated=" + + conn.getPdp(thisPdpId).isDesignated()); + try { + droolsPdpIntegrityMonitor.startTransaction(); + droolsPdpIntegrityMonitor.endTransaction(); + PolicyLogger.debug("testLocking1: As expected, transaction successful"); + } catch (AdministrativeStateException e) { + PolicyLogger.error("testLocking1: Unexpectedly caught AdministrativeStateException, message=" + e.getMessage()); + assertTrue(false); + } catch (StandbyStatusException e) { + PolicyLogger.error("testLocking1: Unexpectedly caught StandbyStatusException, message=" + e.getMessage()); + assertTrue(false); + } catch (Exception e) { + PolicyLogger.error("testLocking1: Unexpectedly caught Exception, message=" + e.getMessage()); + assertTrue(false); + } + + // locking should cause state to transit to cold standby + PolicyLogger.debug("testLocking1: locking PDP=" + thisPdpId); + sm.lock(); + + // Just to avoid any race conditions, sleep a little after locking + PolicyLogger.debug("testLocking1: Sleeping a few millis after locking, to avoid race condition"); + Thread.sleep(100); + + PolicyLogger.debug("testLocking1: Invoking startTransaction on locked PDP=" + + thisPdpId + + ", designated=" + + conn.getPdp(thisPdpId).isDesignated()); + try { + droolsPdpIntegrityMonitor.startTransaction(); + PolicyLogger.error("testLocking1: startTransaction unexpectedly successful"); + assertTrue(false); + } catch (AdministrativeStateException e) { + PolicyLogger.debug("testLocking1: As expected, caught AdministrativeStateException, message=" + e.getMessage()); + } catch (StandbyStatusException e) { + PolicyLogger.error("testLocking1: Unexpectedly caught StandbyStatusException, message=" + e.getMessage()); + assertTrue(false); + } catch (Exception e) { + PolicyLogger.error("testLocking1: Unexpectedly caught Exception, message=" + e.getMessage()); + assertTrue(false); + } finally { + droolsPdpIntegrityMonitor.endTransaction(); + } + + // unlocking should cause state to transit to hot standby + PolicyLogger.debug("testLocking1: unlocking PDP=" + thisPdpId); + sm.unlock(); + + // Just to avoid any race conditions, sleep a little after locking + PolicyLogger.debug("testLocking1: Sleeping a few millis after unlocking, to avoid race condition"); + Thread.sleep(100); + + PolicyLogger.debug("testLocking1: Invoking startTransaction on unlocked PDP=" + + thisPdpId + + ", designated=" + + conn.getPdp(thisPdpId).isDesignated()); + try { + droolsPdpIntegrityMonitor.startTransaction(); + PolicyLogger.error("testLocking1: startTransaction unexpectedly successful"); + assertTrue(false); + } catch (AdministrativeStateException e) { + PolicyLogger.error("testLocking1: Unexpectedly caught AdministrativeStateException, message=" + e.getMessage()); + assertTrue(false); + } catch (StandbyStatusException e) { + PolicyLogger.debug("testLocking1: As expected, caught StandbyStatusException, message=" + e.getMessage()); + } catch (Exception e) { + PolicyLogger.error("testLocking1: Unexpectedly caught Exception, message=" + e.getMessage()); + assertTrue(false); + } finally { + droolsPdpIntegrityMonitor.endTransaction(); + } + + // promoting should cause state to transit to providing service + PolicyLogger.debug("testLocking1: promoting PDP=" + thisPdpId); + sm.promote(); + + // Just to avoid any race conditions, sleep a little after promoting + PolicyLogger.debug("testLocking1: Sleeping a few millis after promoting, to avoid race condition"); + Thread.sleep(100); + + PolicyLogger.debug("testLocking1: Invoking startTransaction on promoted PDP=" + + thisPdpId + + ", designated=" + + conn.getPdp(thisPdpId).isDesignated()); + try { + droolsPdpIntegrityMonitor.startTransaction(); + droolsPdpIntegrityMonitor.endTransaction(); + PolicyLogger.debug("testLocking1: As expected, transaction successful"); + } catch (AdministrativeStateException e) { + PolicyLogger.error("testLocking1: Unexpectedly caught AdministrativeStateException, message=" + e.getMessage()); + assertTrue(false); + } catch (StandbyStatusException e) { + PolicyLogger.error("testLocking1: Unexpectedly caught StandbyStatusException, message=" + e.getMessage()); + assertTrue(false); + } catch (Exception e) { + PolicyLogger.error("testLocking1: Unexpectedly caught Exception, message=" + e.getMessage()); + assertTrue(false); + } + + PolicyLogger.debug("testLocking1: Stopping policyManagementRunner"); + policyManagementRunner.stopRunner(); + + PolicyLogger.debug("\n\ntestLocking1: Exiting\n\n"); + Thread.sleep(interruptRecoveryTime); + + } + + /* + * 1) Inserts and designates this PDP, then verifies that startTransaction + * is successful. + * + * 2) Inserts another PDP in hotstandby. + * + * 3) Demotes this PDP, and verifies 1) that other PDP is not promoted (because one + * PDP cannot promote another PDP) and 2) that this PDP is re-promoted. + */ + @Ignore + @Test + public void testLocking2() throws Exception { + + PolicyLogger.debug("\n\ntestLocking2: Entering\n\n"); + + PolicyLogger.debug("testLocking2: Reading IntegrityMonitorProperties"); + Properties integrityMonitorProperties = new Properties(); + integrityMonitorProperties.load(new FileInputStream(new File( + "src/test/server/config/IntegrityMonitor.properties"))); + IntegrityMonitorProperties.initProperties(integrityMonitorProperties); + String thisPdpId = IntegrityMonitorProperties + .getProperty(IntegrityMonitorProperties.PDP_INSTANCE_ID); + + PolicyLogger.debug("testLocking2: Reading xacmlPersistenceProperties"); + Properties xacmlPersistenceProperties = new Properties(); + xacmlPersistenceProperties.load(new FileInputStream(new File( + "src/test/server/config/xacmlPersistence.properties"))); + XacmlPersistenceProperties.initProperties(xacmlPersistenceProperties); + + PolicyLogger.debug("testLocking2: Creating emfXacml"); + EntityManagerFactory emfXacml = Persistence.createEntityManagerFactory( + "junitXacmlPU", xacmlPersistenceProperties); + + PolicyLogger.debug("testLocking2: Reading droolsPersistenceProperties"); + Properties droolsPersistenceProperties = new Properties(); + droolsPersistenceProperties.load(new FileInputStream(new File( + "src/test/server/config/droolsPersistence.properties"))); + DroolsPersistenceProperties.initProperties(droolsPersistenceProperties); + + PolicyLogger.debug("testLocking2: Creating emfDrools"); + EntityManagerFactory emfDrools = Persistence.createEntityManagerFactory( + "junitDroolsPU", droolsPersistenceProperties); + + DroolsPdpsConnector conn = new JpaDroolsPdpsConnector(emfDrools); + + PolicyLogger.debug("testLocking2: Cleaning up tables"); + conn.deleteAllSessions(); + conn.deleteAllPdps(); + + /* + * Insert this PDP as designated. Initial standby state will be + * either null or cold standby. Demoting should transit state to + * hot standby. + */ + PolicyLogger.debug("testLocking2: Inserting PDP=" + thisPdpId + " as designated"); + DroolsPdpImpl pdp = new DroolsPdpImpl(thisPdpId, true, 3, new Date()); + conn.insertPdp(pdp); + DroolsPdpEntity droolsPdpEntity = conn.getPdp(thisPdpId); + PolicyLogger.debug("testLocking2: After insertion, PDP=" + thisPdpId + " has DESIGNATED=" + + droolsPdpEntity.isDesignated()); + assertTrue(droolsPdpEntity.isDesignated() == true); + + PolicyLogger.debug("testLocking2: Instantiating stateManagement object and promoting PDP=" + thisPdpId); + StateManagement sm = new StateManagement(emfXacml, "dummy"); + sm.deleteAllStateManagementEntities(); + sm = new StateManagement(emfXacml, thisPdpId); + PMStandbyStateChangeNotifier pmStandbyStateChangeNotifier = new PMStandbyStateChangeNotifier(); + sm.addObserver(pmStandbyStateChangeNotifier); + + /* + * Insert another PDP as not designated. Initial standby state will be + * either null or cold standby. Demoting should transit state to + * hot standby. + */ + String standbyPdpId = "pdp2"; + PolicyLogger.debug("testLocking2: Inserting PDP=" + standbyPdpId + " as not designated"); + Date yesterday = DateUtils.addDays(new Date(), -1); + pdp = new DroolsPdpImpl(standbyPdpId, false, 4, yesterday); + conn.insertPdp(pdp); + droolsPdpEntity = conn.getPdp(standbyPdpId); + PolicyLogger.debug("testLocking2: After insertion, PDP=" + standbyPdpId + " has DESIGNATED=" + + droolsPdpEntity.isDesignated()); + assertTrue(droolsPdpEntity.isDesignated() == false); + + PolicyLogger.debug("testLocking2: Demoting PDP=" + standbyPdpId); + StateManagement sm2 = new StateManagement(emfXacml, standbyPdpId); + sm2.addObserver(pmStandbyStateChangeNotifier); + + PolicyLogger.debug("testLocking2: Running policy-management.Main class"); + PolicyManagementRunner policyManagementRunner = new PolicyManagementRunner(); + policyManagementRunner.start(); + + PolicyLogger.debug("testLocking2: Runner started; Sleeping " + + interruptRecoveryTime + "ms before promoting/demoting"); + Thread.sleep(interruptRecoveryTime); + + PolicyLogger.debug("testLocking2: Promoting PDP=" + thisPdpId); + sm.promote(); + + // demoting PDP should ensure that state transits to hotstandby + PolicyLogger.debug("testLocking2: Demoting PDP=" + standbyPdpId); + sm2.demote(); + + PolicyLogger.debug("testLocking2: Sleeping " + + sleepTime + + "ms, to allow time for policy-management.Main class to come up"); + Thread.sleep(sleepTime); + + PolicyLogger.debug("testLocking2: Waking up and invoking startTransaction on active PDP=" + + thisPdpId + + ", designated=" + + conn.getPdp(thisPdpId).isDesignated()); + DroolsPDPIntegrityMonitor droolsPdpIntegrityMonitor = (DroolsPDPIntegrityMonitor) IntegrityMonitor + .getInstance(); + try { + droolsPdpIntegrityMonitor.startTransaction(); + droolsPdpIntegrityMonitor.endTransaction(); + PolicyLogger.debug("testLocking2: As expected, transaction successful"); + } catch (AdministrativeStateException e) { + PolicyLogger.error("testLocking2: Unexpectedly caught AdministrativeStateException, message=" + e.getMessage()); + assertTrue(false); + } catch (StandbyStatusException e) { + PolicyLogger.error("testLocking2: Unexpectedly caught StandbyStatusException, message=" + e.getMessage()); + assertTrue(false); + } catch (Exception e) { + PolicyLogger.error("testLocking2: Unexpectedly caught Exception, message=" + e.getMessage()); + assertTrue(false); + } + + // demoting should cause state to transit to hotstandby followed by re-promotion. + PolicyLogger.debug("testLocking2: demoting PDP=" + thisPdpId); + sm = droolsPdpIntegrityMonitor.getStateManager(); + sm.demote(); + + PolicyLogger.debug("testLocking2: sleeping" + electionWaitSleepTime + + " to allow election handler to re-promote PDP=" + thisPdpId); + Thread.sleep(electionWaitSleepTime); + + PolicyLogger.debug("testLocking2: Waking up and invoking startTransaction on re-promoted PDP=" + + thisPdpId + ", designated=" + + conn.getPdp(thisPdpId).isDesignated()); + try { + droolsPdpIntegrityMonitor.startTransaction(); + droolsPdpIntegrityMonitor.endTransaction(); + PolicyLogger.debug("testLocking2: As expected, transaction successful"); + } catch (AdministrativeStateException e) { + PolicyLogger.error("testLocking2: Unexpectedly caught AdministrativeStateException, message=" + e.getMessage()); + assertTrue(false); + } catch (StandbyStatusException e) { + PolicyLogger.error("testLocking2: Unexpectedly caught StandbyStatusException, message=" + e.getMessage()); + assertTrue(false); + } catch (Exception e) { + PolicyLogger.error("testLocking2: Unexpectedly caught Exception, message=" + e.getMessage()); + assertTrue(false); + } + + PolicyLogger.debug("testLocking2: Verifying designated status for PDP=" + + standbyPdpId); + boolean standbyPdpDesignated = conn.getPdp(standbyPdpId).isDesignated(); + assertTrue(standbyPdpDesignated == false); + + PolicyLogger.debug("testLocking2: Stopping policyManagementRunner"); + policyManagementRunner.stopRunner(); + + PolicyLogger.debug("\n\ntestLocking2: Exiting\n\n"); + Thread.sleep(interruptRecoveryTime); + + } + + private class PolicyManagementRunner extends Thread { + + public void run() { + PolicyLogger.info("PolicyManagementRunner.run: Entering"); + String args[] = { "src/main/server/config" }; + try { + Main.main(args); + } catch (Exception e) { + PolicyLogger + .info("PolicyManagementRunner.run: Exception thrown from Main.main(), message=" + + e.getMessage()); + } + PolicyLogger.info("PolicyManagementRunner.run: Exiting"); + } + + public void stopRunner() { + PolicyEngine.manager.shutdown(); + } + + } + +} diff --git a/policy-persistence/src/test/resources/IntegrityMonitor.properties b/policy-persistence/src/test/resources/IntegrityMonitor.properties new file mode 100644 index 00000000..0ab36286 --- /dev/null +++ b/policy-persistence/src/test/resources/IntegrityMonitor.properties @@ -0,0 +1,67 @@ +### +# ============LICENSE_START======================================================= +# policy-persistence +# ================================================================================ +# 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========================================================= +### + +#hostPort = ${{host_port}} +hostPort = 0.0.0.0:9981 + +# The following were added as part of US673632 +# +# Forward Progress Monitor update interval seconds +fp_monitor_interval = 30 +# Failed counter threshold before failover +failed_counter_threshold = 3 +# Interval between test transactions when no traffic seconds +test_trans_interval = 10 +# Interval between writes of the FPC to the DB seconds +write_fpc_interval = 5 +# Name of the site in which this node is hosted +site_name = pdp_1 +# Node type +# Note: Make sure you don't leave any trailing spaces, or you'll get an 'invalid node type' error! +node_type = pdp_drools +# Dependency groups are groups of resources upon which a node operational state is dependent upon. +# Each group is a comma-separated list of resource names and groups are separated by a semicolon. For example: +#dependency_groups=site_1.astra_1,site_1.astra_2;site_1.brms_1,site_1.brms_2;site_1.logparser_1;site_1.pypdp_1 +#dependency_groups=${{dependency_groups}} +dependency_groups="" +# When set to true, dependent health checks are performed by using JMX to invoke test() on the dependent. +# The default false is to use state checks for health. +#test_via_jmx=${{test_via_jmx}} +# This is the max number of seconds beyond which a non incrementing FPC is considered a failure +#max_fpc_update_interval=${{max_fpc_update_interval}} + +# Needed by DroolsPdpsElectionHandler +pdp.checkInterval=1500 +pdp.updateInterval=1000 +#pdp.timeout=3000 +# Need long timeout, because testTransaction is only run every 10 seconds. +pdp.timeout=15000 +#how long do we wait for the pdp table to populate on initial startup +pdp.initialWait=20000 + +# Known as the PDPID in the droolpdpentity table. +resource.name=pdp1 +#resource.name=${{resource_name}} + + + + + + diff --git a/policy-persistence/src/test/resources/META-INF/persistence.xml b/policy-persistence/src/test/resources/META-INF/persistence.xml new file mode 100644 index 00000000..51ec1613 --- /dev/null +++ b/policy-persistence/src/test/resources/META-INF/persistence.xml @@ -0,0 +1,56 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + ============LICENSE_START======================================================= + policy-persistence + ================================================================================ + 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="junitDroolsPU" transaction-type="RESOURCE_LOCAL"> + <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider> + <class>org.openecomp.policy.drools.persistence.DroolsPdpEntity</class> + <class>org.openecomp.policy.drools.persistence.DroolsSessionEntity</class> + <class>org.openecomp.policy.drools.persistence.LastSiteEntity</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> + <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/generatedCreateDrools.ddl"/> + <property name="javax.persistence.schema-generation.scripts.drop-target" value="./sql/generatedDropDrools.ddl"/> + </properties> + </persistence-unit> + + <persistence-unit name="junitXacmlPU" transaction-type="RESOURCE_LOCAL"> + <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider> + <class>org.openecomp.policy.common.im.jpa.StateManagementEntity</class> + <class>org.openecomp.policy.common.im.jpa.ForwardProgressEntity</class> + <class>org.openecomp.policy.common.im.jpa.ResourceRegistrationEntity</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/generatedCreateXacml.ddl"/> + <property name="javax.persistence.schema-generation.scripts.drop-target" value="./sql/generatedDropXacml.ddl"/> + </properties> + </persistence-unit> + +</persistence> diff --git a/policy-persistence/src/test/resources/droolsPersistence.properties b/policy-persistence/src/test/resources/droolsPersistence.properties new file mode 100644 index 00000000..544e1c23 --- /dev/null +++ b/policy-persistence/src/test/resources/droolsPersistence.properties @@ -0,0 +1,51 @@ +### +# ============LICENSE_START======================================================= +# policy-persistence +# ================================================================================ +# 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========================================================= +### + +javax.persistence.jdbc.driver = org.h2.Driver +javax.persistence.jdbc.url = jdbc:h2:file:./sql/drools +javax.persistence.jdbc.user = sa +javax.persistence.jdbc.password = + +#javax.persistence.jdbc.driver=org.mariadb.jdbc.Driver +#javax.persistence.jdbc.url=jdbc:mariadb://localhost:3306/drools +#javax.persistence.jdbc.user=root +#javax.persistence.jdbc.password=policy + +#javax.persistence.jdbc.driver = ${{JDBC_DRIVER}} +#javax.persistence.jdbc.url = ${{JDBC_DROOLS_URL}} +#javax.persistence.jdbc.user = ${{JDBC_USER}} +#javax.persistence.jdbc.password = ${{JDBC_PASSWORD}} + +# Needed? +#javax.persistence.jdbc.driver = org.h2.Driver +#javax.persistence.jdbc.url = jdbc:h2:file:./sql/ncomp +#javax.persistence.jdbc.user = sa +#javax.persistence.jdbc.password = +#persistenceDisabled=false +#javax.persistence.jdbc.driver=org.mariadb.jdbc.Driver +#javax.persistence.jdbc.url=jdbc:mariadb://192.168.56.30:3306/drools +#javax.persistence.jdbc.user=patb +#javax.persistence.jdbc.password=policy + +hibernate.dataSource=org.mariadb.jdbc.MySQLDataSource + +# For testing purposes, it may be convenient to disable persistence +persistenceDisabled=false + diff --git a/policy-persistence/src/test/resources/log4j.properties b/policy-persistence/src/test/resources/log4j.properties new file mode 100644 index 00000000..746d59a0 --- /dev/null +++ b/policy-persistence/src/test/resources/log4j.properties @@ -0,0 +1,31 @@ +### +# ============LICENSE_START======================================================= +# policy-persistence +# ================================================================================ +# 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========================================================= +### + +log4j.rootLogger=DEBUG, out +log4j.logger.com.att=DEBUG +log4j.logger.org.openecomp.policy.drools.system=DEBUG +log4j.logger.org.openecomp.policy.drools.im=DEBUG +log4j.logger.org.openecomp.policy.common.im=DEBUG +log4j.logger.org.openecomp.policy.drools.event.comm=DEBUG + +# CONSOLE appender not used by default +log4j.appender.out=org.apache.log4j.ConsoleAppender +log4j.appender.out.layout=org.apache.log4j.PatternLayout +log4j.appender.out.layout.ConversionPattern=%d %-5p %-30.30c{1} %4L - %m%n diff --git a/policy-persistence/src/test/resources/logback.xml b/policy-persistence/src/test/resources/logback.xml new file mode 100644 index 00000000..9fd83e8d --- /dev/null +++ b/policy-persistence/src/test/resources/logback.xml @@ -0,0 +1,209 @@ +<!-- + ============LICENSE_START======================================================= + policy-persistence + ================================================================================ + 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========================================================= + --> + +<!-- Controls the output of logs for JUnit tests --> + +<configuration scan="true" scanPeriod="3 seconds" debug="true"> + <!--<jmxConfigurator /> --> + <!-- directory path for all other type logs --> + <property name="logDir" value="testingLogs" /> + + <!-- directory path for debugging type logs --> + <property name="debugDir" value="testingLogs" /> + + <!-- specify the component name + <ECOMP-component-name>::= "MSO" | "DCAE" | "ASDC " | "AAI" |"Policy" | "SDNC" | "AC" --> + <property name="componentName" value="drools-pdp"></property> + <property name="subComponentName" value="policy-management"></property> + + <!-- log file names --> + <property name="errorLogName" value="error" /> + <property name="metricsLogName" value="metrics" /> + <property name="auditLogName" value="audit" /> + <property name="debugLogName" value="debug" /> + + <property name="defaultPattern" value="%d{"yyyy-MM-dd'T'HH:mm:ss.SSSXXX", UTC}|%X{requestId}|%X{serviceInstanceId}|%t|%X{serverName}|%X{serviceName}|%X{instanceUuid}|%p|%X{severity}|%X{serverIpAddress}|%X{server}|%X{clientIpAddress}|%c||%msg%n" /> + <!-- <property name="defaultPattern" value="%d{"yyyy-MM-dd'T'HH:mm:ss.SSSXXX", UTC}|%X{RequestId}|%X{ServiceInstanceId}|%thread||%X{ServiceName}|%X{InstanceUUID}|%.-5level|%X{AlertSeverity}|%X{ServerIPAddress}|%X{ServerFQDN}|%X{RemoteHost}||%X{Timer}|%msg%n" /> --> + <property name="logDirectory" value="${logDir}/${componentName}/${subComponentName}" /> + <property name="debugLogDirectory" value="${debugDir}/${componentName}/${subComponentName}" /> + <!-- + <property name="logDirectory" value="${logDir}/${componentName}/${subComponentName}" /> + <property name="debugLogDirectory" value="${debugDir}/${componentName}/${subComponentName}" /> + --> + <!-- example from old log4j.properties: ${catalina.base}/logs/pdp-rest.log --> + + <!-- Example evaluator filter applied against console appender --> + <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> + <encoder> + <pattern>${defaultPattern}</pattern> + </encoder> + </appender> + + <!-- ============================================================================ --> + <!-- EELF Appenders --> + <!-- ============================================================================ --> + + <!-- The EELFAppender is used to record events to the general application + log --> + + + + + <!-- EELF Audit Appender. This appender is used to record audit engine + related logging events. The audit logger and appender are specializations + of the EELF application root logger and appender. This can be used to segregate + Policy engine events from other components, or it can be eliminated to record + these events as part of the application root log. --> + + <appender name="EELFAudit" + class="ch.qos.logback.core.rolling.RollingFileAppender"> + <file>${logDirectory}/${auditLogName}.log</file> + <rollingPolicy + class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy"> + <fileNamePattern>${logDirectory}/${auditLogName}.%i.log.zip + </fileNamePattern> + <minIndex>1</minIndex> + <maxIndex>9</maxIndex> + </rollingPolicy> + <triggeringPolicy + class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy"> + <maxFileSize>5MB</maxFileSize> + </triggeringPolicy> + <encoder> + <pattern>${defaultPattern}</pattern> + </encoder> + </appender> + <appender name="asyncEELFAudit" class="ch.qos.logback.classic.AsyncAppender"> + <queueSize>256</queueSize> + <appender-ref ref="EELFAudit" /> + </appender> + +<appender name="EELFMetrics" + class="ch.qos.logback.core.rolling.RollingFileAppender"> + <file>${logDirectory}/${metricsLogName}.log</file> + <rollingPolicy + class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy"> + <fileNamePattern>${logDirectory}/${metricsLogName}.%i.log.zip + </fileNamePattern> + <minIndex>1</minIndex> + <maxIndex>9</maxIndex> + </rollingPolicy> + <triggeringPolicy + class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy"> + <maxFileSize>5MB</maxFileSize> + </triggeringPolicy> + <encoder> + <!-- <pattern>"%d{HH:mm:ss.SSS} [%thread] %-5level %logger{1024} - + %msg%n"</pattern> --> + <pattern>${defaultPattern}</pattern> + </encoder> + </appender> + + + <appender name="asyncEELFMetrics" class="ch.qos.logback.classic.AsyncAppender"> + <queueSize>256</queueSize> + <appender-ref ref="EELFMetrics"/> + </appender> + + <appender name="EELFError" + class="ch.qos.logback.core.rolling.RollingFileAppender"> + <file>${logDirectory}/${errorLogName}.log</file> + <rollingPolicy + class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy"> + <fileNamePattern>${logDirectory}/${errorLogName}.%i.log.zip + </fileNamePattern> + <minIndex>1</minIndex> + <maxIndex>9</maxIndex> + </rollingPolicy> + <filter class="ch.qos.logback.classic.filter.ThresholdFilter"> + <level>ERROR</level> + </filter> + <triggeringPolicy + class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy"> + <maxFileSize>5MB</maxFileSize> + </triggeringPolicy> + <encoder> + <pattern>${defaultPattern}</pattern> + </encoder> + </appender> + + <appender name="asyncEELFError" class="ch.qos.logback.classic.AsyncAppender"> + <queueSize>256</queueSize> + <appender-ref ref="EELFError"/> + </appender> + + <appender name="EELFDebug" + class="ch.qos.logback.core.rolling.RollingFileAppender"> + <file>${debugLogDirectory}/${debugLogName}.log</file> + <rollingPolicy + class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy"> + <fileNamePattern>${debugLogDirectory}/${debugLogName}.%i.log.zip + </fileNamePattern> + <minIndex>1</minIndex> + <maxIndex>9</maxIndex> + </rollingPolicy> + <filter class="ch.qos.logback.classic.filter.ThresholdFilter"> + <!-- <level>INFO</level> --> + <level>DEBUG</level> + </filter> + <triggeringPolicy + class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy"> + <maxFileSize>5MB</maxFileSize> + </triggeringPolicy> + <encoder> + <pattern>${defaultPattern}</pattern> + </encoder> + </appender> + + <appender name="asyncEELFDebug" class="ch.qos.logback.classic.AsyncAppender"> + <queueSize>256</queueSize> + <appender-ref ref="EELFDebug" /> + <includeCallerData>true</includeCallerData> + </appender> + + + <!-- ============================================================================ --> + <!-- EELF loggers --> + <!-- ============================================================================ --> + + <logger name="com.att.eelf.audit" level="info" additivity="false"> + <appender-ref ref="asyncEELFAudit" /> + </logger> + + <logger name="com.att.eelf.metrics" level="info" additivity="false"> + <appender-ref ref="asyncEELFMetrics" /> + </logger> + + <logger name="com.att.eelf.error" level="error" additivity="false"> + <appender-ref ref="asyncEELFError" /> + </logger> + + <!-- <logger name="com.att.eelf.debug" level="info" additivity="false"> --> + <logger name="com.att.eelf.debug" level="debug" additivity="false"> + <appender-ref ref="asyncEELFDebug" /> + </logger> + + <!-- <root level="INFO"> --> + <root level="DEBUG"> + <appender-ref ref="asyncEELFDebug" /> + <appender-ref ref="asyncEELFError" /> + </root> + +</configuration> diff --git a/policy-persistence/src/test/resources/xacmlPersistence.properties b/policy-persistence/src/test/resources/xacmlPersistence.properties new file mode 100644 index 00000000..284e87d7 --- /dev/null +++ b/policy-persistence/src/test/resources/xacmlPersistence.properties @@ -0,0 +1,43 @@ +### +# ============LICENSE_START======================================================= +# policy-persistence +# ================================================================================ +# 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========================================================= +### + +javax.persistence.jdbc.driver = org.h2.Driver +javax.persistence.jdbc.url = jdbc:h2:file:./sql/xacml +javax.persistence.jdbc.user = sa +javax.persistence.jdbc.password = + +#javax.persistence.jdbc.driver=org.mariadb.jdbc.Driver +#javax.persistence.jdbc.url=jdbc:mariadb://127.0.0.1:3306/xacml +#javax.persistence.jdbc.user=root +#javax.persistence.jdbc.password=policy + +#javax.persistence.jdbc.driver = ${{JDBC_DRIVER}} +#javax.persistence.jdbc.url = ${{JDBC_URL}} +#javax.persistence.jdbc.user = ${{JDBC_USER}} +#javax.persistence.jdbc.password = ${{JDBC_PASSWORD}} + +# Needed? +hibernate.dataSource=org.mariadb.jdbc.MySQLDataSource + +# For testing purposes, it may be convenient to disable persistence +persistenceDisabled=false + + + diff --git a/policy-persistence/src/test/server/config/IntegrityMonitor.properties b/policy-persistence/src/test/server/config/IntegrityMonitor.properties new file mode 100644 index 00000000..b16beda9 --- /dev/null +++ b/policy-persistence/src/test/server/config/IntegrityMonitor.properties @@ -0,0 +1,62 @@ +### +# ============LICENSE_START======================================================= +# policy-persistence +# ================================================================================ +# 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========================================================= +### + +# port 9981 fails on Jenkins, so try another. +hostPort = 0.0.0.0:57692 + +# The following were added as part of US673632 +# +# Forward Progress Monitor update interval seconds +fp_monitor_interval = 30 +# Failed counter threshold before failover +failed_counter_threshold = 3 +# Interval between test transactions when no traffic seconds +test_trans_interval = 10 +# Interval between writes of the FPC to the DB seconds +write_fpc_interval = 5 +# Name of the site in which this node is hosted +site_name = pdp_1 +# Node type. Can take values of: pdp-xacml, pdp-drools, pap, pap-admin, logparser, brms-gateway, +# astra-gateway, elk-server and pypdpNode type +# Note: Make sure you don't leave any trailing spaces, or you'll get an 'invalid node type' error! +node_type = pdp_drools +# Dependency groups are groups of resources upon which a node operational state is dependent upon. +# Each group is a comma-separated list of resource names and groups are separated by a semicolon. For example: +#For JUnit testing this must be empty since none of the other components exist +#dependency_groups=site_1.astra_1,site_1.astra_2;site_1.brms_1,site_1.brms_2;site_1.logparser_1;site_1.pypdp_1 +dependency_groups= + +# Needed by DroolsPdpsElectionHandler +pdp.checkInterval=1500 +pdp.updateInterval=1000 +#pdp.timeout=3000 +# Need long timeout, because testTransaction is only run every 10 seconds. +pdp.timeout=15000 +#how long do we wait for the pdp table to populate on initial startup +pdp.initialWait=20000 + +# Known as the PDPID in the droolpdpentity table. +resource.name=pdp1 + +# The amount of this a resource (entity) should sleep between audit executions. +# If not specified, defaults to five seconds. +# -1 turns off audit +# zero forces audit to run continuously +integrity_audit_period_seconds=60 diff --git a/policy-persistence/src/test/server/config/droolsPersistence.properties b/policy-persistence/src/test/server/config/droolsPersistence.properties new file mode 100644 index 00000000..8cdaf6ab --- /dev/null +++ b/policy-persistence/src/test/server/config/droolsPersistence.properties @@ -0,0 +1,35 @@ +### +# ============LICENSE_START======================================================= +# policy-persistence +# ================================================================================ +# 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========================================================= +### + +javax.persistence.jdbc.driver = org.h2.Driver +javax.persistence.jdbc.url = jdbc:h2:file:./sql/drools +javax.persistence.jdbc.user = sa +javax.persistence.jdbc.password = + +#javax.persistence.jdbc.driver=org.mariadb.jdbc.Driver +#javax.persistence.jdbc.url=jdbc:mariadb://localhost:3306/drools +#javax.persistence.jdbc.user=root +#javax.persistence.jdbc.password=policy + +# Needed? +hibernate.dataSource=org.mariadb.jdbc.MySQLDataSource + +# For testing purposes, it may be convenient to disable persistence +persistenceDisabled=false diff --git a/policy-persistence/src/test/server/config/policyLogger.properties b/policy-persistence/src/test/server/config/policyLogger.properties new file mode 100644 index 00000000..6ee66fd6 --- /dev/null +++ b/policy-persistence/src/test/server/config/policyLogger.properties @@ -0,0 +1,44 @@ +### +# ============LICENSE_START======================================================= +# policy-persistence +# ================================================================================ +# 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========================================================= +### + +################################### Set concurrentHashMap and timer info ####################### +#Timer initial delay and the delay between in milliseconds before task is to be execute. +timer.delay.time=1000 +#Timer scheduleAtFixedRate period - time in milliseconds between successive task executions. +check.interval= 30000 +#Longest time an event info can be stored in the concurrentHashMap for logging - in seconds. +event.expired.time=86400 +#Size of the concurrentHashMap which stores the event starting time, etc - when its size reaches this limit, the Timer gets executed +#to remove all expired records from this concurrentHashMap. +concurrentHashMap.limit=5000 +#Size of the concurrentHashMap - when its size drops to this point, stop the Timer +stop.check.point=2500 +################################### Set logging format ############################################# +# set EELF for EELF logging format, set LOG4J for using log4j, set SYSTEMOUT for using system.out.println +logger.type=EELF +#################################### Set level for EELF or SYSTEMOUT logging ################################## +# Set level for debug file. Set DEBUG to enable .info, .warn and .debug; set INFO for enable .info and .warn; set OFF to disable all +debugLogger.level=INFO +# Set level for metrics file. Set OFF to disable; set ON to enable +metricsLogger.level=ON +# Set level for error file. Set OFF to disable; set ON to enable +error.level=ON +# Set level for audit file. Set OFF to disable; set ON to enable +audit.level=ON diff --git a/policy-persistence/src/test/server/config/xacmlPersistence.properties b/policy-persistence/src/test/server/config/xacmlPersistence.properties new file mode 100644 index 00000000..149aa557 --- /dev/null +++ b/policy-persistence/src/test/server/config/xacmlPersistence.properties @@ -0,0 +1,38 @@ +### +# ============LICENSE_START======================================================= +# policy-persistence +# ================================================================================ +# 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========================================================= +### + +javax.persistence.jdbc.driver = org.h2.Driver +javax.persistence.jdbc.url = jdbc:h2:file:./sql/xacml +javax.persistence.jdbc.user = sa +javax.persistence.jdbc.password = + +#javax.persistence.jdbc.driver=org.mariadb.jdbc.Driver +#javax.persistence.jdbc.url=jdbc:mariadb://127.0.0.1:3306/xacml +#javax.persistence.jdbc.user=root +#javax.persistence.jdbc.password=policy + +# Needed? +hibernate.dataSource=org.mariadb.jdbc.MySQLDataSource + +# For testing purposes, it may be convenient to disable persistence +persistenceDisabled=false + + + diff --git a/policy-utils/pom.xml b/policy-utils/pom.xml new file mode 100644 index 00000000..b7ac7fb2 --- /dev/null +++ b/policy-utils/pom.xml @@ -0,0 +1,75 @@ +<?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> + + <artifactId>policy-utils</artifactId> + + <parent> + <groupId>org.openecomp.policy.drools-pdp</groupId> + <artifactId>drools-pdp</artifactId> + <version>1.0.0-SNAPSHOT</version> + </parent> + + + <dependencies> + <dependency> + <groupId>junit</groupId> + <artifactId>junit</artifactId> + <version>4.11</version> + </dependency> + <dependency> + <groupId>log4j</groupId> + <artifactId>log4j</artifactId> + <version>1.2.17</version> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>com.att.eelf</groupId> + <artifactId>eelf-core</artifactId> + <version>0.0.1</version> + </dependency> + <dependency> + <groupId>ch.qos.logback</groupId> + <artifactId>logback-classic</artifactId> + <version>1.1.1</version> + </dependency> + <dependency> + <groupId>ch.qos.logback</groupId> + <artifactId>logback-core</artifactId> + <version>1.1.1</version> + </dependency> + <dependency> + <groupId>org.slf4j</groupId> + <artifactId>slf4j-api</artifactId> + <version>1.7.6</version> + </dependency> + <dependency> + <groupId>org.openecomp.policy.common</groupId> + <artifactId>ECOMP-Logging</artifactId> + <version>${common-modules.version}</version> + </dependency> + </dependencies> + + +</project> diff --git a/policy-utils/src/main/java/org/openecomp/policy/drools/utils/OrderedService.java b/policy-utils/src/main/java/org/openecomp/policy/drools/utils/OrderedService.java new file mode 100644 index 00000000..b50e6e85 --- /dev/null +++ b/policy-utils/src/main/java/org/openecomp/policy/drools/utils/OrderedService.java @@ -0,0 +1,35 @@ +/*- + * ============LICENSE_START======================================================= + * policy-utils + * ================================================================================ + * 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.utils; + +/** + * This is a base interface that is used to control the order of a list + * of services (features) discovered via 'ServiceLoader'. See + * 'OrderedServiceImpl' for more details. + */ +public interface OrderedService +{ + /** + * @return an integer sequence number, which determines the order of a list + * of objects implementing this interface + */ + public int getSequenceNumber(); +} diff --git a/policy-utils/src/main/java/org/openecomp/policy/drools/utils/OrderedServiceImpl.java b/policy-utils/src/main/java/org/openecomp/policy/drools/utils/OrderedServiceImpl.java new file mode 100644 index 00000000..2747e85e --- /dev/null +++ b/policy-utils/src/main/java/org/openecomp/policy/drools/utils/OrderedServiceImpl.java @@ -0,0 +1,117 @@ +/*- + * ============LICENSE_START======================================================= + * policy-utils + * ================================================================================ + * 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.utils; + +import java.util.Collections; +import java.util.Comparator; +import java.util.LinkedList; +import java.util.List; +import java.util.ServiceLoader; + +/** + * This class is a template for building a sorted list of service instances, + * which are discovered and created using 'ServiceLoader'. + */ +public class OrderedServiceImpl<T extends OrderedService> +{ + // sorted list of instances implementing the service + private List<T> implementers = null; + + // 'ServiceLoader' that is used to discover and create the services + private ServiceLoader<T> serviceLoader = null; //ServiceLoader.load(T.class); + + /** + * Constructor - create the 'ServiceLoader' instance + * + * @param clazz the class object associated with 'T' (I supposed it could + * be a subclass, but I'm not sure this is useful) + */ + public OrderedServiceImpl(Class clazz) + { + // This constructor wouldn't be needed if 'T.class' was legal + serviceLoader = ServiceLoader.load(clazz); + } + + /** + * @return the sorted list of services implementing interface 'T' discovered + * by 'ServiceLoader'. + */ + public synchronized List<T> getList() + { + if (implementers == null) + { + rebuildList(); + } + return(implementers); + } + + /** + * This method is called by 'getList', but could also be called directly if + * we were running with a 'ClassLoader' that supported the dynamic addition + * of JAR files. In this case, it could be invoked in order to discover any + * new services implementing interface 'T'. This is probably a relatively + * expensive operation in terms of CPU and elapsed time, so it is best if it + * isn't invoked too frequently. + * + * @return the sorted list of services implementing interface 'T' discovered + * by 'ServiceLoader'. + */ + public synchronized List<T> rebuildList() + { + // build a list of all of the current implementors + List<T> tmp = new LinkedList<T>(); + for (T service : serviceLoader) + { + tmp.add(service); + } + + // Sort the list according to sequence number, and then alphabetically + // according to full class name. + Collections.sort(tmp, new Comparator<T>() + { + public int compare(T o1, T o2) + { + int s1 = o1.getSequenceNumber(); + int s2 = o2.getSequenceNumber(); + int rval; + if (s1 < s2) + { + rval = -1; + } + else if (s1 > s2) + { + rval = 1; + } + else + { + rval = o1.getClass().getName().compareTo + (o2.getClass().getName()); + } + return(rval); + } + }); + + // create an unmodifiable version of this list + implementers = Collections.unmodifiableList(tmp); + System.out.println("***** OrderedServiceImpl implementers:\n" + implementers); + return(implementers); + } +} diff --git a/policy-utils/src/main/java/org/openecomp/policy/drools/utils/Pair.java b/policy-utils/src/main/java/org/openecomp/policy/drools/utils/Pair.java new file mode 100644 index 00000000..a5e34695 --- /dev/null +++ b/policy-utils/src/main/java/org/openecomp/policy/drools/utils/Pair.java @@ -0,0 +1,51 @@ +/*- + * ============LICENSE_START======================================================= + * policy-utils + * ================================================================================ + * 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.utils; + +public class Pair<F,S> { + + protected F first; + protected S second; + + public Pair(F first, S second){ + this.first = first; + this.second = second; + } + + public F first() {return this.first;} + + public S second() {return this.second;} + + public F getFirst() {return this.first;} + + public S getSecond() {return this.second;} + + public void first(F first) {this.first = first;} + + public void second(S second) {this.second = second;} + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("Pair [first=").append(first).append(", second=").append(second).append("]"); + return builder.toString(); + } +} diff --git a/policy-utils/src/main/java/org/openecomp/policy/drools/utils/PropertyUtil.java b/policy-utils/src/main/java/org/openecomp/policy/drools/utils/PropertyUtil.java new file mode 100644 index 00000000..34ddcc1c --- /dev/null +++ b/policy-utils/src/main/java/org/openecomp/policy/drools/utils/PropertyUtil.java @@ -0,0 +1,403 @@ +/*- + * ============LICENSE_START======================================================= + * policy-utils + * ================================================================================ + * 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.utils; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.util.HashMap; +import java.util.HashSet; +import java.util.LinkedList; +import java.util.Properties; +import java.util.Set; +import java.util.Timer; +import java.util.TimerTask; + +/** + * This class provides utilities to read properties from a properties + * file, and optionally get notifications of future changes + */ +public class PropertyUtil +{ + /** + * Read in a properties file + * @param file the properties file + * @return a Properties object, containing the associated properties + * @throws IOException - subclass 'FileNotFoundException' if the file + * does not exist or can't be opened, and 'IOException' if there is + * a problem loading the properties file. + */ + static public Properties getProperties(File file) throws IOException + { + // create an InputStream (may throw a FileNotFoundException) + FileInputStream fis = new FileInputStream(file); + try + { + // create the properties instance + Properties rval = new Properties(); + + // load properties (may throw an IOException) + rval.load(fis); + return(rval); + } + finally + { + // close input stream + fis.close(); + } + } + + /** + * Read in a properties file + * @param fileName the properties file + * @return a Properties object, containing the associated properties + * @throws IOException - subclass 'FileNotFoundException' if the file + * does not exist or can't be opened, and 'IOException' if there is + * a problem loading the properties file. + */ + static public Properties getProperties(String fileName) throws IOException + { + return(getProperties(new File(fileName))); + } + + /* ============================================================ */ + + // timer thread used for polling for property file changes + private static Timer timer = null; + + /** + * This is the callback interface, used for sending notifications of + * changes in the properties file. + */ + public interface Listener + { + /** + * Notification of a properties file change + * @param properties the new properties + * @param the set of property names that have changed, including + * additions and removals + */ + void propertiesChanged(Properties properties, Set<String> changedKeys); + } + + // this table maps canonical file into a 'ListenerRegistration' instance + static private HashMap<File, ListenerRegistration> registrations = + new HashMap<File, ListenerRegistration>(); + + /** + * This is an internal class - one instance of this exists for each + * property file that is being monitored. Note that multiple listeners + * can be registered for the same file. + */ + private static class ListenerRegistration + { + // the canonical path of the file being monitored + File file; + + // the most recent value of 'file.lastModified()' + long lastModified; + + // the most recent set of properties + Properties properties; + + // the set of listeners monitoring this file + LinkedList<Listener> listeners; + + // the 'TimerTask' instance, used for periodic polling + TimerTask timerTask; + + /** + * Constructor - create a 'ListenerRegistration' instance for this + * file, but with no listeners + */ + ListenerRegistration(File file) throws IOException + { + this.file = file; + + // The initial value of 'lastModified' is set to 0 to ensure that we + // correctly handle the case where the file is modified within the + // same second that polling begins. + lastModified = 0; + + // fetch current properties + properties = getProperties(file); + + // no listeners yet + listeners = new LinkedList<Listener>(); + + // add to static table, so this instance can be shared + registrations.put(file, this); + + if (timer == null) + { + // still need to create a timer thread + synchronized(PropertyUtil.class) + { + // an additional check is added inside the 'synchronized' block, + // just in case someone beat us to it + if (timer == null) + { + timer = new Timer("PropertyUtil-Timer", true); + } + } + } + + // create and schedule the timer task, so this is periodically polled + timerTask = new TimerTask() + { + public void run() + { + try + { + poll(); + } + catch (Exception e) + { + System.err.println(e); + } + } + }; + timer.schedule(timerTask, 10000L, 10000L); + } + + /** + * Add a listener to the notification list + * @param listener this is the listener to add to the list + * @return the properties at the moment the listener was added to the list + */ + synchronized Properties addListener(Listener listener) + { + listeners.add(listener); + return((Properties)properties.clone()); + } + + /** + * Remove a listener from the notification list + * @param listener this is the listener to remove + */ + synchronized void removeListener(Listener listener) + { + listeners.remove(listener); + + // See if we need to remove this 'ListenerRegistration' instance + // from the table. The 'synchronized' block is needed in case + // another listener is being added at about the same time that this + // one is being removed. + synchronized(registrations) + { + if (listeners.size() == 0) + { + timerTask.cancel(); + registrations.remove(file); + } + } + } + + /** + * This method is periodically called to check for property list updates + * @throws IOException if there is an error in reading the properties file + */ + synchronized void poll() throws IOException + { + long timestamp = file.lastModified(); + if (timestamp != lastModified) + { + // update the record, and send out the notifications + lastModified = timestamp; + + // Save old set, and initial set of changed properties. + Properties oldProperties = properties; + HashSet<String> changedProperties = + new HashSet<String>(oldProperties.stringPropertyNames()); + + // Fetch the list of listeners that we will potentially notify, + // and the new properties. Note that this is in a 'synchronized' + // block to ensure that all listeners receiving notifications + // actually have a newer list of properties than the one + // returned on the initial 'getProperties' call. + properties = getProperties(file); + + Set<String> newPropertyNames = properties.stringPropertyNames(); + changedProperties.addAll(newPropertyNames); + + // At this point, 'changedProperties' is the union of all properties + // in both the old and new properties files. Iterate through all + // of the entries in the new properties file - if the entry + // matches the one in the old file, remove it from + // 'changedProperties'. + for (String name : newPropertyNames) + { + if (properties.getProperty(name).equals + (oldProperties.getProperty(name))) + { + // Apparently, any property that exists must be of type + // 'String', and can't be null. For this reason, we don't + // need to worry about the case where + // 'properties.getProperty(name)' returns 'null'. Note that + // 'oldProperties.getProperty(name)' may be 'null' if the + // old property does not exist. + changedProperties.remove(name); + } + } + + // 'changedProperties' should be correct at this point + if (changedProperties.size() != 0) + { + // there were changes - notify everyone in 'listeners' + for (final Listener notify : listeners) + { + // Copy 'properties' and 'changedProperties', so it doesn't + // cause problems if the recipient makes changes. + final Properties tmpProperties = + (Properties)(properties.clone()); + final HashSet<String> tmpChangedProperties = + new HashSet<String>(changedProperties); + + // Do the notification in a separate thread, so blocking + // won't cause any problems. + new Thread() + { + public void run() + { + notify.propertiesChanged + (tmpProperties, tmpChangedProperties); + } + }.start(); + } + } + } + } + } + + /** + * Read in a properties file, and register for update notifications. + * NOTE: it is possible that the first callback will occur while this + * method is still in progress. To avoid this problem, use 'synchronized' + * blocks around this invocation and in the callback -- that will ensure + * that the processing of the initial properties complete before any + * updates are processed. + * + * @param file the properties file + * @param notify if not null, this is a callback interface that is used for + * notifications of changes + * @return a Properties object, containing the associated properties + * @throws IOException - subclass 'FileNotFoundException' if the file + * does not exist or can't be opened, and 'IOException' if there is + * a problem loading the properties file. + */ + static public Properties getProperties(File file, Listener listener) + throws IOException + { + if (listener == null) + { + // no listener specified -- just fetch the properties + return(getProperties(file)); + } + + // Convert the file to a canonical form in order to avoid the situation + // where different names refer to the same file. + file = file.getCanonicalFile(); + + // See if there is an existing registration. The 'synchronized' block + // is needed to handle the case where a new listener is added at about + // the same time that another one is being removed. + synchronized(registrations) + { + ListenerRegistration reg = registrations.get(file); + if (reg == null) + { + // a new registration is needed + reg = new ListenerRegistration(file); + } + return(reg.addListener(listener)); + } + } + + /** + * Read in a properties file, and register for update notifications. + * NOTE: it is possible that the first callback will occur while this + * method is still in progress. To avoid this problem, use 'synchronized' + * blocks around this invocation and in the callback -- that will ensure + * that the processing of the initial properties complete before any + * updates are processed. + * + * @param fileName the properties file + * @param notify if not null, this is a callback interface that is used for + * notifications of changes + * @return a Properties object, containing the associated properties + * @throws IOException - subclass 'FileNotFoundException' if the file + * does not exist or can't be opened, and 'IOException' if there is + * a problem loading the properties file. + */ + static public Properties getProperties(String fileName, Listener listener) + throws IOException + { + return(getProperties(new File(fileName), listener)); + } + + /** + * Stop listenening for updates + * @param file the properties file + * @param notify if not null, this is a callback interface that was used for + * notifications of changes + */ + static public void stopListening(File file, Listener listener) + { + if (listener != null) + { + ListenerRegistration reg = registrations.get(file); + if (reg != null) + { + reg.removeListener(listener); + } + } + } + + /** + * Stop listenening for updates + * @param fileName the properties file + * @param notify if not null, this is a callback interface that was used for + * notifications of changes + */ + static public void stopListening(String fileName, Listener listener) + { + stopListening(new File(fileName), listener); + } + + /* ============================================================ */ + + // TEMPORARY - used to test callback interface + static public class Test implements Listener + { + String name; + + public Test(String name) + { + this.name = name; + } + + public void propertiesChanged(Properties properties, Set<String> changedKeys) + { + System.out.println("Test(" + name + ")\nproperties = " + properties + + "\nchangedKeys = " + changedKeys); + } + } +} diff --git a/policy-utils/src/main/java/org/openecomp/policy/drools/utils/ReflectionUtil.java b/policy-utils/src/main/java/org/openecomp/policy/drools/utils/ReflectionUtil.java new file mode 100644 index 00000000..0b86c2aa --- /dev/null +++ b/policy-utils/src/main/java/org/openecomp/policy/drools/utils/ReflectionUtil.java @@ -0,0 +1,92 @@ +/*- + * ============LICENSE_START======================================================= + * policy-utils + * ================================================================================ + * 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.utils; + +import org.openecomp.policy.common.logging.eelf.PolicyLogger; + +/** + * Reflection utilities + * + */ +public class ReflectionUtil { + + /** + * returns (if exists) a class fetched from a given classloader + * + * @param classLoader the class loader + * @param classname the class name + * @return the PolicyEvent class + * @throws IllegalArgumentException if an invalid parameter has been passed in + */ + public static Class<?> fetchClass(ClassLoader classLoader, + String classname) + throws IllegalArgumentException { + + PolicyLogger.info("FETCH-CLASS: " + classname + " FROM " + classLoader); + + if (classLoader == null) + throw new IllegalArgumentException("A class loader must be provided"); + + if (classname == null) + throw new IllegalArgumentException("A class name to be fetched in class loader " + + classLoader + " must be provided"); + + try { + Class<?> aClass = Class.forName(classname, + true, + classLoader); + return aClass; + } catch (Exception e) { + e.printStackTrace(); + PolicyLogger.error("FETCH-CLASS: " + classname + " IN " + classLoader + " does NOT exist"); + } + + return null; + } + + /** + * + * @param classLoader target class loader + * @param classname class name to fetch + * @return true if exists + * @throws IllegalArgumentException if an invalid parameter has been passed in + */ + public static boolean isClass(ClassLoader classLoader, String classname) + throws IllegalArgumentException { + return fetchClass(classLoader, classname) != null; + } + + /** + * is a subclass? + * @param parent superclass + * @param presumedSubclass subclass + * @return + */ + public static boolean isSubclass(Class<?> parent, Class<?> presumedSubclass) { + PolicyLogger.debug("IS-SUBCLASS: superclass: " + parent.getCanonicalName() + + " subclass: " + presumedSubclass.getCanonicalName()); + return (parent.isAssignableFrom(presumedSubclass)); + } + +} diff --git a/policy-utils/src/main/java/org/openecomp/policy/drools/utils/Triple.java b/policy-utils/src/main/java/org/openecomp/policy/drools/utils/Triple.java new file mode 100644 index 00000000..214d949e --- /dev/null +++ b/policy-utils/src/main/java/org/openecomp/policy/drools/utils/Triple.java @@ -0,0 +1,45 @@ +/*- + * ============LICENSE_START======================================================= + * policy-utils + * ================================================================================ + * 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.utils; + +public class Triple<F,S,T> { + + private F first; + private S second; + private T third; + + public Triple(F first, S second, T third){ + this.first = first; + this.second = second; + this.third = third; + } + public F first(){ return this.first; } + + public S second(){ return this.second; } + + public T third(){ return this.third; } + + public void first(F first){ this.first = first; } + + public void second(S second){ this.second = second; } + + public void third(T third){ this.third = third; } +} diff --git a/policy-utils/src/test/java/org/openecomp/policy/drools/utils/PropertyUtilTest.java b/policy-utils/src/test/java/org/openecomp/policy/drools/utils/PropertyUtilTest.java new file mode 100644 index 00000000..55091718 --- /dev/null +++ b/policy-utils/src/test/java/org/openecomp/policy/drools/utils/PropertyUtilTest.java @@ -0,0 +1,204 @@ +/*- + * ============LICENSE_START======================================================= + * policy-utils + * ================================================================================ + * 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.utils; + +import static org.junit.Assert.*; + +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.util.Arrays; +import java.util.Properties; +import java.util.Set; +import java.util.TreeSet; +import java.util.UUID; + +import org.apache.log4j.Logger; + +import org.openecomp.policy.common.logging.eelf.PolicyLogger; + +public class PropertyUtilTest +{ + // private static final Logger PolicyLogger = +// Logger.getLogger(PropertyUtilTest.class.getName()); + + private static File directory = null; + + /** + * Test Setup -- Create a directory for temporary files + */ + @BeforeClass + static public void setup() + { + PolicyLogger.info("setup: creating a temporary directory"); + + // create a directory for temporary files + directory = new File(UUID.randomUUID().toString()); + directory.mkdir(); + } + + /** + * Test Cleanup -- Remove temporary files + */ + @AfterClass + static public void teardown() + { + PolicyLogger.info("teardown: remove the temporary directory"); + + // the assumption is that we only have one level of temporary files + for (File file : directory.listFiles()) + { + file.delete(); + } + directory.delete(); + } + + /** + * Utility method to write a properties file + * + * @param name the file name, relative to the temporary directory + * @param the properties to store in the file + * @return a File instance associated with the newly-created file + * @throws IOException if the file can't be created for some reason + */ + File createFile(String name, Properties p) throws IOException + { + File file = new File(directory, name); + FileOutputStream fos = new FileOutputStream(file); + try + { + p.store(fos, "Property file '" + name + "'"); + } + finally + { + fos.close(); + } + return(file); + } + + /** + * Create a 'PropertyUtil.Listener' subclass, which receives property + * file updates. It stores the latest values in an array, and notifies + * any thread waiting on this array. + * + * @param returns this is an array of length 2 -- the first entry will + * contain the 'properties' value, and the second will contain + * 'changedKeys'. It is also used to signal any waiting thread + * using 'returns.notifyAll()'. + */ + PropertyUtil.Listener createListenerThread(final Object[] returns) + { + return(new PropertyUtil.Listener() + { + public void propertiesChanged + (Properties properties, Set<String> changedKeys) + { + // When a notification is received, store the values in the + // 'returns' array, and signal using the same array. + PolicyLogger.info("Listener invoked: properties=" + properties + + ", changedKeys=" + changedKeys); + returns[0] = properties; + returns[1] = changedKeys; + synchronized(returns) + { + returns.notifyAll(); + } + } + }); + } + + /** + * Test the basic properties file interface. + */ + @Test + public void testGetProperties() throws Exception + { + PolicyLogger.info("testGetProperties: test the basic properties file interface"); + + // copy system properties + PolicyLogger.info("Copy system properties to a file"); + Properties prop1 = System.getProperties(); + File file1 = createFile("createAndReadPropertyFile-1", prop1); + + // read in properties, and compare + PolicyLogger.info("Read in properties from new file"); + Properties prop2 = PropertyUtil.getProperties(file1); + + // they should match + assertEquals(prop1, prop2); + } + + /** + * This tests the 'PropertyUtil.Listener' interface. + */ + @Test + public void testListenerInterface() throws Exception + { + PolicyLogger.info("testListenerInterface: test receipt of dynamic updates"); + + // create initial property file + Properties prop1 = new Properties(); + prop1.setProperty("p1", "p1 value"); + prop1.setProperty("p2", "p2 value"); + prop1.setProperty("p3", "p3 value"); + PolicyLogger.info("Create initial properties file: " + prop1); + File file1 = createFile("createAndReadPropertyFile-2", prop1); + + // create a listener for the notification interface + Object[] returns = new Object[2]; + PropertyUtil.Listener listener = createListenerThread(returns); + + // read it in, and do a comparison + Properties prop2 = PropertyUtil.getProperties(file1, listener); + PolicyLogger.info("Read in properties: " + prop2); + assertEquals(prop1, prop2); + assertEquals(prop2.getProperty("p1"), "p1 value"); + assertEquals(prop2.getProperty("p2"), "p2 value"); + assertEquals(prop2.getProperty("p3"), "p3 value"); + + // make some changes, and update the file (p3 is left unchanged) + prop2.remove("p1"); // remove one property + prop2.setProperty("p2", "new p2 value"); // change one property + prop2.setProperty("p4", "p4 value"); // add a new property + PolicyLogger.info("Modified properties: " + prop2); + + // now, update the file, and wait for notification + synchronized(returns) + { + createFile("createAndReadPropertyFile-2", prop2); + + // wait up to 60 seconds, although we should receive notification + // in 10 seconds or less (if things are working) + returns.wait(60000L); + } + + // verify we have the updates + assertEquals(prop2, returns[0]); + + // verify that we have the expected set of keys + assertEquals(new TreeSet(Arrays.asList(new String[]{"p1", "p2", "p4"})), + returns[1]); + } +} diff --git a/policy-utils/src/test/resources/log4j.properties b/policy-utils/src/test/resources/log4j.properties new file mode 100644 index 00000000..0063f104 --- /dev/null +++ b/policy-utils/src/test/resources/log4j.properties @@ -0,0 +1,26 @@ +### +# ============LICENSE_START======================================================= +# policy-utils +# ================================================================================ +# 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========================================================= +### + +log4j.rootLogger=INFO, out + +# CONSOLE appender not used by default +log4j.appender.out=org.apache.log4j.ConsoleAppender +log4j.appender.out.layout=org.apache.log4j.PatternLayout +log4j.appender.out.layout.ConversionPattern=%d %-5p %-30.30c{1} %4L - %m%n diff --git a/pom.xml b/pom.xml new file mode 100644 index 00000000..04002099 --- /dev/null +++ b/pom.xml @@ -0,0 +1,194 @@ +<!-- + ============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>drools-pdp</artifactId> + <version>1.0.0-SNAPSHOT</version> + <packaging>pom</packaging> + <name>ECOMP Policy Engine - Drools PDP</name> + + <description>The ECOMP Policy Engine drools-based PDP Project</description> + + <properties> + <maven.compiler.source>1.8</maven.compiler.source> + <maven.compiler.target>1.8</maven.compiler.target> + + <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> + <project.source.version>1.8</project.source.version> + <project.target.version>1.8</project.target.version> + <!-- <common-modules.version>[1.0.0-SNAPSHOT]</common-modules.version> --> + <common-modules.version>1.0.0-SNAPSHOT</common-modules.version> + + <sonar.language>java</sonar.language> + <sonar.java.coveragePlugin>jacoco</sonar.java.coveragePlugin> + <sonar.surefire.reportsPath>${project.build.directory}/surefire-reports</sonar.surefire.reportsPath> + <sonar.jacoco.reportPath>${project.build.directory}/coverage-reports/jacoco.exec</sonar.jacoco.reportPath> + <sonar.jacoco.itReportPath>/opt/app/jacoco-it.exec</sonar.jacoco.itReportPath> + <sonar.jacoco.reportMissing.force.zero>true</sonar.jacoco.reportMissing.force.zero> + </properties> + + <modules> + <module>policy-utils</module> + <module>policy-core</module> + <module>policy-endpoints</module> + <module>policy-management</module> + <module>policy-persistence</module> + <module>policy-healthcheck</module> + <module>packages</module> + </modules> + + <repositories> + <repository> + <id>central</id> + <name>Maven 2 repository</name> + <url>http://repo2.maven.org/maven2/</url> + </repository> + + <repository> + <id>eclipse</id> + <url>https://repo.eclipse.org/content/repositories/releases</url> + <releases> + <enabled>true</enabled> + <updatePolicy>daily</updatePolicy> + </releases> + <snapshots> + <enabled>false</enabled> + </snapshots> + </repository> + + <repository> + <id>soapUI</id> + <url>http://www.soapui.org/repository/maven2/</url> + <name>SoapUI plugin</name> + </repository> + </repositories> + + <dependencies> + + </dependencies> + + <build> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-deploy-plugin</artifactId> + <version>2.8</version> <!-- This version supports the "deployAtEnd" parameter --> + </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-compiler-plugin</artifactId> + <version>3.0</version> + <configuration> + <encoding>${project.encoding}</encoding> + <source>${project.source.version}</source> + <target>${project.target.version}</target> + </configuration> + </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-resources-plugin</artifactId> + <version>2.6</version> + <configuration> + <encoding>${project.encoding}</encoding> + </configuration> + </plugin> + <!-- + license plugin + Run + mvn clean + before running from the command line + mvn license:update-file-header + --> + <plugin> + <groupId>org.codehaus.mojo</groupId> + <artifactId>license-maven-plugin</artifactId> + <version>1.9</version> + <configuration> + <extraExtensions> + <!-- Used to add or change the header style <fileTypeYouAreMapping> + fileTypeMappedInto </fileTypeYouAreMapping> --> + <drl>java</drl> + <ccf>properties</ccf> + + <!-- Because the typical sql comment type confuses the update algorithm --> + <sql>java</sql> + </extraExtensions> + <licenseName>apache_v2</licenseName> + + <inceptionYear>2017</inceptionYear> + <organizationName>AT&T Intellectual Property. All rights reserved.</organizationName> + + <!-- Once you have established the tags and delimiter, they cannot be + changed --> + <processStartTag>============LICENSE_START=======================================================</processStartTag> + <processEndTag>============LICENSE_END=========================================================</processEndTag> + <sectionDelimiter>================================================================================</sectionDelimiter> + <addJavaLicenseAfterPackage>false</addJavaLicenseAfterPackage> + <canUpdateCopyright>true</canUpdateCopyright> + <canUpdateDescription>true</canUpdateDescription> + <canUpdateLicense>true</canUpdateLicense> + <emptyLineAfterHeader>true</emptyLineAfterHeader> + <roots> + <!-- Default is src, target/generated-sources, target/processed-sources --> + + <!-- Everything except the files in the excludes section --> + <root>/</root> + </roots> + <excludes> + <!-- Files which are to be excluded. The pom.xml is excluded because + the start/end tags and the delimiters are in the body of the file. This confuses + the algorithm. So, this file must be manually updated with a license header. --> + <exclude>pom.xml</exclude> + </excludes> + </configuration> + </plugin> + </plugins> + <pluginManagement> + <plugins> + <plugin> + <groupId>org.jacoco</groupId> + <artifactId>jacoco-maven-plugin</artifactId> + <version>0.7.5.201505241946</version> + <configuration> + <dumpOnExit>true</dumpOnExit> + <includes> + <include>org.openecomp.*</include> + </includes> + </configuration> + <executions> + <execution> + <id>jacoco-initialize-unit-tests</id> + <goals> + <goal>prepare-agent</goal> + </goals> + <configuration> + <destFile>${project.build.directory}/coverage-reports/jacoco.exec</destFile> + </configuration> + </execution> + </executions> + </plugin> + </plugins> + </pluginManagement> + </build> +</project> diff --git a/project-configs/maven/conf/settings.xml b/project-configs/maven/conf/settings.xml new file mode 100644 index 00000000..55687cde --- /dev/null +++ b/project-configs/maven/conf/settings.xml @@ -0,0 +1,162 @@ +<?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========================================================= + --> + + +<!-- Licensed to the Apache Software Foundation (ASF) under one or more contributor + license agreements. See the NOTICE file distributed with this work for additional + information regarding copyright ownership. The ASF licenses this file to + you 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. --> + + + +<!-- | This is the configuration file for Maven. It can be specified at two + levels: | | 1. User Level. This settings.xml file provides configuration + for a single user, | and is normally provided in ${user.home}/.m2/settings.xml. + | | NOTE: This location can be overridden with the CLI option: | | -s /path/to/user/settings.xml + | | 2. Global Level. This settings.xml file provides configuration for all + Maven | users on a machine (assuming they're all using the same Maven | installation). + It's normally provided in | ${maven.home}/conf/settings.xml. | | NOTE: This + location can be overridden with the CLI option: | | -gs /path/to/global/settings.xml + | | The sections in this sample file are intended to give you a running start + at | getting the most out of your Maven installation. Where appropriate, + the default | values (values used when the setting is not specified) are + provided. | | --> +<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0 http://maven.apache.org/xsd/settings-1.0.0.xsd"> + <!-- localRepository | The path to the local repository maven will use to + store artifacts. | | Default: ${user.home}/.m2/repository <localRepository>/path/to/local/repo</localRepository> --> + <localRepository>${user.home}/.m2/repository</localRepository> + <!-- interactiveMode | This will determine whether maven prompts you when + it needs input. If set to false, | maven will use a sensible default value, + perhaps based on some other setting, for | the parameter in question. | | + Default: true <interactiveMode>true</interactiveMode> --> + + <!-- offline | Determines whether maven should attempt to connect to the + network when executing a build. | This will have an effect on artifact downloads, + artifact deployment, and others. | | Default: false <offline>false</offline> --> + + <!-- pluginGroups | This is a list of additional group identifiers that + will be searched when resolving plugins by their prefix, i.e. | when invoking + a command line like "mvn prefix:goal". Maven will automatically add the group + identifiers | "org.apache.maven.plugins" and "org.codehaus.mojo" if these + are not already contained in the list. | --> + <pluginGroups> + <!-- pluginGroup | Specifies a further group identifier to use for plugin + lookup. <pluginGroup>com.your.plugins</pluginGroup> --> + </pluginGroups> + + <!-- proxies | This is a list of proxies which can be used on this machine + to connect to the network. | Unless otherwise specified (by system property + or command-line switch), the first proxy | specification in this list marked + as active will be used. | --> + <proxies> + </proxies> + + <!-- servers | This is a list of authentication profiles, keyed by the server-id + used within the system. | Authentication profiles can be used whenever maven + must make a connection to a remote server. | --> + <servers> + <!-- server | Specifies the authentication information to use when connecting + to a particular server, identified by | a unique name within the system (referred + to by the 'id' attribute below). | | NOTE: You should either specify username/password + OR privateKey/passphrase, since these pairings are | used together. | <server> + <id>deploymentRepo</id> <username>repouser</username> <password>repopwd</password> + </server> --> + + <!-- Another sample, using keys to authenticate. <server> <id>siteServer</id> + <privateKey>/path/to/private/key</privateKey> <passphrase>optional; leave + empty if not used.</passphrase> </server> --> + </servers> + + <!-- mirrors | This is a list of mirrors to be used in downloading artifacts + from remote repositories. | | It works like this: a POM may declare a repository + to use in resolving certain artifacts. | However, this repository may have + problems with heavy traffic at times, so people have mirrored | it to several + places. | | That repository definition will have a unique id, so we can create + a mirror reference for that | repository, to be used as an alternate download + site. The mirror site will be the preferred | server for that repository. + | --> + <mirrors> + <!-- mirror | Specifies a repository mirror site to use instead of a given + repository. The repository that | this mirror serves has an ID that matches + the mirrorOf element of this mirror. IDs are used | for inheritance and direct + lookup purposes, and must be unique across the set of mirrors. | --> + </mirrors> + + <!-- profiles | This is a list of profiles which can be activated in a variety + of ways, and which can modify | the build process. Profiles provided in the + settings.xml are intended to provide local machine- | specific paths and + repository locations which allow the build to work in the local environment. + | | For example, if you have an integration testing plugin - like cactus + - that needs to know where | your Tomcat instance is installed, you can provide + a variable here such that the variable is | dereferenced during the build + process to configure the cactus plugin. | | As noted above, profiles can + be activated in a variety of ways. One way - the activeProfiles | section + of this document (settings.xml) - will be discussed later. Another way essentially + | relies on the detection of a system property, either matching a particular + value for the property, | or merely testing its existence. Profiles can also + be activated by JDK version prefix, where a | value of '1.4' might activate + a profile when the build is executed on a JDK version of '1.4.2_07'. | Finally, + the list of active profiles can be specified directly from the command line. + | | NOTE: For profiles defined in the settings.xml, you are restricted to + specifying only artifact | repositories, plugin repositories, and free-form + properties to be used as configuration | variables for plugins in the POM. + | | --> + <profiles> + <!-- profile | Specifies a set of introductions to the build process, to + be activated using one or more of the | mechanisms described above. For inheritance + purposes, and to activate profiles via <activatedProfiles/> | or the command + line, profiles have to have an ID that is unique. | | An encouraged best + practice for profile identification is to use a consistent naming convention + | for profiles, such as 'env-dev', 'env-test', 'env-production', 'user-jdcasey', + 'user-brett', etc. | This will make it more intuitive to understand what + the set of introduced profiles is attempting | to accomplish, particularly + when you only have a list of profile id's for debug. | | This profile example + uses the JDK version to trigger activation, and provides a JDK-specific repo. + <profile> <id>jdk-1.4</id> <activation> <jdk>1.4</jdk> </activation> <repositories> + <repository> <id>jdk14</id> <name>Repository for JDK 1.4 builds</name> <url>http://www.myhost.com/maven/jdk14</url> + <layout>default</layout> <snapshotPolicy>always</snapshotPolicy> </repository> + </repositories> </profile> --> + + <!-- | Here is another profile, activated by the system property 'target-env' + with a value of 'dev', | which provides a specific path to the Tomcat instance. + To use this, your plugin configuration | might hypothetically look like: + | | ... | <plugin> | <groupId>org.myco.myplugins</groupId> | <artifactId>myplugin</artifactId> + | | <configuration> | <tomcatLocation>${tomcatPath}</tomcatLocation> | </configuration> + | </plugin> | ... | | NOTE: If you just wanted to inject this configuration + whenever someone set 'target-env' to | anything, you could just leave off + the <value/> inside the activation-property. | <profile> <id>env-dev</id> + <activation> <property> <name>target-env</name> <value>dev</value> </property> + </activation> <properties> <tomcatPath>/path/to/tomcat/instance</tomcatPath> + </properties> </profile> --> + </profiles> + + <!-- activeProfiles | List of profiles that are active for all builds. | + <activeProfiles> <activeProfile>alwaysActiveProfile</activeProfile> <activeProfile>anotherAlwaysActiveProfile</activeProfile> + </activeProfiles> --> +</settings> diff --git a/version.properties b/version.properties new file mode 100644 index 00000000..56ab0aff --- /dev/null +++ b/version.properties @@ -0,0 +1,35 @@ +### +# ============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========================================================= +### + +########################################################### +# Versioning variables +# Note that these variables cannot be structured (e.g. : version.release or version.snapshot etc... ) +# because they are used in Jenkins, whose plug-in doesn't support + +release_name=1 +sprint_number=0 +feature_revision=0 +swm_revision=1 + +base_version=${release_name}.${sprint_number}.${feature_revision} + +# Release must be completed with svn revision # in Jenkins +release_version=${base_version}-${swm_revision} +snapshot_version=${base_version}-SNAPSHOT |