diff options
Diffstat (limited to 'sli/common/src/main/java/org/onap')
36 files changed, 5172 insertions, 0 deletions
diff --git a/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/ActivationEntry.java b/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/ActivationEntry.java new file mode 100644 index 000000000..a1c0eafe8 --- /dev/null +++ b/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/ActivationEntry.java @@ -0,0 +1,41 @@ +/*- + * ============LICENSE_START======================================================= + * openECOMP : SDN-C + * ================================================================================ + * 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.onap.ccsdk.sli.core.sli; + +public class ActivationEntry { + String module; + String rpc; + String version; + String mode; + + public ActivationEntry(String module, String rpc, String version, String mode) { + this.module = module; + this.rpc = rpc; + this.version = version; + this.mode = mode; + } + + @Override + public String toString() { + return "ActivationEntry [module=" + module + ", rpc=" + rpc + ", version=" + version + ", mode=" + mode + "]"; + } +} diff --git a/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/BreakNodeException.java b/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/BreakNodeException.java new file mode 100644 index 000000000..e1c0e3db5 --- /dev/null +++ b/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/BreakNodeException.java @@ -0,0 +1,46 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP : CCSDK + * ================================================================================ + * 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.onap.ccsdk.sli.core.sli; + +public class BreakNodeException extends SvcLogicException { + + /** + * + */ + private static final long serialVersionUID = 1L; + + public BreakNodeException() + { + super(); + } + + public BreakNodeException(String message) + { + super(message); + } + + public BreakNodeException(String message, Throwable t) + { + super(message, t); + } + +} diff --git a/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/CheckSumHelper.java b/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/CheckSumHelper.java new file mode 100644 index 000000000..9283cf650 --- /dev/null +++ b/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/CheckSumHelper.java @@ -0,0 +1,51 @@ +/*- + * ============LICENSE_START======================================================= + * openECOMP : SDN-C + * ================================================================================ + * 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.onap.ccsdk.sli.core.sli; + + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; + +import org.onap.ccsdk.sli.core.utils.PathValidator; + +import javax.xml.bind.DatatypeConverter; + +public class CheckSumHelper { + + public static String md5SumFromFile(String pathToFile) throws NoSuchAlgorithmException, IOException { + if (!PathValidator.isValidXmlPath(pathToFile)) { + throw new IOException("Invalid XML file name"); + } + byte[] b = Files.readAllBytes(Paths.get(pathToFile)); + return md5SumFromByteArray(b); + } + + private static String md5SumFromByteArray(byte[] input) throws NoSuchAlgorithmException { + byte[] hash = MessageDigest.getInstance("MD5").digest(input); + String hexString = DatatypeConverter.printHexBinary(hash); + return hexString.toLowerCase(); + } + +} diff --git a/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/CommonConstants.java b/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/CommonConstants.java new file mode 100644 index 000000000..b1a7320d7 --- /dev/null +++ b/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/CommonConstants.java @@ -0,0 +1,38 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP : CCSDK + * ================================================================================ + * 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.onap.ccsdk.sli.core.sli; + +public interface CommonConstants { + + String SERVICE_LOGIC_STATUS = "SvcLogic.status"; + String JDBC_CONN_ERR = "no jdbc connection"; + String JDBC_STATEMENT_ERR = "could not prepare statement "; + String SVCLOGIC_TABLE = ".SVC_LOGIC"; + String JDBC_SELECT_COUNT = "SELECT count(*) FROM "; + String RESULTSET_CLOSE_ERR = "ResultSet close error: "; + String JDBC_SELECT_GRAPGH = "SELECT graph FROM "; + String JDBC_INSERT = "INSERT INTO "; + String JDBC_DELETE = "DELETE FROM "; + String JDBC_UPDATE = "UPDATE "; + String JDBC_GRAPH_QUERY = " WHERE module = ? AND rpc = ? AND mode = ? AND version = ?"; + String JDBC_ACTIVE_GRAPH_QUERY = " WHERE module = ? AND rpc = ? AND mode = ? AND active = 'Y'"; +} diff --git a/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/ConfigurationException.java b/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/ConfigurationException.java new file mode 100644 index 000000000..144b99a8a --- /dev/null +++ b/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/ConfigurationException.java @@ -0,0 +1,45 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP : CCSDK + * ================================================================================ + * 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.onap.ccsdk.sli.core.sli; + +public class ConfigurationException extends SvcLogicException { + + /** + * + */ + private static final long serialVersionUID = 1L; + + public ConfigurationException() + { + super(); + } + + public ConfigurationException(String msg) + { + super(msg); + } + + public ConfigurationException(String msg, Throwable t) + { + super(msg, t); + } +} diff --git a/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/DuplicateValueException.java b/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/DuplicateValueException.java new file mode 100644 index 000000000..43f4fe53e --- /dev/null +++ b/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/DuplicateValueException.java @@ -0,0 +1,45 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP : CCSDK + * ================================================================================ + * 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.onap.ccsdk.sli.core.sli; + +public class DuplicateValueException extends SvcLogicException { + + /** + * + */ + private static final long serialVersionUID = 1L; + + public DuplicateValueException() + { + super(); + } + + public DuplicateValueException(String message) + { + super(message); + } + + public DuplicateValueException(String message, Throwable t) + { + super(message, t); + } +} diff --git a/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/ErrorLogger.java b/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/ErrorLogger.java new file mode 100644 index 000000000..47f6526e9 --- /dev/null +++ b/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/ErrorLogger.java @@ -0,0 +1,100 @@ +package org.onap.ccsdk.sli.core.sli;
+
+import org.onap.logging.ref.slf4j.ONAPLogConstants;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.slf4j.MDC;
+
+public class ErrorLogger {
+ public static final int ERROR_CODE_100 = 100;
+ public static final int ERROR_CODE_200 = 200;
+ public static final int ERROR_CODE_300 = 300;
+ public static final int ERROR_CODE_400 = 400;
+ public static final int ERROR_CODE_500 = 500;
+ public static final int ERROR_CODE_900 = 900;
+
+ private static final String DEFAULT_100_DESCRIPTION = "Permission Error";
+ private static final String DEFAULT_200_DESCRIPTION = "Availability Error or Timeout";
+ private static final String DEFAULT_300_DESCRIPTION = "Data Error";
+ private static final String DEFAULT_400_DESCRIPTION = "Schema Error";
+ private static final String DEFAULT_500_DESCRIPTION = "Business Process Error";
+ private static final String DEFAULT_900_DESCRIPTION = "Unknown Error";
+ private Logger log;
+
+ public ErrorLogger() {
+ this.log = LoggerFactory.getLogger(ErrorLogger.class);
+ }
+
+ public ErrorLogger(Logger log) {
+ this.log = log;
+ }
+
+ public void logError(String message, int errorCode) {
+ createLogEntry(message, errorCode, null, null);
+ }
+
+ public void logError(String message, int errorCode, Exception e) {
+ createLogEntry(message, errorCode, null, e);
+ }
+
+ public void logError(String message, int errorCode, String description) {
+ createLogEntry(message, errorCode, description, null);
+ }
+
+ public void logError(String message, int errorCode, String description, Exception e) {
+ createLogEntry(message, errorCode, description, e);
+ }
+
+ public void createLogEntry(String message, int errorCode, String description, Exception e) {
+ //If the error code isn't valid default it to unknown error code
+ if(!isValidCode(errorCode)) {
+ errorCode = 900;
+ }
+
+ MDC.put(ONAPLogConstants.MDCs.ERROR_CODE, String.valueOf(errorCode));
+
+ if (description == null || description.isEmpty()) {
+ description = getDefaultDescription(errorCode);
+ }
+
+ MDC.put(ONAPLogConstants.MDCs.ERROR_DESC, description);
+ if (e != null) {
+ log.error(message, e);
+ } else {
+ log.error(message);
+ }
+ clearKeys();
+ }
+
+ public boolean isValidCode(int errorCode) {
+ if (errorCode == ERROR_CODE_100 || errorCode == ERROR_CODE_200 || errorCode == ERROR_CODE_300 || errorCode == ERROR_CODE_400 || errorCode == ERROR_CODE_500
+ || errorCode == ERROR_CODE_900) {
+ return true;
+ }
+ return false;
+ }
+
+ public String getDefaultDescription(int errorCode) {
+ if (errorCode == ERROR_CODE_100) {
+ return DEFAULT_100_DESCRIPTION;
+ }
+ if (errorCode == ERROR_CODE_200) {
+ return DEFAULT_200_DESCRIPTION;
+ }
+ if (errorCode == ERROR_CODE_300) {
+ return DEFAULT_300_DESCRIPTION;
+ }
+ if (errorCode == ERROR_CODE_400) {
+ return DEFAULT_400_DESCRIPTION;
+ }
+ if (errorCode == ERROR_CODE_500) {
+ return DEFAULT_500_DESCRIPTION;
+ }
+ return DEFAULT_900_DESCRIPTION;
+ }
+
+ public void clearKeys() {
+ MDC.remove(ONAPLogConstants.MDCs.ERROR_CODE);
+ MDC.remove(ONAPLogConstants.MDCs.ERROR_DESC);
+ }
+}
diff --git a/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/ExitNodeException.java b/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/ExitNodeException.java new file mode 100755 index 000000000..f119c1812 --- /dev/null +++ b/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/ExitNodeException.java @@ -0,0 +1,46 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP : CCSDK + * ================================================================================ + * 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.onap.ccsdk.sli.core.sli; + +public class ExitNodeException extends SvcLogicException { + + /** + * + */ + private static final long serialVersionUID = 1L; + + public ExitNodeException() + { + super(); + } + + public ExitNodeException(String message) + { + super(message); + } + + public ExitNodeException(String message, Throwable t) + { + super(message, t); + } + +} diff --git a/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/MessageWriter.java b/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/MessageWriter.java new file mode 100644 index 000000000..5ededb9eb --- /dev/null +++ b/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/MessageWriter.java @@ -0,0 +1,281 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP : CCSDK + * ================================================================================ + * 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.onap.ccsdk.sli.core.sli; + +import java.io.File; +import java.io.FileInputStream; +import java.sql.SQLException; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Date; +import java.util.Properties; +import javax.sql.rowset.CachedRowSet; +import org.onap.ccsdk.sli.core.dblib.DbLibService; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +@Deprecated +public class MessageWriter { + + private static final Logger LOG = LoggerFactory.getLogger(MessageWriter.class); + + private static final String DBLIB_SERVICE = "org.onap.ccsdk.sli.core.dblib.DBResourceManager"; + private static final String SVCLOGIC_PROP_VAR = "SDNC_SLI_PROPERTIES"; + private static final String SDNC_CONFIG_DIR = "SDNC_CONFIG_DIR"; + + private static final String INCOMING_PROPERTY_NAME = "org.onap.ccsdk.sli.MessageWriter.writeIncomingRequests"; + private static final String OUTGOING_PROPERTY_NAME = "org.onap.ccsdk.sli.MessageWriter.writeOutgoingRequests"; + + private static final SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS"); + + private static DbLibService dbLibService = null; + + private static boolean incomingEnabled = false; + private static boolean outgoingEnabled = false; + + private static boolean initialized = false; + + @SuppressWarnings({ "rawtypes", "unchecked" }) + private static void init() { + if (initialized) + return; + + initialized = true; + + // Read properties + Properties props = new Properties(); + String propPath = System.getenv(SVCLOGIC_PROP_VAR); + + if (propPath == null) { + String propDir = System.getenv(SDNC_CONFIG_DIR); + if (propDir == null) { + propDir = "/opt/sdnc/data/properties"; + } + propPath = propDir + "/svclogic.properties"; + LOG.warn("Environment variable " + SVCLOGIC_PROP_VAR + " unset - defaulting to " + propPath); + } + + File propFile = new File(propPath); + + if (!propFile.exists()) { + LOG.warn("Property file does not exist: " + propPath); + } + + try { + props.load(new FileInputStream(propFile)); + } catch (Exception e) { + LOG.warn("Error loading property file: " + propPath, e); + } + + incomingEnabled = Boolean.valueOf(props.getProperty(INCOMING_PROPERTY_NAME, "false")); + outgoingEnabled = Boolean.valueOf(props.getProperty(OUTGOING_PROPERTY_NAME, "false")); + + LOG.info(INCOMING_PROPERTY_NAME + ": " + incomingEnabled); + LOG.info(OUTGOING_PROPERTY_NAME + ": " + outgoingEnabled); + } + + public static void saveOutgoingRequest( + String requestId, + String serviceInstanceId, + String targetUrl, + String request) { + try { + init(); + + if (!outgoingEnabled) + return; + + if (serviceInstanceId == null || serviceInstanceId.trim().length() == 0) + serviceInstanceId = "NA"; + + int seqnum = getLastSequenceNumber("OUTGOING_MESSAGE", requestId) + 1; + String now = df.format(new Date()); + + String sql = "INSERT INTO OUTGOING_MESSAGE (\n" + + " request_id, sequence_number, service_instance_id, target_url, request, start_time)\n" + + "VALUES (?, ?, ?, ?, ?, ?)"; + + ArrayList<String> data = new ArrayList<>(); + data.add(requestId); + data.add(String.valueOf(seqnum)); + data.add(serviceInstanceId); + data.add(targetUrl); + data.add(request); + data.add(now); + + dbLibService.writeData(sql, data, null); + + } catch (Exception e) { + LOG.warn("Failed to save outgoing request for request-id: " + requestId, e); + } + } + + public static void saveOutgoingResponse(String requestId, int httpResponseCode, String response) { + try { + init(); + + if (!outgoingEnabled) + return; + + int seqnum = getLastSequenceNumber("OUTGOING_MESSAGE", requestId); + if (seqnum == 0) { + LOG.warn("Failed to save outgoing response for request-id: " + requestId + + ": Request record not found in OUTGOING_MESSAGE"); + return; + } + + String now = df.format(new Date()); + + String sql = "UPDATE OUTGOING_MESSAGE SET http_response_code = ?, response = ?,\n" + + " duration = timestampdiff(MICROSECOND, start_time, ?) / 1000\n" + + "WHERE request_id = ? AND sequence_number = ?"; + + ArrayList<String> data = new ArrayList<>(); + data.add(String.valueOf(httpResponseCode)); + data.add(response); + data.add(now); + data.add(requestId); + data.add(String.valueOf(seqnum)); + + dbLibService.writeData(sql, data, null); + + } catch (Exception e) { + LOG.warn("Failed to save outgoing response for request-id: " + requestId, e); + } + } + + public static void saveIncomingRequest( + String requestId, + String serviceInstanceId, + String requestHost, + String request) { + try { + init(); + + if (!incomingEnabled) + return; + + if (serviceInstanceId == null || serviceInstanceId.trim().length() == 0) + serviceInstanceId = "NA"; + + int seqnum = getLastSequenceNumber("INCOMING_MESSAGE", requestId) + 1; + String now = df.format(new Date()); + + String sql = "INSERT INTO INCOMING_MESSAGE (\n" + + " request_id, sequence_number, service_instance_id, request_host, request, start_time)\n" + + "VALUES (?, ?, ?, ?, ?, ?)"; + + ArrayList<String> data = new ArrayList<>(); + data.add(requestId); + data.add(String.valueOf(seqnum)); + data.add(serviceInstanceId); + data.add(requestHost); + data.add(request); + data.add(now); + + dbLibService.writeData(sql, data, null); + + } catch (Exception e) { + LOG.warn("Failed to save incoming request for request-id: " + requestId, e); + } + } + + public static void saveIncomingResponse(String requestId, int httpResponseCode, String response) { + try { + init(); + + if (!incomingEnabled) + return; + + int seqnum = getLastSequenceNumber("INCOMING_MESSAGE", requestId); + if (seqnum == 0) { + LOG.warn("Failed to save response for request-id: " + requestId + + ": Request record not found in INCOMING_MESSAGE"); + return; + } + + String now = df.format(new Date()); + + String sql = "UPDATE INCOMING_MESSAGE SET http_response_code = ?, response = ?,\n" + + " duration = timestampdiff(MICROSECOND, start_time, ?) / 1000\n" + + "WHERE request_id = ? AND sequence_number = ?"; + + ArrayList<String> data = new ArrayList<>(); + data.add(String.valueOf(httpResponseCode)); + data.add(response); + data.add(now); + data.add(requestId); + data.add(String.valueOf(seqnum)); + + dbLibService.writeData(sql, data, null); + + } catch (Exception e) { + LOG.warn("Failed to save response for request-id: " + requestId, e); + } + } + + public static String getServiceInstanceId(String requestId) throws SQLException { + init(); + + String sql = "SELECT service_instance_id FROM OUTGOING_MESSAGE WHERE request_id = '" + requestId + + "' ORDER BY sequence_number DESC"; + + CachedRowSet rs = null; + try { + rs = dbLibService.getData(sql, null, null); + if (rs.next()) { + return rs.getString("service_instance_id"); + } + } finally { + if (rs != null) { + try { + rs.close(); + } catch (Exception e) { + LOG.warn("Failed to close CachedRowSet", e); + } + } + } + return null; + } + + private static int getLastSequenceNumber(String tableName, String requestId) throws SQLException { + String sql = "SELECT sequence_number FROM " + tableName + " WHERE request_id = '" + requestId + + "' ORDER BY sequence_number DESC"; + + CachedRowSet rs = null; + try { + rs = dbLibService.getData(sql, null, null); + if (rs.next()) { + return rs.getInt("sequence_number"); + } + } finally { + if (rs != null) { + try { + rs.close(); + } catch (Exception e) { + LOG.warn("Failed to close CachedRowSet", e); + } + } + } + return 0; + } +} diff --git a/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/MetricLogger.java b/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/MetricLogger.java new file mode 100755 index 000000000..577b73401 --- /dev/null +++ b/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/MetricLogger.java @@ -0,0 +1,165 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP : CCSDK + * ================================================================================ + * 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.onap.ccsdk.sli.core.sli; + +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.time.ZoneOffset; +import java.time.ZonedDateTime; +import java.time.format.DateTimeFormatter; +import java.time.temporal.ChronoUnit; +import java.util.Date; +import java.util.TimeZone; +import java.util.UUID; + +import org.onap.logging.ref.slf4j.ONAPLogConstants; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.slf4j.MDC; +import org.slf4j.Marker; +import org.slf4j.MarkerFactory; + +/** + * @author dt5972 + * + */ +public class MetricLogger { + + private static final Logger METRIC = LoggerFactory.getLogger("org.onap.ccsdk.sli.core.filters.metric"); + private static final Marker INVOKE_RETURN = MarkerFactory.getMarker("INVOKE-RETURN"); + private static final Marker INVOKE = MarkerFactory.getMarker("INVOKE"); + + private String lastMsg = null; + + public String getRequestID() { + return MDC.get(ONAPLogConstants.MDCs.REQUEST_ID); + } + + public MetricLogger() { + + } + + @Deprecated + public static String asIso8601(Date date) { + TimeZone tz = TimeZone.getTimeZone("UTC"); + DateFormat df = new SimpleDateFormat("yyy-MM-dd'T'HH:mm:ss.SS'+00:00'"); + df.setTimeZone(tz); + return df.format(date); + } + + @Deprecated + public static String asIso8601(long tsInMillis) { + return MetricLogger.asIso8601(new Date(tsInMillis)); + } + + @Deprecated + public void logRequest(String svcInstanceId, String svcName, String partnerName, String targetEntity, + String targetServiceName, String targetElement, String msg) { + logRequest(svcInstanceId, targetEntity, targetServiceName, targetElement, msg); + } + + public void logRequest(String svcInstanceId, String targetEntity, String targetServiceName, String targetElement, + String msg) { + String timeNow = ZonedDateTime.now(ZoneOffset.UTC).format(DateTimeFormatter.ISO_INSTANT); + MDC.put(ONAPLogConstants.MDCs.INVOKE_TIMESTAMP, timeNow); + + // If transaction is initialized by an external client this will already be set by the audit servlet filter + // If the transaction is initialized by CCSDK this code will handle generating a new UUID + String requestId = MDC.get(ONAPLogConstants.MDCs.REQUEST_ID); + if (requestId == null || requestId.isEmpty()) { + MDC.put(ONAPLogConstants.MDCs.REQUEST_ID, UUID.randomUUID().toString()); + } + + String randomInvocationId = UUID.randomUUID().toString(); + MDC.put(ONAPLogConstants.MDCs.INVOCATION_ID, randomInvocationId); + MDC.put(ONAPLogConstants.MDCs.CLIENT_INVOCATION_ID, randomInvocationId); + + if (svcInstanceId != null) { + MDC.put(ONAPLogConstants.MDCs.SERVICE_INSTANCE_ID, svcInstanceId); + } + if (targetEntity != null) { + MDC.put(ONAPLogConstants.MDCs.TARGET_ENTITY, targetEntity); + } + + if (targetServiceName != null) { + MDC.put(ONAPLogConstants.MDCs.TARGET_SERVICE_NAME, targetServiceName); + } + + if (targetElement != null) { + MDC.put(ONAPLogConstants.MDCs.TARGET_ELEMENT, targetElement); + } + this.lastMsg = msg; + //During invoke status will always be INPROGRESS + MDC.put(ONAPLogConstants.MDCs.RESPONSE_STATUS_CODE, ONAPLogConstants.ResponseStatus.INPROGRESS.toString()); + MDC.put(ONAPLogConstants.MDCs.ELAPSED_TIME, "0"); + METRIC.info(INVOKE, "Invoke"); + } + + public void logResponse(String statusCode, String responseCode, String responseDescription) { + if (statusCode != null) { + MDC.put(ONAPLogConstants.MDCs.RESPONSE_STATUS_CODE, statusCode); + } + if (responseCode != null) { + MDC.put(ONAPLogConstants.MDCs.RESPONSE_CODE, responseCode); + } + if (responseDescription != null) { + MDC.put(ONAPLogConstants.MDCs.RESPONSE_DESCRIPTION, formatString(responseDescription)); + } + ZonedDateTime endTime = ZonedDateTime.now(ZoneOffset.UTC); + MDC.put(ONAPLogConstants.MDCs.LOG_TIMESTAMP, endTime.format(DateTimeFormatter.ISO_INSTANT)); + try { + DateTimeFormatter timeFormatter = DateTimeFormatter.ISO_ZONED_DATE_TIME; + ZonedDateTime entryTimestamp = + ZonedDateTime.parse(MDC.get(ONAPLogConstants.MDCs.INVOKE_TIMESTAMP), timeFormatter); + String elapedTime = Long.toString(ChronoUnit.MILLIS.between(entryTimestamp, endTime)); + MDC.put(ONAPLogConstants.MDCs.ELAPSED_TIME,elapedTime); + } catch (Exception e) { + //pass + } + METRIC.info(INVOKE_RETURN, formatString(lastMsg)); + resetContext(); + } + + protected String formatString(String str) { + if (str != null) { + str = str.replaceAll("\\R", ""); // this will strip all new line characters + str = str.replaceAll("\\|", "%7C"); // log records should not contain a pipe, encode the pipe character + str = str.replaceAll("\t", " "); // tabs are not allowed, replace with spaces + str = str.replace(",", "\\,"); // comma must be escaped + } + return str; + } + + public static void resetContext() { + MDC.remove(ONAPLogConstants.MDCs.TARGET_ENTITY); + MDC.remove(ONAPLogConstants.MDCs.TARGET_SERVICE_NAME); + MDC.remove(ONAPLogConstants.MDCs.TARGET_ELEMENT); + MDC.remove(ONAPLogConstants.MDCs.RESPONSE_STATUS_CODE); + MDC.remove(ONAPLogConstants.MDCs.RESPONSE_CODE); + MDC.remove(ONAPLogConstants.MDCs.RESPONSE_DESCRIPTION); + MDC.remove(ONAPLogConstants.MDCs.ELAPSED_TIME); + } + +} diff --git a/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SecurePrinter.java b/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SecurePrinter.java new file mode 100644 index 000000000..e25aed9f8 --- /dev/null +++ b/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SecurePrinter.java @@ -0,0 +1,123 @@ + +package org.onap.ccsdk.sli.core.sli; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.PrintStream; +import java.util.HashMap; +import java.util.Map.Entry; +import java.util.Properties; +import java.util.TreeMap; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class SecurePrinter { + private static final Logger LOG = LoggerFactory.getLogger(SecurePrinter.class); + private static final String DEFAULT_FILTER = "password,pass,pswd"; + private static final String REDACTED = "***REDACTED***"; + private static final String FILTER_PROPERTY = "NODE_STRING_FILTER"; + private static final String SEPERATOR = " = "; + private static final String COMMON_ERROR_MESSAGE = "Failed to print properties"; + + private static String[] filterArray; + + public SecurePrinter() { + String filterProperty = System.getProperty(FILTER_PROPERTY); + if (filterProperty != null && !filterProperty.isEmpty() && filterProperty.contains(",")) { + filterArray = filterProperty.split(","); + } else { + filterArray = DEFAULT_FILTER.split(","); + } + } + + private String filterValue(String key, String value) { + String normalizedKey = key.toLowerCase(); + for (String restrictedKey : filterArray) { + if (normalizedKey.contains(restrictedKey)) { + return REDACTED; + } + } + return value; + } + + public void printAttributes(HashMap<String, String> attributes) { + if (LOG.isDebugEnabled()) { + for (Entry<String, String> attribute : attributes.entrySet()) { + String value = filterValue(attribute.getKey(), attribute.getValue()); + LOG.debug(attribute.getKey() + SEPERATOR + value); + } + } + } + + public void printAttributes(HashMap<String, String> attributes, String subpath) { + if (LOG.isDebugEnabled()) { + for (Entry<String, String> attribute : attributes.entrySet()) { + if (attribute.getKey().startsWith(subpath)) { + String value = filterValue(attribute.getKey(), attribute.getValue()); + LOG.debug(attribute.getKey() + SEPERATOR + value); + } + } + } + } + + public void printProperties(Properties props) { + if (LOG.isDebugEnabled()) { + try { + for (Entry<Object, Object> property : props.entrySet()) { + String keyString = (String) property.getKey(); + String valueString = (String) property.getValue(); + String value = filterValue(keyString, valueString); + LOG.debug(keyString + SEPERATOR + value); + } + } catch (Exception e) { + LOG.error(COMMON_ERROR_MESSAGE, e); + } + } + } + + public void printProperties(Properties props, String subpath) { + if (LOG.isDebugEnabled()) { + try { + for (Entry<Object, Object> property : props.entrySet()) { + String keyString = (String) property.getKey(); + if (keyString.startsWith(subpath)) { + String valueString = (String) property.getValue(); + String value = filterValue(keyString, valueString); + LOG.debug(keyString + SEPERATOR + value); + } + } + } catch (Exception e) { + LOG.error(COMMON_ERROR_MESSAGE, e); + } + } + } + + public void printPropertiesAlphabetically(Properties props) { + if (LOG.isDebugEnabled()) { + TreeMap<String, String> sortedMap = new TreeMap(props); + try { + for (Entry<String, String> entry : sortedMap.entrySet()) { + String value = filterValue(entry.getKey(), entry.getValue()); + LOG.debug(entry.getKey() + SEPERATOR + value); + } + } catch (Exception e) { + LOG.error(COMMON_ERROR_MESSAGE, e); + } + } + } + + public void printAttributesToFile(HashMap<String, String> attributes, String fileName) { + try (FileOutputStream fstr = new FileOutputStream(new File(fileName)); + PrintStream pstr = new PrintStream(fstr, true);) { + pstr.println("#######################################"); + for (Entry<String, String> entry : attributes.entrySet()) { + String value = filterValue(entry.getKey(), entry.getValue()); + pstr.println(entry.getKey() + SEPERATOR + value); + } + } catch (Exception e) { + LOG.error("Cannot write context to file.", e); + } + } + +}
\ No newline at end of file diff --git a/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicAdaptor.java b/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicAdaptor.java new file mode 100644 index 000000000..a76b123ca --- /dev/null +++ b/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicAdaptor.java @@ -0,0 +1,42 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP : CCSDK + * ================================================================================ + * 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.onap.ccsdk.sli.core.sli; + +import java.util.Map; + +public interface SvcLogicAdaptor { + + public enum ConfigStatus { + SUCCESS, + ALREADY_ACTIVE, + NOT_FOUND, + NOT_READY, + FAILURE + } + + public ConfigStatus configure(String key, Map<String,String> parameters, SvcLogicContext ctx); + + public ConfigStatus activate(String key, SvcLogicContext ctx); + + public ConfigStatus deactivate(String key, SvcLogicContext ctx); + +} diff --git a/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicAtom.java b/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicAtom.java new file mode 100644 index 000000000..b9ad19e25 --- /dev/null +++ b/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicAtom.java @@ -0,0 +1,170 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP : CCSDK + * ================================================================================ + * 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.onap.ccsdk.sli.core.sli; + +public class SvcLogicAtom extends SvcLogicExpression { + + public enum AtomType { + NUMBER, + STRING, + IDENTIFIER, + CONTEXT_VAR + + } + + private AtomType atomType; + private String atom; + + + public SvcLogicAtom(String atomType, String atom) + { + this.atomType = AtomType.valueOf(atomType); + this.atom = atom; + + } + + public SvcLogicAtom(String atom) + { + + if (atom == null) + { + this.atomType = null; + this.atom = null; + } + else + { + if (atom.startsWith("$")) + { + this.atomType = AtomType.CONTEXT_VAR; + this.atom = atom.substring(1); + } + else + { + if (Character.isDigit(atom.charAt(0))) + { + this.atomType = AtomType.NUMBER; + this.atom = atom; + } + else if (atom.charAt(0) == '\'') + { + this.atomType = AtomType.STRING; + this.atom = atom.substring(1, atom.length()-1); + } + else + { + this.atomType = AtomType.IDENTIFIER; + this.atom = atom; + + } + + } + } + } + + public AtomType getAtomType() { + return atomType; + } + + public void setAtomType(String newType) + { + atomType = AtomType.valueOf(newType); + } + + public String getAtom() { + return atom; + } + + + + public void setAtomType(AtomType atomType) { + this.atomType = atomType; + } + + public void setAtom(String atom) { + this.atom = atom; + } + + + + public String toString() + { + StringBuffer sbuff = new StringBuffer(); + switch(getAtomType()) + { + case CONTEXT_VAR: + sbuff.append("$"); + case IDENTIFIER: + boolean needDot = false; + for (SvcLogicExpression term: this.getOperands()) + { + if (needDot) + { + sbuff.append("."); + } + sbuff.append(term.toString()); + needDot = true; + } + return sbuff.toString(); + case STRING: + case NUMBER: + default: + return atom; + } + } + + public String asParsedExpr() + { + // simplify debugging output for NUMBER type + if (atomType == AtomType.NUMBER) { + return atom; + } + + StringBuffer sbuff = new StringBuffer(); + + sbuff.append("(atom"); + sbuff.append("<"); + sbuff.append(atomType.toString()); + sbuff.append(">"); + + switch(atomType) + { + case IDENTIFIER: + case CONTEXT_VAR: + for (SvcLogicExpression term : getOperands()) + { + sbuff.append(" "); + sbuff.append(term.asParsedExpr()); + + } + break; + default: + sbuff.append(" "); + sbuff.append(atom); + } + + sbuff.append(")"); + return sbuff.toString(); + } + + + +} diff --git a/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicBinaryExpression.java b/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicBinaryExpression.java new file mode 100644 index 000000000..a990dd950 --- /dev/null +++ b/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicBinaryExpression.java @@ -0,0 +1,151 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP : CCSDK + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights + * reserved. + * ================================================================================ + * Modifications Copyright (C) 2018 IBM. + * ================================================================================ + * 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.onap.ccsdk.sli.core.sli; + +import java.util.LinkedList; +import java.util.List; + +public class SvcLogicBinaryExpression extends SvcLogicExpression { + + + public enum OperatorType { + addOp("+"), + subOp("-"), + multOp("*"), + divOp("/"), + equalOp("=="), + ltOp("<"), + leOp("<="), + gtOp(">"), + geOp(">="), + neOp("!="), + andOp("and"), + orOp("or"); + + private String text; + + private OperatorType(String text) + { + this.text = text; + } + + public String getText() + { + return(text); + } + + public static OperatorType fromString(String text) + { + if (text != null) + { + for (OperatorType t : OperatorType.values()) + { + if (text.equalsIgnoreCase(t.getText())) { + + return(t); + } + } + } + return(null); + } + + public String toString() + { + return(text); + } + } + private List<OperatorType> operators; + + public List<OperatorType> getOperators() { + return operators; + } + + public SvcLogicBinaryExpression() + { + operators = new LinkedList<>(); + } + + public void addOperator(String operator) + { + operators.add(OperatorType.fromString(operator)); + } + + + public String toString() + { + + List<SvcLogicExpression>operands = getOperands(); + StringBuffer sbuff = new StringBuffer(); + + sbuff.append(operands.get(0).toString()); + for (int i = 0 ; i < operators.size(); i++) + { + sbuff.append(" "); + sbuff.append(operators.get(i)); + sbuff.append(" "); + if (i + 1 < operands.size()) { + sbuff.append(operands.get(i + 1).toString()); + } else { + // expression incomplete; operand not bound yet + sbuff.append("?"); + } + } + + return(sbuff.toString()); + + } + + public String asParsedExpr() { + + List<SvcLogicExpression> operands = getOperands(); + + if (operators.isEmpty()) { + return operands.get(0).asParsedExpr(); + } else { + StringBuffer sbuff = new StringBuffer(); + // operators in reverse order for left associativity + for (int i = operators.size() - 1; i >= 0; --i) { + sbuff.append("("); + sbuff.append(operators.get(i).getText()); + sbuff.append(" "); + } + for (int i = 0; i < operators.size() + 1; ++i) { + if (i < operands.size()) { + sbuff.append(operands.get(i).asParsedExpr()); + } else { + // expression incomplete; operand not bound yet + sbuff.append("?"); + } + if (i != 0) { + sbuff.append(")"); + } + if (i < operators.size()) { + sbuff.append(" "); + } + } + return sbuff.toString(); + } + } + +} diff --git a/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicConstants.java b/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicConstants.java new file mode 100644 index 000000000..61bfe7c20 --- /dev/null +++ b/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicConstants.java @@ -0,0 +1,7 @@ +package org.onap.ccsdk.sli.core.sli; + +public class SvcLogicConstants { + public final static String SUCCESS = "success"; + public final static String FAILURE = "failure"; + +} diff --git a/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicContext.java b/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicContext.java new file mode 100644 index 000000000..98cf7e05e --- /dev/null +++ b/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicContext.java @@ -0,0 +1,438 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP : CCSDK + * ================================================================================ + * 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.onap.ccsdk.sli.core.sli; + +import java.util.*; + +import com.google.gson.*; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; +import org.w3c.dom.Text; + + +public class SvcLogicContext { + + private static final Logger LOG = LoggerFactory.getLogger(SvcLogicContext.class); + private final SecurePrinter securePrinter = new SecurePrinter(); + public static final String CTX_NULL_VALUE=""; + private static final String LENGTH="_length"; + + private HashMap<String, String> attributes; + + private String status = SvcLogicConstants.SUCCESS; + + public SvcLogicContext() { + this.attributes = new HashMap<>(); + + } + + public SvcLogicContext(Properties props) { + this.attributes = new HashMap<>(); + + if (props.containsKey(CommonConstants.SERVICE_LOGIC_STATUS)) { + this.status = props.getProperty(CommonConstants.SERVICE_LOGIC_STATUS); + } + + for (Object nameObj : props.keySet()) { + String propName = (String) nameObj; + attributes.put(propName, props.getProperty(propName)); + } + } + + public String getAttribute(String name) { + if (attributes.containsKey(name)) { + return attributes.get(name); + } else { + return null; + } + } + + public void setAttribute(String name, String value) { + if (value == null) { + if (attributes.containsKey(name)) { + attributes.remove(name); + } + } else { + attributes.put(name, value); + } + } + + public Set<String> getAttributeKeySet() { + return attributes.keySet(); + } + + public Boolean isSuccess() { + return status.equals(SvcLogicConstants.SUCCESS); + } + + @Deprecated + public String getStatus() { + return status; + } + + @Deprecated + public void setStatus(String status) { + this.status = status; + } + + public void markFailed() { + this.status = SvcLogicConstants.FAILURE; + } + + public void markSuccess() { + this.status = SvcLogicConstants.SUCCESS; + } + + public Properties toProperties() { + Properties props = new Properties(); + + if (status != null) { + props.setProperty(CommonConstants.SERVICE_LOGIC_STATUS, status); + } + + String attrName; + String attrVal; + for (Map.Entry<String, String> entry : attributes.entrySet()) { + attrName = entry.getKey(); + attrVal = entry.getValue(); + if (attrVal == null) { + LOG.warn("attribute {} value is null - setting to empty string", attrName); + props.setProperty(attrName, ""); + } else { + props.setProperty(attrName, attrVal); + } + } + + return props; + } + + public void mergeDocument(String pfx, Document doc) { + String prefix = ""; + + if (pfx != null) { + prefix = pfx; + } + + Element root = doc.getDocumentElement(); + + mergeElement(prefix, root, null); + } + + public void mergeElement(String pfx, Element element, Map<String, Integer> nodeMap) { + + // In XML, cannot tell the difference between containers and lists. + // So, have to treat each element as both (ugly but necessary). + // We do this by passing a nodeMap to be used to count instance of each tag, + // which will be used to set _length and to set index + + LOG.trace("mergeElement({},{},{})", pfx, element.getTagName(), nodeMap); + + String curTagName = element.getTagName(); + String prefix = curTagName; + + if (pfx != null) { + prefix = pfx + "." + prefix; + } + + int myIdx = 0; + + if (nodeMap != null) { + if (nodeMap.containsKey(curTagName)) { + myIdx = nodeMap.get(curTagName); + } + + nodeMap.put(curTagName, myIdx + 1); + this.setAttribute(prefix + "_length", Integer.toString(myIdx + 1)); + } + + NodeList children = element.getChildNodes(); + + int numChildren = children.getLength(); + + Map<String, Integer> childMap = new HashMap<>(); + Map<String, Integer> idxChildMap = new HashMap<>(); + + for (int i = 0; i < numChildren; i++) { + Node curNode = children.item(i); + + if (curNode instanceof Text) { + Text curText = (Text) curNode; + String curTextValue = curText.getTextContent(); + LOG.trace("Setting ctx variable {} = {}", prefix, curTextValue); + this.setAttribute(prefix, curText.getTextContent()); + + + } else if (curNode instanceof Element) { + mergeElement(prefix, (Element) curNode, childMap); + if (nodeMap != null) { + + mergeElement(prefix + "[" + myIdx + "]", (Element) curNode, idxChildMap); + + } + } + } + + } + + public void mergeJson(String pfx, String jsonString) { + + JsonParser jp = new JsonParser(); + JsonElement element = jp.parse(jsonString); + String root = ""; + if ((pfx != null) && (pfx.length() > 0)) { + root = pfx + "."; + } + if (element.isJsonObject()) { + writeJsonObject(element.getAsJsonObject(), root); + } else if (element.isJsonArray()) { + handleJsonArray("", element.getAsJsonArray(), root); + } + } + + + protected void writeJsonObject(JsonObject obj, String root) { + for (Map.Entry<String, JsonElement> entry : obj.entrySet()) { + String key = entry.getKey(); + if (entry.getValue().isJsonObject()) { + writeJsonObject(entry.getValue().getAsJsonObject(), root + key + "."); + } else if (entry.getValue().isJsonArray()) { + JsonArray array = entry.getValue().getAsJsonArray(); + handleJsonArray(key, array, root); + } else { + //Handles when a JSON obj is nested within a JSON obj + if(!root.endsWith(".")){ + root = root + "."; + } + if(entry.getValue().isJsonNull()) { + this.setAttribute(root + key, CTX_NULL_VALUE); + }else { + this.setAttribute(root + key, entry.getValue().getAsString()); + } + } + } + } + + protected void handleJsonArray(String key, JsonArray array, String root) { + this.setAttribute(root + key + LENGTH, String.valueOf(array.size())); + Integer arrayIdx = 0; + for (JsonElement element : array) { + String prefix = root + key + "[" + arrayIdx + "]"; + + if (element.isJsonArray()) { + handleJsonArray(key, element.getAsJsonArray(), prefix); + } else if (element.isJsonObject()) { + writeJsonObject(element.getAsJsonObject(), prefix + "."); + } else if (element.isJsonNull()) { + this.setAttribute(prefix, CTX_NULL_VALUE); + } else if (element.isJsonPrimitive()) { + this.setAttribute(prefix, element.getAsString()); + } + arrayIdx++; + } + } + + + public String resolve(String ctxVarName) { + + if (ctxVarName.indexOf('[') == -1) { + // Ctx variable contains no arrays + return getAttribute(ctxVarName); + } + + // Resolve any array references + StringBuilder sbuff = new StringBuilder(); + String[] ctxVarParts = ctxVarName.split("\\["); + sbuff.append(ctxVarParts[0]); + for (int i = 1; i < ctxVarParts.length; i++) { + if (ctxVarParts[i].startsWith("$")) { + int endBracketLoc = ctxVarParts[i].indexOf(']'); + if (endBracketLoc == -1) { + // Missing end bracket ... give up parsing + LOG.warn("Variable reference {} seems to be missing a ']'", ctxVarName); + return getAttribute(ctxVarName); + } + + String idxVarName = ctxVarParts[i].substring(1, endBracketLoc); + String remainder = ctxVarParts[i].substring(endBracketLoc); + + sbuff.append("["); + sbuff.append(this.getAttribute(idxVarName)); + sbuff.append(remainder); + + } else { + // Index is not a variable reference + sbuff.append("["); + sbuff.append(ctxVarParts[i]); + } + } + + return getAttribute(sbuff.toString()); + } + + public String toJsonString(String pfx) { + JsonParser jp = new JsonParser(); + + String jsonString = this.toJsonString(); + JsonObject jsonRoot = (JsonObject) jp.parse(jsonString); + JsonObject targetJson = jsonRoot.getAsJsonObject(pfx); + if (targetJson == null) { + return(""); + } else { + return(targetJson.toString()); + } + } + + public String toJsonString() { + JsonObject root = new JsonObject(); + JsonElement lastJsonObject = root; + JsonElement currJsonLeaf = root; + + String attrName = null; + String attrVal = null; + + // Sort properties so that arrays will be reconstructed in proper order + TreeMap<String, String> sortedAttributes = new TreeMap<>(); + sortedAttributes.putAll(attributes); + + // Loop through properties, sorted by key + for (Map.Entry<String, String> entry : sortedAttributes.entrySet()) { + attrName = entry.getKey(); + attrVal = entry.getValue(); + + currJsonLeaf = root; + String curFieldName = null; + JsonArray curArray = null; + lastJsonObject = null; + boolean addNeeded = false; + + // Split property names by period and iterate through parts + for (String attrNamePart : attrName.split("\\.")) { + + // Add last object found to JSON tree. Need to handle + // this way because last element found (leaf) needs to be + // assigned the property value. + if (lastJsonObject != null) { + if (addNeeded) { + if (currJsonLeaf.isJsonArray()) { + ((JsonArray) currJsonLeaf).add(lastJsonObject); + } else { + ((JsonObject) currJsonLeaf).add(curFieldName, lastJsonObject); + } + } + currJsonLeaf = (JsonObject) lastJsonObject; + } + addNeeded = false; + // See if current level should be a JsonArray or JsonObject based on + // whether name part contains square brackets. + if (!attrNamePart.contains("[")) { + // This level should be inserted as a JsonObject + curFieldName = attrNamePart; + lastJsonObject = ((JsonObject) currJsonLeaf).get(curFieldName); + if (lastJsonObject == null) { + lastJsonObject = new JsonObject(); + addNeeded = true; + } else if (!lastJsonObject.isJsonObject()) { + LOG.error("Unexpected condition - expecting to find JsonObject, but found " + lastJsonObject.getClass().getName()); + lastJsonObject = new JsonObject(); + addNeeded = true; + } + } else { + // This level should be inserted as a JsonArray. + + String[] curFieldNameParts = attrNamePart.split("[\\[\\]]"); + curFieldName = curFieldNameParts[0]; + int curIndex = Integer.parseInt(curFieldNameParts[1]); + + + curArray = ((JsonObject) currJsonLeaf).getAsJsonArray(curFieldName); + + if (curArray == null) { + // This is the first time we see this array. + // Create a new JsonArray and add it to current + // leaf + curArray = new JsonArray(); + ((JsonObject) currJsonLeaf).add(curFieldName, curArray); + } + + // Current leaf should point to the JsonArray for this level. + // lastJsonObject should point to the array item entry to append + // the next level to - which is a new one if the index value + // isn't the end of the current array. + currJsonLeaf = curArray; + if (curArray.size() == curIndex + 1) { + lastJsonObject = curArray.get(curArray.size() - 1); + } else { + lastJsonObject = new JsonObject(); + addNeeded = true; + } + } + } + + // Done parsing property name. Add the value of this + // property to the current json leaf, either as a property + // or as a string (if the current leaf is a JsonArray) + + if (!curFieldName.endsWith("_length")) { + if (currJsonLeaf.isJsonArray()) { + if ("true".equals(attrVal) || "false".equals(attrVal)) { + ((JsonArray) currJsonLeaf).add(Boolean.valueOf(attrVal)); + } else if ("null".equals(attrVal)) { + ((JsonArray) currJsonLeaf).add(new JsonNull()); + } else { + ((JsonArray) currJsonLeaf).add(attrVal); + } + } else { + if (("true".equals(attrVal) || "false".equals(attrVal))) { + ((JsonObject) currJsonLeaf).addProperty(curFieldName, Boolean.valueOf(attrVal)); + } else if ("null".equals(attrVal)){ + + ((JsonObject) currJsonLeaf).add(curFieldName, new JsonNull()); + } else { + ((JsonObject) currJsonLeaf).addProperty(curFieldName, attrVal); + } + } + } + } + + return (root.toString()); + } + + public void printProperties(Properties props) { + securePrinter.printProperties(props); + } + + public void printAttributes() { + securePrinter.printAttributes(attributes); + } + + public void printProperties(Properties props, String subpath) { + securePrinter.printProperties(props, subpath); + } + + public void printAttributes(String subpath) { + securePrinter.printAttributes(attributes, subpath); + } +} diff --git a/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicCrawler.java b/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicCrawler.java new file mode 100644 index 000000000..c6fd8b6a2 --- /dev/null +++ b/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicCrawler.java @@ -0,0 +1,92 @@ +/*- + * ============LICENSE_START======================================================= + * openECOMP : SDN-C + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights + * reserved. + * ================================================================================ + * Modifications Copyright (C) 2018 IBM. + * ================================================================================ + * 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.onap.ccsdk.sli.core.sli; + +import static java.nio.file.FileVisitResult.CONTINUE; + +import java.io.IOException; +import java.nio.file.FileVisitResult; +import java.nio.file.Path; +import java.nio.file.SimpleFileVisitor; +import java.nio.file.attribute.BasicFileAttributes; +import java.util.ArrayList; +import java.util.List; + +public class SvcLogicCrawler extends SimpleFileVisitor<Path> { + + private List<Path> xmlGraphPathList; + private List<Path> activationFilePathList; + + public SvcLogicCrawler() { + xmlGraphPathList = new ArrayList<>(); + activationFilePathList = new ArrayList<>(); + } + + @Override + public FileVisitResult visitFile(Path file, BasicFileAttributes attr) { + if (attr.isRegularFile()) { + String fileName = file.getFileName().toString(); + if (!file.toString().contains(".git") && !fileName.equals("pom.xml") && !fileName.equals("assemble_zip.xml") && !fileName.equals("assemble_zip_less_config.xml") && !fileName.equals("descriptor.xml")) { + if (fileName.endsWith(".xml")) { + xmlGraphPathList.add(file); + } + else if (fileName.endsWith(".versions")) { + activationFilePathList.add(file); + } + } + } + return CONTINUE; + } + + @Override + public FileVisitResult postVisitDirectory(Path dir, IOException exc) { + return CONTINUE; + } + + @Override + public FileVisitResult visitFileFailed(Path file, IOException exc) { + System.err.println("Couldn't visitFile"); + System.err.println(exc.getMessage()); + return CONTINUE; + } + + @Override + public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException { + String[] skipDirectories = {".git"}; + for (String str : skipDirectories) { + if (dir.endsWith(str)) { + return FileVisitResult.SKIP_SUBTREE; + } + } + return CONTINUE; + } + + public List<Path> getGraphPaths() { + return this.xmlGraphPathList; + } + + public List<Path> getActivationPaths() { + return this.activationFilePathList; + } +} diff --git a/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicDblibStore.java b/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicDblibStore.java new file mode 100644 index 000000000..dc3a560eb --- /dev/null +++ b/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicDblibStore.java @@ -0,0 +1,332 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP : CCSDK + * ================================================================================ + * 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.onap.ccsdk.sli.core.sli; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.sql.Blob; +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.Properties; +import javax.sql.rowset.CachedRowSet; +import org.onap.ccsdk.sli.core.dblib.DbLibService; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class SvcLogicDblibStore implements SvcLogicStore { + private static final Logger LOG = LoggerFactory.getLogger(SvcLogicDblibStore.class); + private DbLibService dbSvc; + + public SvcLogicDblibStore(DbLibService dbsvc) { + this.dbSvc = dbsvc; + } + + public Connection getConnection() throws SQLException { + return(dbSvc.getConnection()); + } + + @Override + public void init(Properties props) throws ConfigurationException { + if(dbSvc == null) { + LOG.error("SvcLogic cannot acquire DBLIB_SERVICE"); + return; + } + try { + dbSvc.getData("select 1 from DUAL", new ArrayList<String>(), null); + LOG.debug("SQL test was successful"); + } catch (SQLException e) { + LOG.error("Failed SQL test", e); + } + } + + @Override + public boolean hasGraph(String module, String rpc, String version, + String mode) throws SvcLogicException { + boolean retval = false; + CachedRowSet results = null; + String hasVersionGraphSql = "SELECT count(*) FROM SVC_LOGIC" + + " WHERE module = ? AND rpc = ? AND mode = ? AND version = ?"; + + String hasActiveGraphSql = "SELECT count(*) FROM SVC_LOGIC" + + " WHERE module = ? AND rpc = ? AND mode = ? AND active = 'Y'"; + + ArrayList<String> args = new ArrayList<>(); + args.add(module); + args.add(rpc); + args.add(mode); + + try { + + if (version == null) { + results = dbSvc.getData(hasActiveGraphSql, args, null); + } else { + args.add(version); + results = dbSvc.getData(hasVersionGraphSql, args, null); + } + + if (results.next()) { + int cnt = results.getInt(1); + + if (cnt > 0) { + retval = true; + } + } + } catch (Exception e) { + throw new ConfigurationException("SQL query failed", e); + } finally { + if (results != null) { + try { + results.close(); + } catch (SQLException x) { + LOG.error("Failed to close CachedRowSet", x); + } + } + + } + + return retval; + } + + public SvcLogicGraph fetch(String module, String rpc, String version, + String mode) throws SvcLogicException { + + PreparedStatement fetchGraphStmt = null; + Connection dbConn = null; + SvcLogicGraph retval = null; + ResultSet results = null; + + String fetchVersionGraphSql = "SELECT graph FROM SVC_LOGIC" + + " WHERE module = ? AND rpc = ? AND mode = ? AND version = ?"; + + String fetchActiveGraphSql = "SELECT graph FROM SVC_LOGIC" + + " WHERE module = ? AND rpc = ? AND mode = ? AND active = 'Y'"; + + + try { + dbConn = dbSvc.getConnection(); + + if (version == null) { + fetchGraphStmt = dbConn.prepareStatement(fetchActiveGraphSql); + } else { + fetchGraphStmt = dbConn.prepareStatement(fetchVersionGraphSql); + } + + fetchGraphStmt.setString(1, module); + fetchGraphStmt.setString(2, rpc); + fetchGraphStmt.setString(3, mode); + if (version != null) { + fetchGraphStmt.setString(4,version); + } + + results = fetchGraphStmt.executeQuery(); + + if (results.next()) { + Blob graphBlob = results.getBlob("graph"); + + ObjectInputStream gStream = new ObjectInputStream(graphBlob.getBinaryStream()); + + Object graphObj = gStream.readObject(); + gStream.close(); + + if (graphObj instanceof SvcLogicGraph) { + retval = (SvcLogicGraph) graphObj; + } else { + throw new ConfigurationException("invalid type for graph (" + + graphObj.getClass().getName()); + + } + + } else { + return null; + } + } catch (Exception e) { + LOG.error("Graph processing failed", e); + throw new ConfigurationException("Graph processing failed: " + e.getMessage()); + } finally { + try { + if (fetchGraphStmt != null) { + fetchGraphStmt.close(); + } + } catch (SQLException e) { + LOG.error("PreparedStatement close error", e); + } + if (results != null) { + try { + results.close(); + } catch (SQLException x) { + LOG.error("ResultSet close error", x); + } + } + try { + if (dbConn != null && !dbConn.isClosed()) { + dbConn.close(); + } + } catch (Exception exc) { + LOG.error("dbConn close error", exc); + } finally { + dbConn = null; + } + + } + + return retval; + } + + public void store(SvcLogicGraph graph) throws SvcLogicException { + + + + String storeGraphSql = "INSERT INTO SVC_LOGIC (module, rpc, version, mode, active, graph, md5sum)" + + " VALUES(?, ?, ?, ?, ?, ?, ?)"; + + if (graph == null) { + throw new SvcLogicException("graph cannot be null"); + } + + byte[] graphBytes = null; + + try (ByteArrayOutputStream byteStr = new ByteArrayOutputStream(); + ObjectOutputStream goutStr = new ObjectOutputStream(byteStr)) { + + goutStr.writeObject(graph); + + graphBytes = byteStr.toByteArray(); + + } catch (Exception e) { + throw new SvcLogicException("could not serialize graph", e); + } + + // If object already stored in database, delete it + if (hasGraph(graph.getModule(), graph.getRpc(), graph.getVersion(), + graph.getMode())) { + delete(graph.getModule(), graph.getRpc(), graph.getVersion(), + graph.getMode()); + } + + Connection dbConn = null; + PreparedStatement storeGraphStmt = null; + try { + dbConn = dbSvc.getConnection(); + boolean oldAutoCommit = dbConn.getAutoCommit(); + dbConn.setAutoCommit(false); + storeGraphStmt = dbConn.prepareStatement(storeGraphSql); + storeGraphStmt.setString(1, graph.getModule()); + storeGraphStmt.setString(2, graph.getRpc()); + storeGraphStmt.setString(3, graph.getVersion()); + storeGraphStmt.setString(4, graph.getMode()); + storeGraphStmt.setString(5, "N"); + storeGraphStmt.setBlob(6, new ByteArrayInputStream(graphBytes)); + storeGraphStmt.setString(7, graph.getMd5sum()); + storeGraphStmt.executeUpdate(); + dbConn.commit(); + dbConn.setAutoCommit(oldAutoCommit); + } catch (Exception e) { + throw new SvcLogicException("Could not write object to database", e); + } finally { + try { + if (storeGraphStmt != null) { + storeGraphStmt.close(); + } + } catch (SQLException e) { + LOG.error("PreparedStatement close error", e); + } + try { + if (dbConn != null && !dbConn.isClosed()) { + dbConn.close(); + } + } catch (Exception exc) { + LOG.error("dbConn close error", exc); + } finally { + dbConn = null; + } + + } + } + + public void delete(String module, String rpc, String version, String mode) + throws SvcLogicException { + String deleteGraphSql = "DELETE FROM SVC_LOGIC WHERE module = ? AND rpc = ? AND version = ? AND mode = ?"; + + ArrayList<String> args = new ArrayList<>(); + + args.add(module); + args.add(rpc); + args.add(version); + args.add(mode); + + try { + dbSvc.writeData(deleteGraphSql, args, null); + } catch (Exception e) { + throw new SvcLogicException("Could not delete object from database", e); + } + } + + public void activate(SvcLogicGraph graph) throws SvcLogicException { + String deactivateSql = "UPDATE SVC_LOGIC SET active = 'N' WHERE module = ? AND rpc = ? AND mode = ?"; + String activateSql = "UPDATE SVC_LOGIC SET active = 'Y' WHERE module = ? AND rpc = ? AND mode = ? AND version = ?"; + + ArrayList<String> args = new ArrayList<>(); + + args.add(graph.getModule()); + args.add(graph.getRpc()); + args.add(graph.getMode()); + + try { + dbSvc.writeData(deactivateSql, args, null); + args.add(graph.getVersion()); + dbSvc.writeData(activateSql, args, null); + } catch (Exception e) { + throw new SvcLogicException("Could not activate graph", e); + } + } + + @Override + public void activate(String module, String rpc, String version, String mode) throws SvcLogicException { + + String deactivateSql = "UPDATE SVC_LOGIC SET active = 'N' WHERE module = ? AND rpc = ? AND mode = ?"; + + String activateSql = "UPDATE SVC_LOGIC SET active = 'Y' WHERE module = ? AND rpc = ? AND mode = ? AND version = ?"; + + ArrayList<String> args = new ArrayList<>(); + + args.add(module); + args.add(rpc); + args.add(mode); + + try { + + dbSvc.writeData(deactivateSql, args, null); + + args.add(version); + dbSvc.writeData(activateSql, args, null); + + } catch (Exception e) { + throw new SvcLogicException("Could not activate graph", e); + } + } + +} diff --git a/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicException.java b/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicException.java new file mode 100644 index 000000000..c03ef9787 --- /dev/null +++ b/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicException.java @@ -0,0 +1,46 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP : CCSDK + * ================================================================================ + * 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.onap.ccsdk.sli.core.sli; + +public class SvcLogicException extends Exception { + + /** + * + */ + private static final long serialVersionUID = 1L; + + public SvcLogicException() + { + super(); + } + + public SvcLogicException(String message) + { + super(message); + } + + public SvcLogicException(String message, Throwable t) + { + super(message, t); + } + +} diff --git a/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicExprListener.java b/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicExprListener.java new file mode 100644 index 000000000..a1871951f --- /dev/null +++ b/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicExprListener.java @@ -0,0 +1,271 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP : CCSDK + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights + * reserved. + * ================================================================================ + * Modifications Copyright (C) 2018 IBM. + * ================================================================================ + * 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.onap.ccsdk.sli.core.sli; + +import java.util.LinkedList; +import java.util.List; + +import org.antlr.v4.runtime.tree.TerminalNode; +import org.onap.ccsdk.sli.core.sli.ExprGrammarParser.AddExprContext; +import org.onap.ccsdk.sli.core.sli.ExprGrammarParser.AtomContext; +import org.onap.ccsdk.sli.core.sli.ExprGrammarParser.CompareExprContext; +import org.onap.ccsdk.sli.core.sli.ExprGrammarParser.ConstantContext; +import org.onap.ccsdk.sli.core.sli.ExprGrammarParser.ExprContext; +import org.onap.ccsdk.sli.core.sli.ExprGrammarParser.FuncExprContext; +import org.onap.ccsdk.sli.core.sli.ExprGrammarParser.MultExprContext; +import org.onap.ccsdk.sli.core.sli.ExprGrammarParser.ParenExprContext; +import org.onap.ccsdk.sli.core.sli.ExprGrammarParser.RelExprContext; +import org.onap.ccsdk.sli.core.sli.ExprGrammarParser.VariableContext; +import org.onap.ccsdk.sli.core.sli.ExprGrammarParser.VariableLeadContext; +import org.onap.ccsdk.sli.core.sli.ExprGrammarParser.VariableTermContext; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class SvcLogicExprListener extends ExprGrammarBaseListener +{ + + + + + private static final Logger LOG = LoggerFactory + .getLogger(SvcLogicExprListener.class); + + private SvcLogicExpression curExpr; + //private SvcLogicExpression topExpr; + private LinkedList<SvcLogicExpression> exprStack; + + public SvcLogicExprListener() + { + exprStack = new LinkedList<>(); + } + + public SvcLogicExpression getParsedExpr() + { + return(curExpr); + } + + private void pushOperand(SvcLogicExpression operand) + { + if (curExpr == null) + { + curExpr = operand; + } + else + { + curExpr.addOperand(operand); + } + } + + private void pushExpr(SvcLogicExpression expr) + { + if (curExpr != null) + { + exprStack.push(curExpr); + } + curExpr = expr; + } + + private void popExpr() + { + if (exprStack.isEmpty()) + { + //topExpr = curExpr; + } + else + { + SvcLogicExpression lastExpr = curExpr; + curExpr = exprStack.pop(); + curExpr.addOperand(lastExpr); + } + + } + + @Override + public void enterAtom(AtomContext ctx) { + String atomText = ctx.getText(); + SvcLogicAtom newAtom = new SvcLogicAtom(atomText); + pushExpr(newAtom); + } + + + @Override + public void enterMultExpr(MultExprContext ctx) { + SvcLogicBinaryExpression curBinExpr = new SvcLogicBinaryExpression(); + pushExpr(curBinExpr); + + List<TerminalNode> opList = ctx.MULTOP(); + + for (TerminalNode nd : opList) + { + curBinExpr.addOperator(nd.getText()); + } + + } + + @Override + public void exitMultExpr(MultExprContext ctx) { + popExpr(); + } + + @Override + public void exitAtom(AtomContext ctx) { + popExpr(); + } + + @Override + public void enterAddExpr(AddExprContext ctx) { + List<TerminalNode> opList = ctx.ADDOP(); + + + SvcLogicBinaryExpression curBinExpr = new SvcLogicBinaryExpression(); + pushExpr(curBinExpr); + + + for (TerminalNode nd : opList) + { + curBinExpr.addOperator(nd.getText()); + } + + } + + @Override + public void exitAddExpr(AddExprContext ctx) { + popExpr(); + } + + @Override + public void enterFuncExpr(FuncExprContext ctx) { + LOG.trace("enterFuncExpr: text = "+ctx.getText()); + LOG.trace("enterFuncExpr - IDENTIFIER : "+ctx.IDENTIFIER().getText()); + + for (ExprContext expr: ctx.expr()) + { + LOG.trace("enterFuncExpr - expr = "+expr.getText()); + } + + + pushExpr(new SvcLogicFunctionCall(ctx.IDENTIFIER().getText())); + } + + @Override + public void exitFuncExpr(FuncExprContext ctx) { + popExpr(); + } + + @Override + public void enterParenExpr(ParenExprContext ctx) { + LOG.trace("enterParenExpr: text = "+ctx.getText()); + LOG.trace("enterParenExpr: expr = "+ctx.expr().getText()); + } + + @Override + public void exitParenExpr(ParenExprContext ctx) { + LOG.trace("exitParenExpr: text = "+ctx.getText()); + } + + @Override + public void enterRelExpr(RelExprContext ctx) { + List<TerminalNode> opList = ctx.RELOP(); + + + SvcLogicBinaryExpression curBinExpr = new SvcLogicBinaryExpression(); + pushExpr(curBinExpr); + + + for (TerminalNode nd : opList) + { + curBinExpr.addOperator(nd.getText()); + } + + } + + @Override + public void exitRelExpr(RelExprContext ctx) { + popExpr(); + } + + @Override + public void enterCompareExpr(CompareExprContext ctx) { + + TerminalNode nd = ctx.COMPAREOP(); + + SvcLogicBinaryExpression curBinExpr = new SvcLogicBinaryExpression(); + pushExpr(curBinExpr); + + curBinExpr.addOperator(nd.getText()); + + } + + @Override + public void exitCompareExpr(CompareExprContext ctx) { + + popExpr(); + } + + + + @Override + public void enterConstant(ConstantContext ctx) { + } + + @Override + public void exitConstant(ConstantContext ctx) { + } + + + @Override + public void enterVariable(VariableContext ctx) { + } + + @Override + public void exitVariable(VariableContext ctx) { + } + + + @Override + public void enterVariableLead(VariableLeadContext ctx) { + } + + @Override + public void exitVariableLead(VariableLeadContext ctx) { + } + + @Override + public void enterVariableTerm(VariableTermContext ctx) { + String name = ctx.getText(); + + int subscrStart = name.indexOf("["); + if (subscrStart > -1) + { + name = name.substring(0, subscrStart); + } + SvcLogicVariableTerm vterm = new SvcLogicVariableTerm(name); + pushExpr(vterm); + } + + @Override + public void exitVariableTerm(VariableTermContext ctx) { + popExpr(); + } +} diff --git a/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicExprParserErrorListener.java b/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicExprParserErrorListener.java new file mode 100644 index 000000000..03f2a8b0b --- /dev/null +++ b/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicExprParserErrorListener.java @@ -0,0 +1,44 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP : CCSDK + * ================================================================================ + * 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.onap.ccsdk.sli.core.sli; + +import org.antlr.v4.runtime.BaseErrorListener; +import org.antlr.v4.runtime.RecognitionException; +import org.antlr.v4.runtime.Recognizer; +import org.antlr.v4.runtime.misc.ParseCancellationException; + +public class SvcLogicExprParserErrorListener extends BaseErrorListener { + + private static final SvcLogicExprParserErrorListener instance = new SvcLogicExprParserErrorListener(); + + public static SvcLogicExprParserErrorListener getInstance() { + return(instance); + } + + @Override + public void syntaxError(Recognizer<?, ?> recognizer, Object offendingSymbol, int line, int charPositionInLine, + String msg, RecognitionException e) throws ParseCancellationException { + throw new ParseCancellationException(msg); + } + + +} diff --git a/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicExpression.java b/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicExpression.java new file mode 100644 index 000000000..81aeb6c37 --- /dev/null +++ b/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicExpression.java @@ -0,0 +1,52 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP : CCSDK + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights + * reserved. + * ================================================================================ + * Modifications Copyright (C) 2018 IBM. + * ================================================================================ + * 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.onap.ccsdk.sli.core.sli; + +import java.io.Serializable; +import java.util.LinkedList; +import java.util.List; + + +public abstract class SvcLogicExpression implements Serializable { + + private List<SvcLogicExpression> operands = new LinkedList<>(); + + + public void addOperand(SvcLogicExpression expr) + { + operands.add(expr); + } + + public List<SvcLogicExpression> getOperands() { + return operands; + } + + public int numOperands() + { + return(operands.size()); + } + + public abstract String asParsedExpr(); + +} diff --git a/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicExpressionFactory.java b/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicExpressionFactory.java new file mode 100644 index 000000000..727c84b19 --- /dev/null +++ b/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicExpressionFactory.java @@ -0,0 +1,75 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP : CCSDK + * ================================================================================ + * 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.onap.ccsdk.sli.core.sli; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import org.antlr.v4.runtime.ANTLRInputStream; +import org.antlr.v4.runtime.CharStream; +import org.antlr.v4.runtime.CommonTokenStream; +import org.antlr.v4.runtime.tree.ParseTreeWalker; +import org.onap.ccsdk.sli.core.sli.ExprGrammarParser.ExprContext; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + + +public class SvcLogicExpressionFactory { + + private static final Logger LOG = LoggerFactory + .getLogger(SvcLogicExpressionFactory.class); + + + public static SvcLogicExpression parse(String exprStr) throws IOException + { + InputStream exprStream = new ByteArrayInputStream(exprStr.getBytes()); + CharStream input = new ANTLRInputStream(exprStream); + ExprGrammarLexer lexer = new ExprGrammarLexer(input); + CommonTokenStream tokens = new CommonTokenStream(lexer); + ExprGrammarParser parser = new ExprGrammarParser(tokens); + + lexer.removeErrorListeners(); + lexer.addErrorListener(SvcLogicExprParserErrorListener.getInstance()); + parser.removeErrorListeners(); + parser.addErrorListener(SvcLogicExprParserErrorListener.getInstance()); + + ExprContext expression = null; + + try { + expression = parser.expr(); + } catch (Exception e) { + String errorMsg = e.getMessage(); + + LOG.error(errorMsg); + throw new SvcLogicParserException(errorMsg); + } + + + ParseTreeWalker walker = new ParseTreeWalker(); + SvcLogicExprListener listener = new SvcLogicExprListener(); + walker.walk(listener, expression); + + + return(listener.getParsedExpr()); + } + +} diff --git a/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicFunctionCall.java b/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicFunctionCall.java new file mode 100644 index 000000000..8289f16da --- /dev/null +++ b/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicFunctionCall.java @@ -0,0 +1,80 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP : CCSDK + * ================================================================================ + * 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.onap.ccsdk.sli.core.sli; + +public class SvcLogicFunctionCall extends SvcLogicExpression { + + private String functionName; + + public SvcLogicFunctionCall(String functionName) + { + this.functionName = functionName; + } + + public String getFunctionName() { + return functionName; + } + + public void setFunctionName(String functionName) { + this.functionName = functionName; + } + + public String toString() + { + StringBuffer sbuff = new StringBuffer(); + + sbuff.append(functionName); + sbuff.append("("); + boolean needComma = false; + for (SvcLogicExpression operand: getOperands()) + { + if (needComma) + { + sbuff.append(","); + } + else + { + needComma = true; + } + sbuff.append(operand.toString()); + + } + sbuff.append(")"); + return(sbuff.toString()); + } + + public String asParsedExpr() + { + StringBuffer sbuff = new StringBuffer(); + + sbuff.append("("); + sbuff.append(functionName); + for (SvcLogicExpression operand: getOperands()) + { + sbuff.append(" "); + sbuff.append(operand.asParsedExpr()); + } + sbuff.append(")"); + return(sbuff.toString()); + } + +} diff --git a/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicGraph.java b/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicGraph.java new file mode 100644 index 000000000..97f2bd7ab --- /dev/null +++ b/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicGraph.java @@ -0,0 +1,199 @@ +/*- +x * ============LICENSE_START======================================================= + * ONAP : CCSDK + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights + * reserved. + * ================================================================================ + * Modifications 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.onap.ccsdk.sli.core.sli; + +import java.io.PrintStream; +import java.io.Serializable; +import java.util.HashMap; +import java.util.Map; + +public class SvcLogicGraph implements Serializable { + + /** + * + */ + private static final long serialVersionUID = 1L; + + private String module = null; + private String rpc = null; + private String mode = null; + private String version = null; + + private String md5sum = null; + + private Map<String, Serializable> attributes; + private Map<String, SvcLogicNode> namedNodes; + private SvcLogicNode rootNode; + + public SvcLogicGraph() + { + attributes = new HashMap<>(); + namedNodes = new HashMap<>(); + rootNode = null; + } + + public String getMd5sum() { + return md5sum; + } + + + public void setMd5sum(String md5sum) { + this.md5sum = md5sum; + } + + + + public String getModule() { + return module; + } + + + public void setModule(String module) { + this.module = module; + } + + + public String getRpc() { + return rpc; + } + + + public void setRpc(String rpc) { + this.rpc = rpc; + } + + + + + public String getMode() { + return mode; + } + + + public void setMode(String mode) { + this.mode = mode; + } + + + public String getVersion() { + return version; + } + + + public void setVersion(String version) { + this.version = version; + } + + + public void setRootNode(SvcLogicNode rootNode) + { + this.rootNode = rootNode; + } + + public SvcLogicNode getRootNode() + { + return(rootNode); + } + + public Serializable getAttribute(String name) + { + if (attributes.containsKey(name)) + { + return(attributes.get(name)); + } + else + { + return(null); + } + + } + + public void setAttribute(String name, Serializable value) throws DuplicateValueException + { + if (attributes.containsKey(name)) + { + throw new DuplicateValueException("Duplicate attribute "+name); + } + + attributes.put(name, value); + } + + public SvcLogicNode getNamedNode(String nodeName) + { + if (namedNodes.containsKey(nodeName)) + { + return(namedNodes.get(nodeName)); + } + else + { + return(null); + } + } + + public void setNamedNode(String nodeName, SvcLogicNode node) throws DuplicateValueException + { + if (namedNodes.containsKey(nodeName)) + { + throw new DuplicateValueException("Duplicate node name "+nodeName); + } + + namedNodes.put(nodeName, node); + } + + + + public void printAsGv(PrintStream pstr) + { + pstr.println("digraph g {"); + pstr.println("START [label=\"START\\n"+module+":"+rpc+"\"];"); + + if (rootNode != null) + { + pstr.println("START -> node"+rootNode.getNodeId()+";"); + rootNode.setVisited(false, true); + rootNode.printAsGv(pstr); + } + pstr.println("}"); + } + + public void printAsXml(PrintStream pstr) + { + pstr.println("<service-logic module='"+getModule()+"' version='"+getVersion()+"'>"); + pstr.println(" <method rpc='"+getRpc()+"' mode='"+getMode()+"'>"); + if (rootNode != null) + { + rootNode.setVisited(false, true); + rootNode.printAsXml(pstr, 2); + } + pstr.println(" </method>"); + pstr.println("</service-logic>"); + } + + @Override + public String toString() { + return "SvcLogicGraph [module=" + module + ", rpc=" + rpc + ", mode=" + mode + ", version=" + version + ", md5sum=" + md5sum + "]"; + } + +} diff --git a/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicJavaPlugin.java b/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicJavaPlugin.java new file mode 100644 index 000000000..23dff3e6e --- /dev/null +++ b/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicJavaPlugin.java @@ -0,0 +1,30 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP : CCSDK + * ================================================================================ + * 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.onap.ccsdk.sli.core.sli; + +/** + * A marker interface, used to indicate that a class exposes methods that can be + * called from an <execute> node. Such methods must have the signature: + * void methodName(Map, SvcLogicContext) + */ +public interface SvcLogicJavaPlugin { +} diff --git a/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicJdbcStore.java b/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicJdbcStore.java new file mode 100644 index 000000000..f23456fee --- /dev/null +++ b/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicJdbcStore.java @@ -0,0 +1,574 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP : CCSDK + * ================================================================================ + * 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.onap.ccsdk.sli.core.sli; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.sql.Blob; +import java.sql.Connection; +import java.sql.DatabaseMetaData; +import java.sql.Driver; +import java.sql.DriverManager; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.Properties; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class SvcLogicJdbcStore implements SvcLogicStore { + private static final Logger LOG = LoggerFactory.getLogger(SvcLogicJdbcStore.class); + + private String dbUrl = null; + private String dbName = null; + private String dbUser = null; + private String dbPasswd = null; + private String dbDriver = null; + + private Connection dbConn; + private PreparedStatement hasActiveGraphStmt = null; + private PreparedStatement hasVersionGraphStmt = null; + private PreparedStatement fetchActiveGraphStmt = null; + private PreparedStatement fetchVersionGraphStmt = null; + private PreparedStatement storeGraphStmt = null; + private PreparedStatement deleteGraphStmt = null; + + private PreparedStatement deactivateStmt = null; + private PreparedStatement activateStmt = null; + + private void getConnection() throws ConfigurationException { + + Properties jdbcProps = new Properties(); + + jdbcProps.setProperty("user", dbUser); + jdbcProps.setProperty("password", dbPasswd); + + try { + Driver dvr = new org.mariadb.jdbc.Driver(); + if (dvr.acceptsURL(dbUrl)) { + LOG.debug("Driver com.mysql.jdbc.Driver accepts {}", dbUrl); + } else { + LOG.warn("Driver com.mysql.jdbc.Driver does not accept {}", dbUrl); + } + } catch (SQLException e1) { + LOG.error("Caught exception trying to load com.mysql.jdbc.Driver", e1); + } + + try { + this.dbConn = DriverManager.getConnection(dbUrl, jdbcProps); + } catch (Exception e) { + throw new ConfigurationException("failed to get database connection [" + dbUrl + "]", e); + } + + } + + private void createTable() throws ConfigurationException { + + DatabaseMetaData dbm; + + try { + dbm = dbConn.getMetaData(); + } catch (SQLException e) { + + throw new ConfigurationException("could not get databse metadata", e); + } + + // See if table SVC_LOGIC exists. If not, create it. + Statement stmt = null; + try { + + ResultSet tables = dbm.getTables(null, null, "SVC_LOGIC", null); + if (tables.next()) { + LOG.debug("SVC_LOGIC table already exists"); + } else { + String crTableCmd = "CREATE TABLE " + dbName + ".SVC_LOGIC (" + "module varchar(80) NOT NULL," + + "rpc varchar(80) NOT NULL," + "version varchar(40) NOT NULL," + "mode varchar(5) NOT NULL," + + "active varchar(1) NOT NULL,graph BLOB," + + "modified_timestamp timestamp ," + + "md5sum varchar(128) DEFAULT NULL," + + "CONSTRAINT P_SVC_LOGIC PRIMARY KEY(module, rpc, version, mode))"; + + stmt = dbConn.createStatement(); + stmt.executeUpdate(crTableCmd); + } + } catch (Exception e) { + throw new ConfigurationException("could not create SVC_LOGIC table", e); + } finally { + if (stmt != null) { + try { + stmt.close(); + } catch (SQLException e) { + LOG.error("Statement close error ", e); + } + } + } + + // See if NODE_TYPES table exists and, if not, create it + stmt = null; + try { + + ResultSet tables = dbm.getTables(null, null, "NODE_TYPES", null); + if (tables.next()) { + LOG.debug("NODE_TYPES table already exists"); + } else { + String crTableCmd = "CREATE TABLE " + dbName + ".NODE_TYPES (" + "nodetype varchar(80) NOT NULL," + + "CONSTRAINT P_NODE_TYPES PRIMARY KEY(nodetype))"; + + stmt = dbConn.createStatement(); + + stmt.executeUpdate(crTableCmd); + } + } catch (Exception e) { + throw new ConfigurationException("could not create SVC_LOGIC table", e); + } finally { + if (stmt != null) { + try { + stmt.close(); + } catch (SQLException e) { + LOG.error("Statement close error ", e); + } + } + } + } + + private void prepStatements() throws ConfigurationException { + + // Prepare statements + String hasVersionGraphSql = CommonConstants.JDBC_SELECT_COUNT + dbName + CommonConstants.SVCLOGIC_TABLE + + CommonConstants.JDBC_GRAPH_QUERY; + + try { + hasVersionGraphStmt = dbConn.prepareStatement(hasVersionGraphSql); + } catch (Exception e) { + throw new ConfigurationException(CommonConstants.JDBC_STATEMENT_ERR + hasVersionGraphSql, e); + + } + + String hasActiveGraphSql = CommonConstants.JDBC_SELECT_COUNT + dbName + CommonConstants.SVCLOGIC_TABLE + + CommonConstants.JDBC_ACTIVE_GRAPH_QUERY; + + try { + hasActiveGraphStmt = dbConn.prepareStatement(hasActiveGraphSql); + } catch (Exception e) { + throw new ConfigurationException(CommonConstants.JDBC_STATEMENT_ERR + hasVersionGraphSql, e); + + } + + String fetchVersionGraphSql = CommonConstants.JDBC_SELECT_GRAPGH + dbName + CommonConstants.SVCLOGIC_TABLE + + CommonConstants.JDBC_GRAPH_QUERY; + + try { + fetchVersionGraphStmt = dbConn.prepareStatement(fetchVersionGraphSql); + } catch (Exception e) { + throw new ConfigurationException(CommonConstants.JDBC_STATEMENT_ERR + fetchVersionGraphSql, e); + + } + + String fetchActiveGraphSql = CommonConstants.JDBC_SELECT_GRAPGH + dbName + CommonConstants.SVCLOGIC_TABLE + + CommonConstants.JDBC_ACTIVE_GRAPH_QUERY; + + try { + fetchActiveGraphStmt = dbConn.prepareStatement(fetchActiveGraphSql); + } catch (Exception e) { + throw new ConfigurationException(CommonConstants.JDBC_STATEMENT_ERR + fetchVersionGraphSql, e); + + } + + String storeGraphSql = CommonConstants.JDBC_INSERT + dbName + + ".SVC_LOGIC (module, rpc, version, mode, active, graph, md5sum) VALUES(?, ?, ?, ?, ?, ?, ?)"; + + try { + storeGraphStmt = dbConn.prepareStatement(storeGraphSql); + } catch (Exception e) { + throw new ConfigurationException(CommonConstants.JDBC_STATEMENT_ERR + storeGraphSql, e); + } + + String deleteGraphSql = CommonConstants.JDBC_DELETE + dbName + + ".SVC_LOGIC WHERE module = ? AND rpc = ? AND version = ? AND mode = ?"; + + try { + deleteGraphStmt = dbConn.prepareStatement(deleteGraphSql); + } catch (Exception e) { + throw new ConfigurationException(CommonConstants.JDBC_STATEMENT_ERR + deleteGraphSql, e); + } + + String deactivateSql = CommonConstants.JDBC_UPDATE + dbName + + ".SVC_LOGIC SET active = 'N' WHERE module = ? AND rpc = ? AND mode = ?"; + + try { + deactivateStmt = dbConn.prepareStatement(deactivateSql); + } catch (Exception e) { + throw new ConfigurationException(CommonConstants.JDBC_STATEMENT_ERR + deactivateSql, e); + } + + String activateSql = CommonConstants.JDBC_UPDATE + dbName + + ".SVC_LOGIC SET active = 'Y' WHERE module = ? AND rpc = ? AND version = ? AND mode = ?"; + + try { + activateStmt = dbConn.prepareStatement(activateSql); + } catch (Exception e) { + throw new ConfigurationException(CommonConstants.JDBC_STATEMENT_ERR + activateSql, e); + } + } + + private void initDbResources() throws ConfigurationException { + if ((dbDriver != null) && (dbDriver.length() > 0)) { + + try { + Class.forName(dbDriver); + } catch (Exception e) { + throw new ConfigurationException("could not load driver class " + dbDriver, e); + } + } + getConnection(); + createTable(); + prepStatements(); + } + + + @Override + public void init(Properties props) throws ConfigurationException { + + + dbUrl = props.getProperty("org.onap.ccsdk.sli.jdbc.url"); + if ((dbUrl == null) || (dbUrl.length() == 0)) { + throw new ConfigurationException("property org.onap.ccsdk.sli.jdbc.url unset"); + } + + dbName = props.getProperty("org.onap.ccsdk.sli.jdbc.database"); + if ((dbName == null) || (dbName.length() == 0)) { + throw new ConfigurationException("property org.onap.ccsdk.sli.jdbc.database unset"); + } + + dbUser = props.getProperty("org.onap.ccsdk.sli.jdbc.user"); + if ((dbUser == null) || (dbUser.length() == 0)) { + throw new ConfigurationException("property org.onap.ccsdk.sli.jdbc.user unset"); + } + + + dbPasswd = props.getProperty("org.onap.ccsdk.sli.jdbc.password"); + if ((dbPasswd == null) || (dbPasswd.length() == 0)) { + throw new ConfigurationException("property org.onap.ccsdk.sli.jdbc.password unset"); + } + + dbDriver = props.getProperty("org.onap.ccsdk.sli.jdbc.driver"); + + + initDbResources(); + + } + + private boolean isDbConnValid() { + + boolean isValid = false; + + try { + if (dbConn != null) { + isValid = dbConn.isValid(1); + } + } catch (SQLException e) { + LOG.error("Not a valid db connection: ", e); + } + + return isValid; + } + + @Override + public boolean hasGraph(String module, String rpc, String version, String mode) throws SvcLogicException { + + if (!isDbConnValid()) { + + // Try reinitializing + initDbResources(); + + if (!isDbConnValid()) { + throw new ConfigurationException(CommonConstants.JDBC_CONN_ERR); + } + } + + boolean retval = false; + ResultSet results = null; + + PreparedStatement hasGraphStmt; + if (version == null) { + hasGraphStmt = hasActiveGraphStmt; + } else { + hasGraphStmt = hasVersionGraphStmt; + } + + try { + hasGraphStmt.setString(1, module); + hasGraphStmt.setString(2, rpc); + hasGraphStmt.setString(3, mode); + + + if (version != null) { + hasGraphStmt.setString(4, version); + } + boolean oldAutoCommit = dbConn.getAutoCommit(); + dbConn.setAutoCommit(false); + results = hasGraphStmt.executeQuery(); + dbConn.commit(); + dbConn.setAutoCommit(oldAutoCommit); + + if (results.next()) { + int cnt = results.getInt(1); + + if (cnt > 0) { + retval = true; + } + + } + } catch (Exception e) { + throw new ConfigurationException("SQL query failed", e); + } finally { + if (results != null) { + try { + results.close(); + } catch (SQLException x) { + LOG.error(CommonConstants.RESULTSET_CLOSE_ERR, x); + } + } + + } + + return retval; + + } + + @Override + public SvcLogicGraph fetch(String module, String rpc, String version, String mode) throws SvcLogicException { + + + if (!isDbConnValid()) { + + // Try reinitializing + initDbResources(); + + if (!isDbConnValid()) { + throw new ConfigurationException(CommonConstants.JDBC_CONN_ERR); + } + } + + SvcLogicGraph retval = null; + ResultSet results = null; + + PreparedStatement fetchGraphStmt; + if (version == null) { + fetchGraphStmt = fetchActiveGraphStmt; + } else { + fetchGraphStmt = fetchVersionGraphStmt; + } + try { + fetchGraphStmt.setString(1, module); + fetchGraphStmt.setString(2, rpc); + fetchGraphStmt.setString(3, mode); + + + if (version != null) { + fetchGraphStmt.setString(4, version); + } + boolean oldAutoCommit = dbConn.getAutoCommit(); + dbConn.setAutoCommit(false); + results = fetchGraphStmt.executeQuery(); + dbConn.commit(); + dbConn.setAutoCommit(oldAutoCommit); + + if (results.next()) { + Blob graphBlob = results.getBlob("graph"); + + ObjectInputStream gStream = new ObjectInputStream(graphBlob.getBinaryStream()); + + Object graphObj = gStream.readObject(); + gStream.close(); + + if (graphObj instanceof SvcLogicGraph) { + retval = (SvcLogicGraph) graphObj; + } else { + throw new ConfigurationException("invalid type for graph (" + graphObj.getClass().getName()); + + } + } + + } catch (Exception e) { + throw new ConfigurationException("SQL query failed", e); + } finally { + if (results != null) { + try { + results.close(); + } catch (SQLException x) { + LOG.error(CommonConstants.RESULTSET_CLOSE_ERR, x); + } + } + + } + + return retval; + } + + public void store(SvcLogicGraph graph) throws SvcLogicException { + + + if (!isDbConnValid()) { + + // Try reinitializing + initDbResources(); + + if (!isDbConnValid()) { + throw new ConfigurationException(CommonConstants.JDBC_CONN_ERR); + } + } + + if (graph == null) { + throw new SvcLogicException("graph cannot be null"); + } + + byte[] graphBytes; + + try (ByteArrayOutputStream byteStr = new ByteArrayOutputStream(); + ObjectOutputStream goutStr = new ObjectOutputStream(byteStr)) { + + goutStr.writeObject(graph); + + graphBytes = byteStr.toByteArray(); + + } catch (Exception e) { + throw new SvcLogicException("could not serialize graph", e); + } + + // If object already stored in database, delete it + if (hasGraph(graph.getModule(), graph.getRpc(), graph.getVersion(), graph.getMode())) { + delete(graph.getModule(), graph.getRpc(), graph.getVersion(), graph.getMode()); + } + + try { + boolean oldAutoCommit = dbConn.getAutoCommit(); + dbConn.setAutoCommit(false); + storeGraphStmt.setString(1, graph.getModule()); + storeGraphStmt.setString(2, graph.getRpc()); + storeGraphStmt.setString(3, graph.getVersion()); + storeGraphStmt.setString(4, graph.getMode()); + storeGraphStmt.setString(5, "N"); + storeGraphStmt.setBlob(6, new ByteArrayInputStream(graphBytes)); + storeGraphStmt.setString(7, graph.getMd5sum()); + + storeGraphStmt.executeUpdate(); + dbConn.commit(); + + dbConn.setAutoCommit(oldAutoCommit); + } catch (Exception e) { + throw new SvcLogicException("Could not write object to database", e); + } + } + + @Override + public void delete(String module, String rpc, String version, String mode) throws SvcLogicException { + if (!isDbConnValid()) { + + // Try reinitializing + initDbResources(); + + if (!isDbConnValid()) { + throw new ConfigurationException(CommonConstants.JDBC_CONN_ERR); + } + } + + try { + boolean oldAutoCommit = dbConn.getAutoCommit(); + dbConn.setAutoCommit(false); + deleteGraphStmt.setString(1, module); + deleteGraphStmt.setString(2, rpc); + deleteGraphStmt.setString(3, version); + deleteGraphStmt.setString(4, mode); + + + deleteGraphStmt.executeUpdate(); + dbConn.commit(); + dbConn.setAutoCommit(oldAutoCommit); + } catch (Exception e) { + throw new SvcLogicException("Could not delete object from database", e); + } + } + + @Override + public void activate(SvcLogicGraph graph) throws SvcLogicException { + try { + boolean oldAutoCommit = dbConn.getAutoCommit(); + + dbConn.setAutoCommit(false); + + // Deactivate any current active version + deactivateStmt.setString(1, graph.getModule()); + deactivateStmt.setString(2, graph.getRpc()); + deactivateStmt.setString(3, graph.getMode()); + deactivateStmt.executeUpdate(); + + // Activate this version + activateStmt.setString(1, graph.getModule()); + activateStmt.setString(2, graph.getRpc()); + activateStmt.setString(3, graph.getVersion()); + activateStmt.setString(4, graph.getMode()); + activateStmt.executeUpdate(); + + dbConn.commit(); + + dbConn.setAutoCommit(oldAutoCommit); + + } catch (Exception e) { + throw new SvcLogicException("Could not activate graph", e); + } + } + + @Override + public void activate(String module, String rpc, String version, String mode) throws SvcLogicException { + try { + boolean oldAutoCommit = dbConn.getAutoCommit(); + + dbConn.setAutoCommit(false); + + // Deactivate any current active version + deactivateStmt.setString(1, module); + deactivateStmt.setString(2, rpc); + deactivateStmt.setString(3, mode); + deactivateStmt.executeUpdate(); + + // Activate this version + activateStmt.setString(1, module); + activateStmt.setString(2, rpc); + activateStmt.setString(3, version); + activateStmt.setString(4, mode); + activateStmt.executeUpdate(); + + dbConn.commit(); + + dbConn.setAutoCommit(oldAutoCommit); + + } catch (Exception e) { + throw new SvcLogicException("Could not activate graph", e); + } + } + + +} diff --git a/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicLoader.java b/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicLoader.java new file mode 100644 index 000000000..433b723e7 --- /dev/null +++ b/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicLoader.java @@ -0,0 +1,178 @@ +/*- + * ============LICENSE_START======================================================= + * openECOMP : SDN-C + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights + * reserved. + * ================================================================================ + * Modifications Copyright (C) 2018 IBM. + * ================================================================================ + * 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.onap.ccsdk.sli.core.sli; + +import java.io.BufferedReader; +import java.io.File; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class SvcLogicLoader { + private static final Logger LOGGER = LoggerFactory.getLogger(SvcLogicLoader.class); + protected SvcLogicStore store; + protected String directoryRoot; + protected SvcLogicParser parser; + + public SvcLogicLoader(String directoryRoot, SvcLogicStore store) { + this.store = store; + this.directoryRoot = directoryRoot; + this.parser = new SvcLogicParser(); + } + + public SvcLogicLoader(String directoryRoot, String propFile) { + this.store = SvcLogicParser.getStore(propFile); + this.directoryRoot = directoryRoot; + this.parser = new SvcLogicParser(); + } + + public void loadAndActivate() throws IOException { + SvcLogicCrawler slc = new SvcLogicCrawler(); + Files.walkFileTree(Paths.get(directoryRoot), slc); + loadGraphs(slc.getGraphPaths(), directoryRoot); + List<ActivationEntry> activationEntries = processActivationFiles(slc.getActivationPaths()); + activateGraphs(activationEntries); + } + + protected List<ActivationEntry> processActivationFiles(List<Path> activationPaths) { + List<ActivationEntry> activationEntries = new ArrayList<>(); + for (Path activationFile : activationPaths) { + activationEntries.addAll(getActivationEntries(activationFile)); + } + return activationEntries; + } + + protected void activateGraphs(List<ActivationEntry> activationEntries) { + for (ActivationEntry entry : activationEntries) { + try { + if (store.hasGraph(entry.module, entry.rpc, entry.version, entry.mode)) { + LOGGER.info("Activating SvcLogicGraph [module=" + entry.module + ", rpc=" + entry.rpc + ", mode=" + + entry.mode + ", version=" + entry.version + "]"); + store.activate(entry.module, entry.rpc, entry.version, entry.mode); + } else { + LOGGER.error("hasGraph returned false for " + entry.toString()); + } + } catch (SvcLogicException e) { + LOGGER.error("Failed to call hasGraph for " + entry.toString(), e); + } + } + } + + protected List<ActivationEntry> getActivationEntries(Path activationFilePath) { + List<ActivationEntry> activationEntries = new ArrayList<>(); + int lineNumber = 1; + try (BufferedReader br = Files.newBufferedReader(activationFilePath, StandardCharsets.US_ASCII)) { + String fileRead = br.readLine(); + while (fileRead != null) { + String[] fields = fileRead.split("\\s"); + if (fields.length == 4) { + activationEntries.add(parseActivationEntry(fields)); + } else { + LOGGER.error("Activation entry [" + fileRead + "] is declared at line number " + lineNumber + + " in the file " + activationFilePath + " and is invalid."); + } + fileRead = br.readLine(); + lineNumber++; + } + return activationEntries; + } catch (IOException ioe) { + LOGGER.error("Couldn't read the activation file at " + activationFilePath, ioe); + return new ArrayList<>(); + } + } + + protected void loadGraphs(List<Path> graphPaths, String directoryRoot) { + for (Path graphPath : graphPaths) { + try { + saveGraph(graphPath.toString()); + } catch (Exception e) { + LOGGER.error("Couldn't load graph at " + graphPath, e); + } + } + } + + protected void saveGraph(String xmlFile) throws SvcLogicException { + File f = new File(xmlFile); + if (!f.canRead()) { + throw new ConfigurationException("Cannot read xml file (" + xmlFile + ")"); + } + + LinkedList<SvcLogicGraph> graphs = null; + + try { + graphs = parser.parse(xmlFile); + } catch (Exception e) { + throw new SvcLogicException(e.getMessage(), e); + } + + if (graphs == null) { + throw new SvcLogicException("Could not parse " + xmlFile); + } + + for (Iterator<SvcLogicGraph> iter = graphs.iterator(); iter.hasNext();) { + SvcLogicGraph graph = iter.next(); + try { + LOGGER.info("Saving " + graph.toString() + " to database"); + store.store(graph); + } catch (Exception e) { + throw new SvcLogicException(e.getMessage(), e); + } + } + } + + protected ActivationEntry parseActivationEntry(String[] fileInput) { + return new ActivationEntry(fileInput[0], fileInput[1], fileInput[2], fileInput[3]); + } + + protected String getValue(String raw, String attributeName) { + raw = raw.substring(attributeName.length() + 1); + if (raw.contains(">")) { + raw = raw.substring(0, raw.lastIndexOf('>')); + } + if (raw.endsWith("'")) { + raw = raw.substring(0, raw.lastIndexOf('\'')); + } + if (raw.endsWith("\"")) { + raw = raw.substring(0, raw.lastIndexOf('"')); + } + return raw; + } + + public void bulkActivate() { + Path activationFile = Paths.get(directoryRoot); + List<Path> pathList = new ArrayList<>(1); + pathList.add(activationFile); + List<ActivationEntry> activationEntries = processActivationFiles(pathList); + activateGraphs(activationEntries); + } + +} diff --git a/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicNode.java b/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicNode.java new file mode 100644 index 000000000..b0d4fc058 --- /dev/null +++ b/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicNode.java @@ -0,0 +1,457 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP : CCSDK + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights + * reserved. + * ================================================================================ + * Modifications Copyright (C) 2018 IBM. + * ================================================================================ + * 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.onap.ccsdk.sli.core.sli; + +import java.io.IOException; +import java.io.PrintStream; +import java.io.Serializable; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; +import java.util.Set; +import java.util.HashSet; +import java.util.TreeMap; + +import org.apache.commons.text.StringEscapeUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class SvcLogicNode implements Serializable { + + private static final Logger LOG = LoggerFactory + .getLogger(SvcLogicExprListener.class); + + private static final long serialVersionUID = 2L; + + private String nodeName; + private int nodeId; + private String nodeType; + private boolean visited; + private SvcLogicGraph graph; + + + private HashMap<String, SvcLogicExpression> attributes; + private HashMap<String, SvcLogicNode> outcomes; + private HashMap<String, SvcLogicExpression> parameters; + + public SvcLogicNode(int nodeId, String nodeType, SvcLogicGraph graph) + { + this.nodeId = nodeId; + nodeName = ""; + this.nodeType = nodeType; + this.graph = graph; + attributes = new HashMap<> (); + parameters = new HashMap<> (); + outcomes = null; + + } + + public SvcLogicNode(int nodeId, String nodeType, String nodeName, SvcLogicGraph graph) throws DuplicateValueException + { + this.nodeId = nodeId; + this.nodeName = nodeName; + this.nodeType = nodeType; + this.graph = graph; + attributes = new HashMap<> (); + parameters = new HashMap<> (); + outcomes = null; + graph.setNamedNode(nodeName, this); + } + + + public int getNodeId() + { + return nodeId; + } + + public String getNodeName() + { + return nodeName; + } + + public String getNodeType() + { + return nodeType; + } + + public SvcLogicGraph getGraph() + { + return graph; + } + + public int getNumOutcomes() + { + if (outcomes == null) + { + return 0; + } + else + { + return outcomes.size(); + } + } + + public SvcLogicExpression getAttribute(String name) + { + if (attributes.containsKey(name)) + { + return attributes.get(name); + } + else + { + return null; + } + + } + + public void setAttribute(String name, String value) throws SvcLogicException + { + setAttribute(name, new SvcLogicAtom("STRING", value)); + } + + public void setAttribute(String name, SvcLogicExpression value) throws SvcLogicException + { + if (attributes.containsKey(name)) + { + throw new DuplicateValueException("Duplicate attribute "+name); + } + + attributes.put(name, value); + } + + + public void mapParameter(String name, String value) throws SvcLogicException + { + + if (parameters.containsKey(name)) + { + throw new DuplicateValueException("Duplicate parameter "+name); + } + try + { + SvcLogicExpression parmValue; + if (value == null || value.length() == 0) + { + parmValue = new SvcLogicAtom("STRING", ""); + } + else if (value.trim().startsWith("`")) + { + int lastParen = value.lastIndexOf("`"); + String evalExpr = value.trim().substring(1, lastParen); + parmValue = SvcLogicExpressionFactory.parse(evalExpr); + + } + else + { + if (Character.isDigit(value.charAt(0))) + { + parmValue = new SvcLogicAtom("NUMBER", value); + } + else + { + parmValue = new SvcLogicAtom("STRING", value); + } + } + LOG.debug("Setting parameter "+name+" = "+value+" = "+parmValue.asParsedExpr()); + parameters.put(name, parmValue); + } + catch (IOException e) { + + LOG.error("Invalid parameter value expression ("+value+")"); + throw new SvcLogicException(e.getMessage()); + } + } + + public SvcLogicExpression getParameter(String name) + { + if (parameters.containsKey(name)) + { + return parameters.get(name); + } + else + { + return null; + } + } + + public boolean isVisited() { + return visited; + } + + public void setVisited(boolean visited, boolean recursive) { + this.visited = visited; + + if (recursive) + { + Set<Map.Entry<String, SvcLogicNode>> outcomeSet = getOutcomeSet(); + + if (outcomeSet == null) + { + return; + } + + for (Iterator<Map.Entry<String, SvcLogicNode>> iter = outcomeSet.iterator(); iter.hasNext();) + { + Map.Entry<String, SvcLogicNode> curOutcome = iter.next(); + SvcLogicNode outNode = curOutcome.getValue(); + outNode.setVisited(visited, recursive); + } + } + } + + public void addOutcome(String outcomeValue, SvcLogicNode node) throws SvcLogicException + { + if (outcomes == null) + { + outcomes = new HashMap<>(); + } + + if (outcomeValue.length() == 0) { + outcomeValue = "\"\""; + } + if (outcomes.containsKey(outcomeValue)) + { + throw new DuplicateValueException("Duplicate outcome value "+outcomeValue); + } + + outcomes.put(outcomeValue, node); + } + + public Set<Map.Entry<String, SvcLogicNode>> getOutcomeSet() + { + if (outcomes == null) + { + return new HashSet<>(); + } + + return outcomes.entrySet(); + + } + + public Set<Map.Entry<String, SvcLogicExpression>> getParameterSet() + { + if (parameters == null) + { + return new HashSet<>(); + } + + return parameters.entrySet(); + + } + + public void printAsGv(PrintStream pstr) + { + + if (visited) + { + return; + } + else + { + visited = true; + } + + StringBuffer sbuff = new StringBuffer(); + + sbuff.append("node"); + sbuff.append(nodeId); + sbuff.append(" [ shape=none, margin=0, label=<<table border=\"0\" cellborder=\"1\" align=\"left\">"); + sbuff.append("<tr><td colspan=\"2\"><b>"); + sbuff.append(nodeId); + sbuff.append(" : "); + sbuff.append(nodeType); + sbuff.append("</b></td></tr><th><td><i>Attribute</i></td><td><i>Value</i></td></th>"); + + if (nodeName.length() > 0) + { + sbuff.append("<tr><td>name</td><td>"); + sbuff.append(nodeName); + sbuff.append("</td></tr>"); + } + + Set<Map.Entry<String, SvcLogicExpression>> attrSet = attributes.entrySet(); + for (Iterator<Map.Entry<String, SvcLogicExpression>> iter = attrSet.iterator() ; iter.hasNext();) + { + Map.Entry<String, SvcLogicExpression> curAttr = iter.next(); + sbuff.append("<tr><td>"); + sbuff.append(curAttr.getKey()); + sbuff.append("</td><td>"); + sbuff.append(StringEscapeUtils.escapeHtml3(curAttr.getValue().toString())); + sbuff.append("</td></tr>"); + } + sbuff.append("</table>>];"); + + pstr.println(sbuff.toString()); + + + if (outcomes != null) + { + TreeMap<String, SvcLogicNode> sortedOutcomes = new TreeMap<>(outcomes); + Set<Map.Entry<String, SvcLogicNode>> outcomeSet = sortedOutcomes.entrySet(); + + for (Iterator<Map.Entry<String, SvcLogicNode>> iter = outcomeSet.iterator(); iter.hasNext();) + { + Map.Entry<String, SvcLogicNode> curOutcome = iter.next(); + String outValue = curOutcome.getKey(); + SvcLogicNode outNode = curOutcome.getValue(); + pstr.println("node"+nodeId+" -> node"+outNode.getNodeId()+" [label=\""+outValue+"\"];"); + outNode.printAsGv(pstr); + } + } + } + + public void printAsXml(PrintStream pstr, int indentLvl) + { + if (visited) + { + return; + } + // Print node tag + for (int i = 0 ; i < indentLvl ; i++) + { + pstr.print(" "); + } + pstr.print("<"); + pstr.print(this.getNodeType()); + + Set<Map.Entry<String, SvcLogicExpression>> attrSet = attributes.entrySet(); + for (Iterator<Map.Entry<String, SvcLogicExpression>> iter = attrSet.iterator() ; iter.hasNext();) + { + Map.Entry<String, SvcLogicExpression> curAttr = iter.next(); + pstr.print(" "); + pstr.print(curAttr.getKey()); + pstr.print("='`"); + pstr.print(curAttr.getValue()); + pstr.print("'`"); + } + + if ((parameters == null || parameters.isEmpty()) && + (outcomes == null || outcomes.isEmpty())) + { + pstr.print("/>\n"); + pstr.flush(); + return; + } + else + { + pstr.print(">\n"); + } + + // Print parameters (if any) + if (parameters != null) + { + Set<Map.Entry<String, SvcLogicExpression>> paramSet = parameters.entrySet(); + for (Iterator<Map.Entry<String, SvcLogicExpression>> iter = paramSet.iterator() ; iter.hasNext();) + { + for (int i = 0 ; i < indentLvl+1 ; i++) + { + pstr.print(" "); + } + pstr.print("<parameter"); + Map.Entry<String, SvcLogicExpression> curAttr = iter.next(); + pstr.print(" name='"); + pstr.print(curAttr.getKey()); + pstr.print("' value='`"); + pstr.print(curAttr.getValue().toString()); + pstr.print("`'/>\n"); + } + } + + // Print outcomes (if any) + if (outcomes != null) + { + Set<Map.Entry<String, SvcLogicNode>> outcomeSet = outcomes.entrySet(); + for (Iterator<Map.Entry<String, SvcLogicNode>> iter = outcomeSet.iterator() ; iter.hasNext();) + { + for (int i = 0 ; i < indentLvl+1 ; i++) + { + pstr.print(" "); + } + pstr.print("<outcome"); + Map.Entry<String, SvcLogicNode> curAttr = iter.next(); + pstr.print(" value='"); + pstr.print(curAttr.getKey()); + pstr.print("'>\n"); + SvcLogicNode outNode = curAttr.getValue(); + outNode.printAsXml(pstr, indentLvl+2); + for (int i = 0 ; i < indentLvl+1 ; i++) + { + pstr.print(" "); + } + pstr.print("</outcome>\n"); + } + } + + // Print node end tag + for (int i = 0 ; i < indentLvl ; i++) + { + pstr.print(" "); + } + pstr.print("</"); + pstr.print(this.getNodeType()); + pstr.print(">\n"); + pstr.flush(); + + } + + + public SvcLogicNode getOutcomeValue(String value) + { + + if (value.length() == 0) { + value = "\"\""; + } + if (outcomes == null) + { + return null; + } + + if (outcomes.containsKey(value)) + { + return outcomes.get(value); + } + else + { + StringBuffer keyBuffer = new StringBuffer(); + keyBuffer.append("{"); + for (String key : outcomes.keySet()) { + keyBuffer.append(" ("+key+")"); + } + keyBuffer.append("}"); + LOG.info("Outcome (" + value + ") not found, keys are " + keyBuffer.toString()); + + if (outcomes.containsKey("Other")) + { + return outcomes.get("Other"); + } + else + { + return null; + } + } + } +} diff --git a/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicParser.java b/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicParser.java new file mode 100644 index 000000000..adec7b27d --- /dev/null +++ b/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicParser.java @@ -0,0 +1,615 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP : CCSDK + * ================================================================================ + * 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.onap.ccsdk.sli.core.sli; + +import java.io.File; +import java.io.IOException; +import java.net.URL; +import java.util.LinkedList; +import javax.xml.XMLConstants; +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.parsers.SAXParser; +import javax.xml.parsers.SAXParserFactory; +import javax.xml.validation.Schema; +import javax.xml.validation.SchemaFactory; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.xml.sax.*; +import org.xml.sax.helpers.DefaultHandler; +import org.onap.ccsdk.sli.core.utils.PathValidator; + +/** + * @author dt5972 + * + */ +public class SvcLogicParser { + + static final String JAXP_SCHEMA_LANGUAGE = "http://java.sun.com/xml/jaxp/properties/schemaLanguage"; + static final String W3C_XML_SCHEMA = "http://www.w3.org/2001/XMLSchema"; + static final String JAXP_SCHEMA_SOURCE = "http://java.sun.com/xml/jaxp/properties/schemaSource"; + static final String JAXP_DYNAMIC_VALIDATION = "http://apache.org/xml/features/validation/dynamic"; + static final String JAXP_SCHEMA_VALIDATION = "http://apache.org/xml/features/validation/schema"; + + private static final String LOAD_MESSAGE = "Getting SvcLogicGraph from database - {}"; + private static final String LOAD_ERROR_MESSAGE = "SvcLogicGraph not found - {}"; + private static final String ACTIVATION_ERROR_MESSAGE = "Could not activate SvcLogicGraph - {}"; + private static final String PRINT_ERROR_MESSAGE = "Could not print SvcLogicGraph - {}"; + private static final String SVC_LOGIC_STORE_ERROR = "Could not get service logic store"; + + private static final Logger LOGGER = LoggerFactory.getLogger(SvcLogicParser.class); + private static final String SLI_VALIDATING_PARSER = "org.onap.ccsdk.sli.parser.validate"; + private static final String SVCLOGIC_XSD = "/svclogic.xsd"; + private SAXParser saxParser; + + private class SvcLogicHandler extends DefaultHandler { + private Locator locator = null; + private String module = null; + private String version = null; + private LinkedList<SvcLogicGraph> graphs = null; + private SvcLogicGraph curGraph = null; + private SvcLogicNode curNode = null; + private LinkedList<SvcLogicNode> nodeStack = null; + private int curNodeId = 0; + private String outcomeValue = null; + private LinkedList<String> outcomeStack = null; + + public SvcLogicHandler(LinkedList<SvcLogicGraph> graphs) { + this.graphs = graphs; + this.curNode = null; + this.nodeStack = new LinkedList<>(); + this.outcomeStack = new LinkedList<>(); + this.curNodeId = 1; + this.outcomeValue = null; + } + + @Override + public void setDocumentLocator(Locator locator) { + this.locator = locator; + } + + @Override + public void startElement(String uri, String localName, String qName, Attributes attributes) + throws SAXException { + + // Handle service-logic (graph) tag + if ("service-logic".equalsIgnoreCase(qName)) { + + module = attributes.getValue("module"); + if (module == null || module.length() == 0) { + throw new SAXException("line " + locator.getLineNumber() + ":" + locator.getColumnNumber() + " " + + "Missing 'module' attribute from service-logic tag"); + } + + version = attributes.getValue("version"); + if (version == null || version.length() == 0) { + throw new SAXException("line " + locator.getLineNumber() + ":" + locator.getColumnNumber() + " " + + "Missing 'version' attribute from service-logic tag"); + } + + return; + } + + if ("method".equalsIgnoreCase(qName)) { + + if (curGraph != null) { + throw new SAXException("line " + locator.getLineNumber() + ":" + locator.getColumnNumber() + " " + + "Cannot nest module tags"); + } + + curGraph = new SvcLogicGraph(); + curGraph.setModule(module); + curGraph.setVersion(version); + this.curNodeId = 1; + + String attrValue = attributes.getValue("rpc"); + if (attrValue == null || attrValue.length() == 0) { + throw new SAXException("line " + locator.getLineNumber() + ":" + locator.getColumnNumber() + " " + + "Missing 'rpc' attribute for method tag"); + } + curGraph.setRpc(attrValue); + + attrValue = attributes.getValue("mode"); + if (attrValue == null || attrValue.length() == 0) { + throw new SAXException("line " + locator.getLineNumber() + ":" + locator.getColumnNumber() + " " + + "Missing 'mode' attribute for method tag"); + } + curGraph.setMode(attrValue); + + return; + } + + // Handle outcome (edge) tag + if ("outcome".equalsIgnoreCase(qName)) { + String refValue = attributes.getValue("ref"); + + if (refValue != null) { + SvcLogicNode refNode = curGraph.getNamedNode(refValue); + + if (refNode != null) { + try { + curNode.addOutcome(attributes.getValue("value"), refNode); + } catch (SvcLogicException e) { + throw new SAXException("line " + locator.getLineNumber() + ":" + locator.getColumnNumber() + + " " + "Cannot add outcome", e); + } + } else { + throw new SAXException("line " + locator.getLineNumber() + ":" + locator.getColumnNumber() + " " + + "ref to unknown node " + refValue); + } + return; + } + + if (outcomeValue != null) { + outcomeStack.push(outcomeValue); + } + outcomeValue = attributes.getValue("value"); + + return; + } + + // Handle parameter tag + if ("parameter".equalsIgnoreCase(qName)) { + String parmName = attributes.getValue("name"); + String parmValue = attributes.getValue("value"); + + if (parmName != null && parmName.length() > 0 && parmValue != null) { + try { + + curNode.mapParameter(parmName, parmValue); + } catch (Exception e) { + throw new SAXException("line " + locator.getLineNumber() + ":" + locator.getColumnNumber() + " " + + " cannot set parameter " + parmName + " to " + parmValue + " [" + e.getMessage() + + "]"); + } + } + + return; + } + + // Handle node tags + String nodeName = attributes.getValue("name"); + SvcLogicNode thisNode; + + + try { + if (nodeName != null && nodeName.length() > 0) { + thisNode = new SvcLogicNode(curNodeId++, qName, nodeName, curGraph); + } else { + thisNode = new SvcLogicNode(curNodeId++, qName, curGraph); + } + + if (curGraph.getRootNode() == null) { + curGraph.setRootNode(thisNode); + } + } catch (SvcLogicException e) { + throw new SAXException( + "line " + locator.getLineNumber() + ":" + locator.getColumnNumber() + " " + e.getMessage()); + + } + + int numAttributes = attributes.getLength(); + + for (int i = 0; i < numAttributes; i++) { + String attrName = attributes.getQName(i); + if (!"name".equalsIgnoreCase(attrName)) { + try { + + String attrValueStr = attributes.getValue(i); + SvcLogicExpression attrValue; + if (attrValueStr.trim().startsWith("`")) { + int lastParen = attrValueStr.lastIndexOf('`'); + String evalExpr = attrValueStr.trim().substring(1, lastParen); + attrValue = SvcLogicExpressionFactory.parse(evalExpr); + + } else { + if (Character.isDigit(attrValueStr.charAt(0))) { + attrValue = new SvcLogicAtom("NUMBER", attrValueStr); + } else { + attrValue = new SvcLogicAtom("STRING", attrValueStr); + } + } + thisNode.setAttribute(attrName, attrValue); + } catch (Exception e) { + throw new SAXException("line " + locator.getLineNumber() + ":" + locator.getColumnNumber() + " " + + "Cannot set attribute " + attrName, e); + } + } + } + + if (curNode != null) { + try { + if ("block".equalsIgnoreCase(curNode.getNodeType()) || "for".equalsIgnoreCase(curNode.getNodeType()) + || "while".equalsIgnoreCase(curNode.getNodeType())) { + curNode.addOutcome(Integer.toString(curNode.getNumOutcomes() + 1), thisNode); + } else { + if (outcomeValue == null) { + throw new SAXException("line " + locator.getLineNumber() + ":" + locator.getColumnNumber() + + " " + curNode.getNodeType() + " node expects outcome, instead found " + + thisNode.getNodeType()); + } + curNode.addOutcome(outcomeValue, thisNode); + } + } catch (SvcLogicException e) { + throw new SAXException( + "line " + locator.getLineNumber() + ":" + locator.getColumnNumber() + " " + e.getMessage()); + } + nodeStack.push(curNode); + } + curNode = thisNode; + + } + + @Override + public void endElement(String uri, String localName, String qName) throws SAXException { + + // Handle close of service-logic tag + if ("service-logic".equalsIgnoreCase(qName)) { + // Nothing more to do + return; + } + + // Handle close of method tag + if ("method".equalsIgnoreCase(qName)) { + graphs.add(curGraph); + curGraph = null; + return; + } + + // Handle close of outcome tag + if ("outcome".equalsIgnoreCase(qName)) { + // Finished this outcome - pop the outcome stack + if (outcomeStack.isEmpty()) { + outcomeValue = null; + } else { + outcomeValue = outcomeStack.pop(); + } + return; + } + + // Handle close of parameter tag - do nothing + if ("parameter".equalsIgnoreCase(qName)) { + return; + } + + // Handle close of a node tag + if (nodeStack.isEmpty()) { + curNode = null; + } else { + curNode = nodeStack.pop(); + } + } + + @Override + public void error(SAXParseException arg0) throws SAXException { + throw new SAXException( + "line " + locator.getLineNumber() + ":" + locator.getColumnNumber() + " " + arg0.getMessage()); + } + + } + + public LinkedList<SvcLogicGraph> parse(String fileName) throws SvcLogicException { + LinkedList<SvcLogicGraph> graphs; + + try { + if (saxParser == null) { + saxParser = initParser(); + } + + graphs = new LinkedList<>(); + saxParser.parse(fileName, new SvcLogicHandler(graphs)); + + try { + for (SvcLogicGraph graph : graphs) { + graph.setMd5sum(CheckSumHelper.md5SumFromFile(fileName)); + } + } catch (Exception exc) { + LOGGER.error("Couldn't set md5sum on graphs", exc); + } + } catch (Exception e) { + LOGGER.error("Parsing failed ", e); + String msg = e.getMessage(); + if (msg != null) { + throw new SvcLogicException("Compiler error: " + fileName + " @ " + msg); + } else { + throw new SvcLogicException("Compiler error: " + fileName, e); + } + } + return graphs; + } + + public static void main(String argv[]) { + + if (argv.length == 0) { + SvcLogicParser.usage(); + } + + if ("load".equalsIgnoreCase(argv[0])) { + if (argv.length == 3) { + String xmlfile = argv[1]; + String propfile = argv[2]; + + SvcLogicStore store = SvcLogicParser.getStore(propfile); + try { + SvcLogicParser.load(xmlfile, store); + } catch (Exception e) { + LOGGER.error("Load failed ", e); + } + } else { + SvcLogicParser.usage(); + } + } else if ("print".equalsIgnoreCase(argv[0])) { + String version = null; + String propfile = null; + + switch (argv.length) { + case 6: + version = argv[4]; + propfile = argv[5]; + case 5: + if (propfile == null) { + propfile = argv[4]; + } + SvcLogicStore store = SvcLogicParser.getStore(propfile); + SvcLogicParser.print(argv[1], argv[2], argv[3], version, store); + break; + default: + SvcLogicParser.usage(); + } + } else if ("get-source".equalsIgnoreCase(argv[0])) { + + if (argv.length == 6) { + SvcLogicStore store = SvcLogicParser.getStore(argv[5]); + SvcLogicParser.getSource(argv[1], argv[2], argv[3], argv[4], store); + } else { + SvcLogicParser.usage(); + } + } else if ("activate".equalsIgnoreCase(argv[0])) { + if (argv.length == 6) { + SvcLogicStore store = SvcLogicParser.getStore(argv[5]); + SvcLogicParser.activate(argv[1], argv[2], argv[3], argv[4], store); + } else { + SvcLogicParser.usage(); + } + } else if ("validate".equalsIgnoreCase(argv[0])) { + if (argv.length == 3) { + String xmlfile = argv[1]; + String propfile = argv[2]; + + System.setProperty(SLI_VALIDATING_PARSER, "true"); + SvcLogicStore store = SvcLogicParser.getStore(propfile); + try { + SvcLogicParser.validate(xmlfile, store); + } catch (Exception e) { + LOGGER.error("Validate failed", e); + } + } else { + SvcLogicParser.usage(); + } + } else if ("install".equalsIgnoreCase(argv[0])) { + if (argv.length == 3) { + SvcLogicLoader loader = new SvcLogicLoader(argv[1], argv[2]); + try { + loader.loadAndActivate(); + } catch (IOException e) { + LOGGER.error(e.getMessage(), e); + } + } else { + SvcLogicParser.usage(); + } + } else if ("bulkActivate".equalsIgnoreCase(argv[0])) { + if (argv.length == 3) { + SvcLogicLoader loader = new SvcLogicLoader(argv[1], argv[2]); + try { + loader.bulkActivate(); + } catch (Exception e) { + LOGGER.error(e.getMessage(), e); + } + } else { + SvcLogicParser.usage(); + } + } + + System.exit(0); + } + + protected static SvcLogicStore getStore(String propfile) { + + SvcLogicStore store = null; + + try { + store = SvcLogicStoreFactory.getSvcLogicStore(propfile); + } catch (Exception e) { + LOGGER.error(SVC_LOGIC_STORE_ERROR, e); + System.exit(1); + } + + return store; + + } + + + public static void load(String xmlfile, SvcLogicStore store) throws SvcLogicException { + if (!PathValidator.isValidXmlPath(xmlfile)) { + throw new ConfigurationException("Invalid xml file name ("+ xmlfile + ")"); + } + File xmlFile = new File(xmlfile); + if (!xmlFile.canRead()) { + throw new ConfigurationException("Cannot read xml file (" + xmlfile + ")"); + } + + SvcLogicParser parser = new SvcLogicParser(); + LinkedList<SvcLogicGraph> graphs; + try { + LOGGER.info("Loading {}", xmlfile); + graphs = parser.parse(xmlfile); + } catch (Exception e) { + throw new SvcLogicException(e.getMessage(), e); + } + + if (graphs == null) { + throw new SvcLogicException("Could not parse " + xmlfile); + } + + for (SvcLogicGraph graph : graphs) { + + try { + LOGGER.info("Saving " + graph.toString() + " to database."); + store.store(graph); + } catch (Exception e) { + throw new SvcLogicException(e.getMessage(), e); + } + + } + + } + + public static void validate(String xmlfile, SvcLogicStore store) throws SvcLogicException { + if (!PathValidator.isValidXmlPath(xmlfile)) { + throw new ConfigurationException("Invalid xml file name ("+ xmlfile + ")"); + } + File xmlFile = new File(xmlfile); + if (!xmlFile.canRead()) { + throw new ConfigurationException("Cannot read xml file (" + xmlfile + ")"); + } + + SvcLogicParser parser = new SvcLogicParser(); + LinkedList<SvcLogicGraph> graphs; + try { + LOGGER.info("Validating {}", xmlfile); + graphs = parser.parse(xmlfile); + } catch (Exception e) { + throw new SvcLogicException(e.getMessage(), e); + } + + if (graphs == null) { + throw new SvcLogicException("Could not parse " + xmlfile); + } else { + LOGGER.info("Compilation successful for {}", xmlfile); + } + + } + + private static void print(String module, String rpc, String mode, String version, SvcLogicStore store) { + String details = "(module:" + module + ", rpc:" + rpc + ", version:" + version + ", mode:" + mode + ")"; + + try { + LOGGER.info(LOAD_MESSAGE, details); + + SvcLogicGraph graph = store.fetch(module, rpc, version, mode); + if (graph == null) { + LOGGER.error(LOAD_ERROR_MESSAGE, details); + System.exit(1); + } + graph.printAsGv(System.out); + } catch (Exception e) { + LOGGER.error(PRINT_ERROR_MESSAGE, details, e); + System.exit(1); + } + + } + + private static void getSource(String module, String rpc, String mode, String version, SvcLogicStore store) { + String details = "(module:" + module + ", rpc:" + rpc + ", version:" + version + ", mode:" + mode + ")"; + + try { + LOGGER.info(LOAD_MESSAGE, details); + + SvcLogicGraph graph = store.fetch(module, rpc, version, mode); + if (graph == null) { + LOGGER.error(LOAD_ERROR_MESSAGE, details); + System.exit(1); + } + graph.printAsXml(System.out); + } catch (Exception e) { + LOGGER.error(PRINT_ERROR_MESSAGE, details, e); + System.exit(1); + } + + } + + public static void activate(String module, String rpc, String version, String mode, SvcLogicStore store) { + String details = "(module:" + module + ", rpc:" + rpc + ", version:" + version + ", mode:" + mode + ")"; + + try { + LOGGER.info(LOAD_MESSAGE, details); + + SvcLogicGraph graph = store.fetch(module, rpc, version, mode); + if (graph == null) { + LOGGER.error(LOAD_ERROR_MESSAGE, details); + System.exit(1); + } + store.activate(graph); + } catch (Exception e) { + LOGGER.error(ACTIVATION_ERROR_MESSAGE, details, e); + System.exit(1); + } + + } + + private static void usage() { + System.err.println("Usage: SvcLogicParser load <xml-file> <prop-file>"); + System.err.println(" OR SvcLogicParser print <module> <rpc> <mode> [<version>] <prop-file>"); + System.err.println(" OR SvcLogicParser get-source <module> <rpc> <mode> <version> <prop-file>"); + System.err.println(" OR SvcLogicParser activate <module> <rpc> <version> <mode>"); + System.err.println(" OR SvcLogicParser validate <file path to graph> <prop-file>"); + System.err.println(" OR SvcLogicParser install <service-logic directory path> <prop-file>"); + System.err.println(" OR SvcLogicParser bulkActivate <path to activation file> <prop-file>"); + System.exit(1); + } + + protected SAXParser initParser() throws ParserConfigurationException, SAXException { + URL xsdUrl = null; + Schema schema = null; + String validateSchema = System.getProperty(SLI_VALIDATING_PARSER, "true"); + + if ("true".equalsIgnoreCase(validateSchema)) { + xsdUrl = getClass().getResource(SVCLOGIC_XSD); + } + + if (xsdUrl != null) { + try { + SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI); + schema = schemaFactory.newSchema(xsdUrl); + LOGGER.info("Schema path {}", xsdUrl.getPath()); + } catch (Exception e) { + LOGGER.warn("Could not validate using schema {}", xsdUrl.getPath(), e); + } + } else { + LOGGER.warn("Could not find resource {}", SVCLOGIC_XSD); + } + + SAXParserFactory factory = SAXParserFactory.newInstance(); + + if (schema != null) { + factory.setNamespaceAware(true); + factory.setSchema(schema); + } + + SAXParser saxParser = factory.newSAXParser(); + if (saxParser.isValidating()) { + LOGGER.info("Parser configured to validate XML {}", (xsdUrl != null ? xsdUrl.getPath() : null)); + } + return saxParser; + } + + +} diff --git a/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicParserException.java b/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicParserException.java new file mode 100644 index 000000000..61f80f7e2 --- /dev/null +++ b/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicParserException.java @@ -0,0 +1,43 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP : CCSDK + * ================================================================================ + * 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.onap.ccsdk.sli.core.sli; + +import java.io.IOException; + +public class SvcLogicParserException extends IOException { + + public SvcLogicParserException() { + super(); + } + + public SvcLogicParserException(String msg) { + super(msg); + } + + public SvcLogicParserException(Throwable t) { + super(t); + } + + public SvcLogicParserException(String msg, Throwable t) { + super(msg, t); + } +} diff --git a/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicRecorder.java b/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicRecorder.java new file mode 100644 index 000000000..ca13536bb --- /dev/null +++ b/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicRecorder.java @@ -0,0 +1,30 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP : CCSDK + * ================================================================================ + * 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.onap.ccsdk.sli.core.sli; + +import java.util.Map; + +public interface SvcLogicRecorder { + + void record(Map<String, String> parmMap) throws SvcLogicException; + +} diff --git a/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicResource.java b/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicResource.java new file mode 100644 index 000000000..0e2c42574 --- /dev/null +++ b/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicResource.java @@ -0,0 +1,52 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP : CCSDK + * ================================================================================ + * 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.onap.ccsdk.sli.core.sli; + +import java.util.Map; + +public interface SvcLogicResource { + + public enum QueryStatus { + SUCCESS, + NOT_FOUND, + FAILURE + } + + public QueryStatus isAvailable(String resource, String key, String prefix, SvcLogicContext ctx) throws SvcLogicException; + + public QueryStatus exists(String resource, String key, String prefix, SvcLogicContext ctx) throws SvcLogicException; + + public QueryStatus query(String resource, boolean localOnly, String select, String key, String prefix, String orderBy, SvcLogicContext ctx) throws SvcLogicException; + + public QueryStatus reserve(String resource, String select, String key, String prefix, SvcLogicContext ctx) throws SvcLogicException; + + public QueryStatus save(String resource, boolean force, boolean localOnly, String key, Map<String, String> parms, String prefix, SvcLogicContext ctx) throws SvcLogicException; + + public QueryStatus release(String resource, String key, SvcLogicContext ctx) throws SvcLogicException; + + public QueryStatus delete(String resource, String key, SvcLogicContext ctx) throws SvcLogicException; + + public QueryStatus notify(String resource, String action, String key, SvcLogicContext ctx) throws SvcLogicException; + + public QueryStatus update(String resource, String key, Map<String, String> parms, String prefix, SvcLogicContext ctx) throws SvcLogicException; + +} diff --git a/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicStore.java b/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicStore.java new file mode 100644 index 000000000..2eda67f11 --- /dev/null +++ b/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicStore.java @@ -0,0 +1,36 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP : CCSDK + * ================================================================================ + * 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.onap.ccsdk.sli.core.sli; + +import java.util.Properties; + +public interface SvcLogicStore { + + public void init(Properties props) throws SvcLogicException; + public boolean hasGraph(String module, String rpc, String version, String mode) throws SvcLogicException; + public SvcLogicGraph fetch(String module, String rpc, String version, String mode) throws SvcLogicException; + public void store(SvcLogicGraph graph) throws SvcLogicException; + public void delete(String module, String rpc, String version, String mode) throws SvcLogicException; + public void activate(SvcLogicGraph graph) throws SvcLogicException; + public void activate(String module, String rpc, String version, String mode) throws SvcLogicException; + +} diff --git a/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicStoreFactory.java b/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicStoreFactory.java new file mode 100644 index 000000000..e0eb57304 --- /dev/null +++ b/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicStoreFactory.java @@ -0,0 +1,100 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP : CCSDK + * ================================================================================ + * 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.onap.ccsdk.sli.core.sli; + +import java.io.File; +import java.io.FileInputStream; +import java.io.InputStream; +import java.util.Properties; +import org.onap.ccsdk.sli.core.dblib.DBResourceManager; +import org.onap.ccsdk.sli.core.utils.PathValidator; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class SvcLogicStoreFactory { + + private static final Logger LOG = LoggerFactory.getLogger(SvcLogicStoreFactory.class); + + public static SvcLogicStore getSvcLogicStore(String propfile) + throws SvcLogicException { + if (!PathValidator.isValidPropertiesPath(propfile)) { + throw new ConfigurationException("Invalid property file name ("+propfile+")"); + } + File propFile = new File(propfile); + if (!propFile.canRead()) { + throw new ConfigurationException("Cannot read property file " + + propfile); + + } + + try { + return getSvcLogicStore(new FileInputStream(propFile)); + } catch (Exception e) { + throw new ConfigurationException( + "Could load service store from properties file " + propfile, + e); + } + + } + + public static SvcLogicStore getSvcLogicStore(InputStream inStr) throws SvcLogicException + { + Properties props = new Properties(); + + try { + props.load(inStr); + } catch (Exception e) { + throw new ConfigurationException("Could not get load properties from input stream", e); + } + + return getSvcLogicStore(props); + } + + public static SvcLogicStore getSvcLogicStore(Properties props) + throws SvcLogicException { + String storeType = props.getProperty("org.onap.ccsdk.sli.dbtype"); + if ((storeType == null) || (storeType.length() == 0)) { + throw new ConfigurationException( + "property org.onap.ccsdk.sli.dbtype unset"); + + } + + SvcLogicStore retval; + LOG.debug("Using org.onap.ccsdk.sli.dbtype={}", storeType); + + if ("jdbc".equalsIgnoreCase(storeType)) { + retval = new SvcLogicJdbcStore(); + + } else if ("dblib".equalsIgnoreCase(storeType)) { + retval = new SvcLogicDblibStore(new DBResourceManager(props)); + } else { + throw new ConfigurationException("unsupported dbtype (" + storeType + + ")"); + + } + + + retval.init(props); + return retval; + } + +} diff --git a/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicVariableTerm.java b/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicVariableTerm.java new file mode 100644 index 000000000..4edf3ecbe --- /dev/null +++ b/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicVariableTerm.java @@ -0,0 +1,77 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP : CCSDK + * ================================================================================ + * 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.onap.ccsdk.sli.core.sli; + +public class SvcLogicVariableTerm extends SvcLogicExpression { + + private String name = null; + + public String getName() { + return name; + } + + + public SvcLogicVariableTerm(String identifier) + { + this.name = identifier; + } + + public SvcLogicExpression getSubscript() + { + if (numOperands() > 0) + { + return(getOperands().get(0)); + } + else + { + return(null); + } + } + + @Override + public String toString() + { + String retval; + + if (numOperands() > 0) + { + retval = name + "[" + getSubscript().toString() + "]"; + } + else + { + retval = name; + } + return(retval); + } + + @Override + public String asParsedExpr() { + if (numOperands() == 0) { + return("(variable-term "+name+")"); + } + else + { + return("(variable-term "+name+" "+getSubscript().asParsedExpr()+")"); + } + } + +} |