From 49e1a61bf58185149d9879447180e9c5c2790111 Mon Sep 17 00:00:00 2001 From: Edson Tirelli Date: Mon, 12 May 2014 20:52:32 -0400 Subject: [PATCH] DROOLS-494: implementing execution server --- kie-server/.gitignore | 31 ++ kie-server/kie-server-api/.gitignore | 31 ++ kie-server/kie-server-api/pom.xml | 75 +++ .../filtered-resources/kie.server.properties | 1 + .../kie/server/api/KieServerEnvironment.java | 55 ++ .../main/java/org/kie/server/api/Version.java | 73 +++ .../api/commands/CallContainerCommand.java | 53 ++ .../server/api/commands/CommandScript.java | 84 +++ .../api/commands/CreateContainerCommand.java | 66 +++ .../api/commands/DisposeContainerCommand.java | 34 ++ .../api/commands/ListContainersCommand.java | 18 + .../api/model/KieContainerResource.java | 124 +++++ .../api/model/KieContainerResourceList.java | 35 ++ .../server/api/model/KieContainerStatus.java | 5 + .../server/api/model/KieScannerResource.java | 75 +++ .../server/api/model/KieScannerStatus.java | 8 + .../server/api/model/KieServerCommand.java | 10 + .../kie/server/api/model/KieServerInfo.java | 32 ++ .../org/kie/server/api/model/ReleaseId.java | 74 +++ .../kie/server/api/model/ServiceResponse.java | 73 +++ kie-server/kie-server-client/.gitignore | 31 ++ kie-server/kie-server-client/pom.xml | 40 ++ .../kie/server/client/KieServicesClient.java | 172 +++++++ kie-server/kie-server-services/.gitignore | 31 ++ kie-server/kie-server-services/pom.xml | 152 ++++++ .../server/services/KieServerApplication.java | 34 ++ .../kie/server/services/api/KieServer.java | 68 +++ .../services/impl/KieContainerInstance.java | 74 +++ .../services/impl/KieContainersRegistry.java | 36 ++ .../server/services/impl/KieServerImpl.java | 485 ++++++++++++++++++ .../kie/server/services/impl/XStreamXml.java | 133 +++++ .../adapters/ExecutionResultsAdapter.java | 21 + .../src/main/resources/applicationContext.xml | 17 + .../src/main/webapp/WEB-INF/web.xml | 32 ++ .../org/kie/server/impl/KieServerTest.java | 351 +++++++++++++ kie-server/pom.xml | 54 ++ 36 files changed, 2688 insertions(+) create mode 100644 kie-server/.gitignore create mode 100644 kie-server/kie-server-api/.gitignore create mode 100644 kie-server/kie-server-api/pom.xml create mode 100644 kie-server/kie-server-api/src/main/filtered-resources/kie.server.properties create mode 100644 kie-server/kie-server-api/src/main/java/org/kie/server/api/KieServerEnvironment.java create mode 100644 kie-server/kie-server-api/src/main/java/org/kie/server/api/Version.java create mode 100644 kie-server/kie-server-api/src/main/java/org/kie/server/api/commands/CallContainerCommand.java create mode 100644 kie-server/kie-server-api/src/main/java/org/kie/server/api/commands/CommandScript.java create mode 100644 kie-server/kie-server-api/src/main/java/org/kie/server/api/commands/CreateContainerCommand.java create mode 100644 kie-server/kie-server-api/src/main/java/org/kie/server/api/commands/DisposeContainerCommand.java create mode 100644 kie-server/kie-server-api/src/main/java/org/kie/server/api/commands/ListContainersCommand.java create mode 100644 kie-server/kie-server-api/src/main/java/org/kie/server/api/model/KieContainerResource.java create mode 100644 kie-server/kie-server-api/src/main/java/org/kie/server/api/model/KieContainerResourceList.java create mode 100644 kie-server/kie-server-api/src/main/java/org/kie/server/api/model/KieContainerStatus.java create mode 100644 kie-server/kie-server-api/src/main/java/org/kie/server/api/model/KieScannerResource.java create mode 100644 kie-server/kie-server-api/src/main/java/org/kie/server/api/model/KieScannerStatus.java create mode 100644 kie-server/kie-server-api/src/main/java/org/kie/server/api/model/KieServerCommand.java create mode 100644 kie-server/kie-server-api/src/main/java/org/kie/server/api/model/KieServerInfo.java create mode 100644 kie-server/kie-server-api/src/main/java/org/kie/server/api/model/ReleaseId.java create mode 100644 kie-server/kie-server-api/src/main/java/org/kie/server/api/model/ServiceResponse.java create mode 100644 kie-server/kie-server-client/.gitignore create mode 100644 kie-server/kie-server-client/pom.xml create mode 100644 kie-server/kie-server-client/src/main/java/org/kie/server/client/KieServicesClient.java create mode 100644 kie-server/kie-server-services/.gitignore create mode 100644 kie-server/kie-server-services/pom.xml create mode 100644 kie-server/kie-server-services/src/main/java/org/kie/server/services/KieServerApplication.java create mode 100644 kie-server/kie-server-services/src/main/java/org/kie/server/services/api/KieServer.java create mode 100644 kie-server/kie-server-services/src/main/java/org/kie/server/services/impl/KieContainerInstance.java create mode 100644 kie-server/kie-server-services/src/main/java/org/kie/server/services/impl/KieContainersRegistry.java create mode 100644 kie-server/kie-server-services/src/main/java/org/kie/server/services/impl/KieServerImpl.java create mode 100644 kie-server/kie-server-services/src/main/java/org/kie/server/services/impl/XStreamXml.java create mode 100644 kie-server/kie-server-services/src/main/java/org/kie/server/services/impl/adapters/ExecutionResultsAdapter.java create mode 100644 kie-server/kie-server-services/src/main/resources/applicationContext.xml create mode 100644 kie-server/kie-server-services/src/main/webapp/WEB-INF/web.xml create mode 100644 kie-server/kie-server-services/src/test/java/org/kie/server/impl/KieServerTest.java create mode 100644 kie-server/pom.xml diff --git a/kie-server/.gitignore b/kie-server/.gitignore new file mode 100644 index 0000000000..4e841117e9 --- /dev/null +++ b/kie-server/.gitignore @@ -0,0 +1,31 @@ +/target +/local + +# Eclipse, Netbeans and IntelliJ files +/.* +!.gitignore +/nbproject +/*.ipr +/*.iws +/*.iml + +# Repository wide ignore mac DS_Store files +.DS_Store + +# Original jbpm ignores +bin/ +*~ +*.tlog + +# Test info +/settings*.xml +/lib-jdbc/ +bitronix-default-config.properties +*.db + +# modules that don't exist in this branch +/jbpm-human-task-war/ + +# files used for external db testing +jdbc_driver.jar +db-settings.xml diff --git a/kie-server/kie-server-api/.gitignore b/kie-server/kie-server-api/.gitignore new file mode 100644 index 0000000000..4e841117e9 --- /dev/null +++ b/kie-server/kie-server-api/.gitignore @@ -0,0 +1,31 @@ +/target +/local + +# Eclipse, Netbeans and IntelliJ files +/.* +!.gitignore +/nbproject +/*.ipr +/*.iws +/*.iml + +# Repository wide ignore mac DS_Store files +.DS_Store + +# Original jbpm ignores +bin/ +*~ +*.tlog + +# Test info +/settings*.xml +/lib-jdbc/ +bitronix-default-config.properties +*.db + +# modules that don't exist in this branch +/jbpm-human-task-war/ + +# files used for external db testing +jdbc_driver.jar +db-settings.xml diff --git a/kie-server/kie-server-api/pom.xml b/kie-server/kie-server-api/pom.xml new file mode 100644 index 0000000000..4beac51e9f --- /dev/null +++ b/kie-server/kie-server-api/pom.xml @@ -0,0 +1,75 @@ + + 4.0.0 + + org.kie + kie-server + 6.2.0-SNAPSHOT + + + kie-server-api + jar + + KIE :: Execution Server :: API + KIE Execution Server API + + + + + org.kie + kie-api + + + + + + + + + src/main/resources + + + true + src/main/filtered-resources + + + + + + maven-eclipse-plugin + + + + org.eclipse.ui.externaltools.ExternalToolBuilder + auto,full,incremental, + + <project>/.externalToolBuilders/mvn-resources.launch + + + + + + .externalToolBuilders/mvn-resources.launch + + + + + + + + + + + +]]> + + + + + + + + + + + diff --git a/kie-server/kie-server-api/src/main/filtered-resources/kie.server.properties b/kie-server/kie-server-api/src/main/filtered-resources/kie.server.properties new file mode 100644 index 0000000000..129cd2cd3d --- /dev/null +++ b/kie-server/kie-server-api/src/main/filtered-resources/kie.server.properties @@ -0,0 +1 @@ +kie.server.version=${project.version} \ No newline at end of file diff --git a/kie-server/kie-server-api/src/main/java/org/kie/server/api/KieServerEnvironment.java b/kie-server/kie-server-api/src/main/java/org/kie/server/api/KieServerEnvironment.java new file mode 100644 index 0000000000..c3be25e974 --- /dev/null +++ b/kie-server/kie-server-api/src/main/java/org/kie/server/api/KieServerEnvironment.java @@ -0,0 +1,55 @@ +package org.kie.server.api; + +import java.io.IOException; +import java.io.InputStream; +import java.util.Properties; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + + +public class KieServerEnvironment { + + private static final Pattern VERSION_PAT = Pattern.compile("(\\d+)\\.(\\d+)\\.(\\d+)([\\.-].*)?"); + private static Version version; + + static { + String kieServerString = KieServerEnvironment.class.getPackage().getImplementationVersion(); + if (kieServerString == null) { + InputStream is = null; + try { + is = KieServerEnvironment.class.getClassLoader().getResourceAsStream("kie.server.properties"); + Properties properties = new Properties(); + properties.load(is); + kieServerString = properties.get("kie.server.version").toString(); + is.close(); + } catch ( IOException e ) { + throw new RuntimeException(e); + } finally { + if (is != null) { + try { + is.close(); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + } + } + + Matcher m = VERSION_PAT.matcher(kieServerString); + if( m.matches() ) { + try { + version = new Version( Integer.parseInt(m.group(1)), + Integer.parseInt(m.group(2)), + Integer.parseInt(m.group(3)), + m.group(4) ); + } catch (NumberFormatException e) { + version = new Version(0,0,0,null); + } + } + } + + public static Version getVersion() { + return version; + } + +} diff --git a/kie-server/kie-server-api/src/main/java/org/kie/server/api/Version.java b/kie-server/kie-server-api/src/main/java/org/kie/server/api/Version.java new file mode 100644 index 0000000000..33f676e8f6 --- /dev/null +++ b/kie-server/kie-server-api/src/main/java/org/kie/server/api/Version.java @@ -0,0 +1,73 @@ +package org.kie.server.api; + +public class Version { + + private final int major; + private final int minor; + private final int revision; + private final String classifier; + + public Version(int major, int minor, int revision, String classifier) { + super(); + this.major = major; + this.minor = minor; + this.revision = revision; + this.classifier = classifier; + } + + public int getMajor() { + return major; + } + + public int getMinor() { + return minor; + } + + public int getRevision() { + return revision; + } + + public String getClassifier() { + return classifier; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((classifier == null) ? 0 : classifier.hashCode()); + result = prime * result + major; + result = prime * result + minor; + result = prime * result + revision; + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + Version other = (Version) obj; + if (classifier == null) { + if (other.classifier != null) + return false; + } else if (!classifier.equals(other.classifier)) + return false; + if (major != other.major) + return false; + if (minor != other.minor) + return false; + if (revision != other.revision) + return false; + return true; + } + + @Override + public String toString() { + return major + "." + minor + "." + revision + (classifier != null ? classifier : ""); + } + +} diff --git a/kie-server/kie-server-api/src/main/java/org/kie/server/api/commands/CallContainerCommand.java b/kie-server/kie-server-api/src/main/java/org/kie/server/api/commands/CallContainerCommand.java new file mode 100644 index 0000000000..146b62188c --- /dev/null +++ b/kie-server/kie-server-api/src/main/java/org/kie/server/api/commands/CallContainerCommand.java @@ -0,0 +1,53 @@ +package org.kie.server.api.commands; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlAttribute; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; + +import org.kie.server.api.model.KieServerCommand; + +@XmlRootElement(name = "call-container") +@XmlAccessorType(XmlAccessType.NONE) +public class CallContainerCommand implements KieServerCommand { + + private static final long serialVersionUID = -1803374525440238478L; + + @XmlAttribute(name = "container-id") + private String containerId; + + @XmlElement(name = "payload") + private String payload; + + public CallContainerCommand() { + super(); + } + + public CallContainerCommand(String containerId, String cmdPayload) { + this.containerId = containerId; + this.payload = cmdPayload; + } + + public String getContainerId() { + return containerId; + } + + public void setContainerId(String containerId) { + this.containerId = containerId; + } + + public String getPayload() { + return payload; + } + + public void setPayload(String payload) { + this.payload = payload; + } + + @Override + public String toString() { + return "CallContainerCommand [containerId=" + containerId + ", payload=" + payload + "]"; + } + +} diff --git a/kie-server/kie-server-api/src/main/java/org/kie/server/api/commands/CommandScript.java b/kie-server/kie-server-api/src/main/java/org/kie/server/api/commands/CommandScript.java new file mode 100644 index 0000000000..26146823af --- /dev/null +++ b/kie-server/kie-server-api/src/main/java/org/kie/server/api/commands/CommandScript.java @@ -0,0 +1,84 @@ +/* + * Copyright 2010 JBoss Inc + * + * 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. + */ + +package org.kie.server.api.commands; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlAttribute; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlElements; +import javax.xml.bind.annotation.XmlRootElement; +import javax.xml.bind.annotation.XmlType; + +import org.kie.server.api.model.KieServerCommand; + +@XmlRootElement(name = "script") +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "script", propOrder = {"lookup", "commands"}) +public class CommandScript implements Serializable { + + private static final long serialVersionUID = 510l; + + @XmlAttribute + private String lookup; + + @XmlElements({ + @XmlElement(name = "create-container", type = CreateContainerCommand.class), + @XmlElement(name = "list-containers", type = ListContainersCommand.class), + @XmlElement(name = "dispose-container", type = DisposeContainerCommand.class), + @XmlElement(name = "call-container", type = CallContainerCommand.class) + }) + protected List commands; + + public CommandScript() { + } + + public CommandScript(List commands) { + this.commands = commands; + } + + public CommandScript(List commands, String lookup) { + this.commands = commands; + this.lookup = lookup; + } + + public List getCommands() { + if (commands == null) { + commands = new ArrayList(); + } + return this.commands; + } + + public void setLookup(String lookup) { + this.lookup = lookup; + } + + public String getLookup() { + return lookup; + } + + public String toString() { + return "CommandScriptImpl{" + + "lookup='" + lookup + '\'' + + ", commands=" + commands + + '}'; + } +} diff --git a/kie-server/kie-server-api/src/main/java/org/kie/server/api/commands/CreateContainerCommand.java b/kie-server/kie-server-api/src/main/java/org/kie/server/api/commands/CreateContainerCommand.java new file mode 100644 index 0000000000..caa644dc58 --- /dev/null +++ b/kie-server/kie-server-api/src/main/java/org/kie/server/api/commands/CreateContainerCommand.java @@ -0,0 +1,66 @@ +package org.kie.server.api.commands; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; + +import org.kie.server.api.model.KieContainerResource; +import org.kie.server.api.model.KieServerCommand; + +@XmlRootElement(name = "create-container") +@XmlAccessorType(XmlAccessType.NONE) +public class CreateContainerCommand implements KieServerCommand { + + private static final long serialVersionUID = -1803374525440238478L; + + @XmlElement + private KieContainerResource container; + + public CreateContainerCommand() { + super(); + } + + public CreateContainerCommand(KieContainerResource container) { + this.container = container; + } + + public KieContainerResource getContainer() { + return container; + } + + public void setContainer(KieContainerResource container) { + this.container = container; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((container == null) ? 0 : container.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + CreateContainerCommand other = (CreateContainerCommand) obj; + if (container == null) { + if (other.container != null) + return false; + } else if (!container.equals(other.container)) + return false; + return true; + } + + @Override + public String toString() { + return "CreateContainerCommand [container=" + container + "]"; + } + +} diff --git a/kie-server/kie-server-api/src/main/java/org/kie/server/api/commands/DisposeContainerCommand.java b/kie-server/kie-server-api/src/main/java/org/kie/server/api/commands/DisposeContainerCommand.java new file mode 100644 index 0000000000..96fe5f57ca --- /dev/null +++ b/kie-server/kie-server-api/src/main/java/org/kie/server/api/commands/DisposeContainerCommand.java @@ -0,0 +1,34 @@ +package org.kie.server.api.commands; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlAttribute; +import javax.xml.bind.annotation.XmlRootElement; + +import org.kie.server.api.model.KieServerCommand; + +@XmlRootElement(name="dispose-container") +@XmlAccessorType(XmlAccessType.NONE) +public class DisposeContainerCommand implements KieServerCommand { + private static final long serialVersionUID = -1803374525440238478L; + + @XmlAttribute(name="container-id") + private String containerId; + + public DisposeContainerCommand() { + super(); + } + + public DisposeContainerCommand(String containerId) { + this.containerId = containerId; + } + + public String getContainerId() { + return containerId; + } + + public void setContainerId(String containerId) { + this.containerId = containerId; + } + +} diff --git a/kie-server/kie-server-api/src/main/java/org/kie/server/api/commands/ListContainersCommand.java b/kie-server/kie-server-api/src/main/java/org/kie/server/api/commands/ListContainersCommand.java new file mode 100644 index 0000000000..33c05e1537 --- /dev/null +++ b/kie-server/kie-server-api/src/main/java/org/kie/server/api/commands/ListContainersCommand.java @@ -0,0 +1,18 @@ +package org.kie.server.api.commands; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlRootElement; + +import org.kie.server.api.model.KieServerCommand; + +@XmlRootElement(name="list-containers") +@XmlAccessorType(XmlAccessType.NONE) +public class ListContainersCommand implements KieServerCommand { + private static final long serialVersionUID = -1803374525440238478L; + + public ListContainersCommand() { + super(); + } + +} diff --git a/kie-server/kie-server-api/src/main/java/org/kie/server/api/model/KieContainerResource.java b/kie-server/kie-server-api/src/main/java/org/kie/server/api/model/KieContainerResource.java new file mode 100644 index 0000000000..70dbc3814c --- /dev/null +++ b/kie-server/kie-server-api/src/main/java/org/kie/server/api/model/KieContainerResource.java @@ -0,0 +1,124 @@ +package org.kie.server.api.model; + +import javax.xml.bind.annotation.XmlAttribute; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; + +@XmlRootElement(name = "kie-container") +public class KieContainerResource { + + private String containerId; + private ReleaseId releaseId; + private ReleaseId resolvedReleaseId; + private KieContainerStatus status; + private KieScannerResource scanner; + + public KieContainerResource() { + } + + public KieContainerResource(String containerId, ReleaseId releaseId) { + this( containerId, releaseId, null, null ); + } + + public KieContainerResource(String containerId, ReleaseId releaseId, KieContainerStatus status) { + this( containerId, releaseId, null, status ); + } + + public KieContainerResource(String containerId, ReleaseId releaseId, ReleaseId resolvedReleaseId, KieContainerStatus status) { + this.containerId = containerId; + this.releaseId = releaseId; + this.resolvedReleaseId = resolvedReleaseId; + this.status = status; + } + + @XmlAttribute(name = "container-id") + public String getContainerId() { + return containerId; + } + + public void setContainerId(String containerId) { + this.containerId = containerId; + } + + @XmlAttribute(name = "status") + public KieContainerStatus getStatus() { + return status; + } + + public void setStatus(KieContainerStatus status) { + this.status = status; + } + + @XmlElement(name = "release-id") + public ReleaseId getReleaseId() { + return releaseId; + } + + public void setReleaseId(ReleaseId releaseId) { + this.releaseId = releaseId; + } + + @XmlElement(name = "resolved-release-id") + public ReleaseId getResolvedReleaseId() { + return resolvedReleaseId; + } + + public void setResolvedReleaseId(ReleaseId resolvedReleaseId) { + this.resolvedReleaseId = resolvedReleaseId; + } + + @XmlElement + public KieScannerResource getScanner() { + return scanner; + } + + public void setScanner(KieScannerResource scanner) { + this.scanner = scanner; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((containerId == null) ? 0 : containerId.hashCode()); + result = prime * result + ((releaseId == null) ? 0 : releaseId.hashCode()); + result = prime * result + ((resolvedReleaseId == null) ? 0 : resolvedReleaseId.hashCode()); + result = prime * result + ((status == null) ? 0 : status.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + KieContainerResource other = (KieContainerResource) obj; + if (containerId == null) { + if (other.containerId != null) + return false; + } else if (!containerId.equals(other.containerId)) + return false; + if (releaseId == null) { + if (other.releaseId != null) + return false; + } else if (!releaseId.equals(other.releaseId)) + return false; + if (resolvedReleaseId == null) { + if (other.resolvedReleaseId != null) + return false; + } else if (!resolvedReleaseId.equals(other.resolvedReleaseId)) + return false; + if (status != other.status) + return false; + return true; + } + + @Override + public String toString() { + return "KieContainerResource [containerId=" + containerId + ", releaseId=" + releaseId + ", resolvedReleaseId=" + resolvedReleaseId + ", status=" + status + "]"; + } + +} \ No newline at end of file diff --git a/kie-server/kie-server-api/src/main/java/org/kie/server/api/model/KieContainerResourceList.java b/kie-server/kie-server-api/src/main/java/org/kie/server/api/model/KieContainerResourceList.java new file mode 100644 index 0000000000..701b4cd1ec --- /dev/null +++ b/kie-server/kie-server-api/src/main/java/org/kie/server/api/model/KieContainerResourceList.java @@ -0,0 +1,35 @@ +package org.kie.server.api.model; + +import java.util.List; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; + + +@XmlRootElement(name="kie-containers") +@XmlAccessorType (XmlAccessType.FIELD) +public class KieContainerResourceList { + + @XmlElement + private List containers; + + public KieContainerResourceList() { + super(); + } + + public KieContainerResourceList(List containers) { + super(); + this.containers = containers; + } + + public List getContainers() { + return containers; + } + + public void setContainers(List containers) { + this.containers = containers; + } + +} diff --git a/kie-server/kie-server-api/src/main/java/org/kie/server/api/model/KieContainerStatus.java b/kie-server/kie-server-api/src/main/java/org/kie/server/api/model/KieContainerStatus.java new file mode 100644 index 0000000000..d4985e5534 --- /dev/null +++ b/kie-server/kie-server-api/src/main/java/org/kie/server/api/model/KieContainerStatus.java @@ -0,0 +1,5 @@ +package org.kie.server.api.model; + +public enum KieContainerStatus { + CREATING, STARTED, FAILED, DISPOSING +} \ No newline at end of file diff --git a/kie-server/kie-server-api/src/main/java/org/kie/server/api/model/KieScannerResource.java b/kie-server/kie-server-api/src/main/java/org/kie/server/api/model/KieScannerResource.java new file mode 100644 index 0000000000..72cf3775c0 --- /dev/null +++ b/kie-server/kie-server-api/src/main/java/org/kie/server/api/model/KieScannerResource.java @@ -0,0 +1,75 @@ +package org.kie.server.api.model; + +import javax.xml.bind.annotation.XmlAttribute; +import javax.xml.bind.annotation.XmlRootElement; + +@XmlRootElement(name = "kie-scanner") +public class KieScannerResource { + + private KieScannerStatus status; + private Long pollInterval; + + public KieScannerResource() { + } + + public KieScannerResource(KieScannerStatus status) { + this(status, null); + } + + public KieScannerResource(KieScannerStatus status, Long interval) { + this.status = status; + this.pollInterval = interval; + } + + @XmlAttribute(name = "status") + public KieScannerStatus getStatus() { + return status; + } + + public void setStatus(KieScannerStatus status) { + this.status = status; + } + + @XmlAttribute(name = "poll-interval") + public Long getPollInterval() { + return pollInterval; + } + + public void setPollInterval(Long pollInterval) { + this.pollInterval = pollInterval; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((pollInterval == null) ? 0 : pollInterval.hashCode()); + result = prime * result + ((status == null) ? 0 : status.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + KieScannerResource other = (KieScannerResource) obj; + if (pollInterval == null) { + if (other.pollInterval != null) + return false; + } else if (!pollInterval.equals(other.pollInterval)) + return false; + if (status != other.status) + return false; + return true; + } + + @Override + public String toString() { + return "KieScannerResource [status=" + status + ", pollInterval=" + pollInterval + "]"; + } + +} \ No newline at end of file diff --git a/kie-server/kie-server-api/src/main/java/org/kie/server/api/model/KieScannerStatus.java b/kie-server/kie-server-api/src/main/java/org/kie/server/api/model/KieScannerStatus.java new file mode 100644 index 0000000000..2178a108b1 --- /dev/null +++ b/kie-server/kie-server-api/src/main/java/org/kie/server/api/model/KieScannerStatus.java @@ -0,0 +1,8 @@ +package org.kie.server.api.model; + + +public enum KieScannerStatus { + + UNKNOWN, CREATED, STARTED, SCANNING, STOPPED, DISPOSED + +} diff --git a/kie-server/kie-server-api/src/main/java/org/kie/server/api/model/KieServerCommand.java b/kie-server/kie-server-api/src/main/java/org/kie/server/api/model/KieServerCommand.java new file mode 100644 index 0000000000..f29591df89 --- /dev/null +++ b/kie-server/kie-server-api/src/main/java/org/kie/server/api/model/KieServerCommand.java @@ -0,0 +1,10 @@ +package org.kie.server.api.model; + +import javax.xml.bind.annotation.XmlRootElement; + +import org.kie.api.command.Command; + +@XmlRootElement +public interface KieServerCommand extends Command { + +} diff --git a/kie-server/kie-server-api/src/main/java/org/kie/server/api/model/KieServerInfo.java b/kie-server/kie-server-api/src/main/java/org/kie/server/api/model/KieServerInfo.java new file mode 100644 index 0000000000..87b85c9be1 --- /dev/null +++ b/kie-server/kie-server-api/src/main/java/org/kie/server/api/model/KieServerInfo.java @@ -0,0 +1,32 @@ +package org.kie.server.api.model; + +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; + +@XmlRootElement(name="kie-server-info") +public class KieServerInfo { + private String version; + + public KieServerInfo() { + super(); + } + + public KieServerInfo(String version) { + super(); + this.version = version; + } + + @XmlElement(name="version") + public String getVersion() { + return version; + } + + public void setVersion(String version) { + this.version = version; + } + + @Override + public String toString() { + return "KieServerInfo [version=" + version + "]"; + } +} diff --git a/kie-server/kie-server-api/src/main/java/org/kie/server/api/model/ReleaseId.java b/kie-server/kie-server-api/src/main/java/org/kie/server/api/model/ReleaseId.java new file mode 100644 index 0000000000..dbd656af33 --- /dev/null +++ b/kie-server/kie-server-api/src/main/java/org/kie/server/api/model/ReleaseId.java @@ -0,0 +1,74 @@ +package org.kie.server.api.model; + +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; + +/** + * This is a JAXB friendly ReleaseId implementation + * used for JAXB marshalling/unmarshalling only + */ +@XmlRootElement +public class ReleaseId implements org.kie.api.builder.ReleaseId { + + private String groupId; + private String artifactId; + private String version; + + public ReleaseId() { + super(); + } + + public ReleaseId( org.kie.api.builder.ReleaseId releaseId ) { + this( releaseId.getGroupId(), releaseId.getArtifactId(), releaseId.getVersion() ); + } + + public ReleaseId(String groupId, String artifactId, String version) { + super(); + this.groupId = groupId; + this.artifactId = artifactId; + this.version = version; + } + + @XmlElement(required = true, name = "group-id") + public String getGroupId() { + return groupId; + } + + public void setGroupId(String groupId) { + this.groupId = groupId; + } + + @XmlElement(required = true, name = "artifact-id") + public String getArtifactId() { + return artifactId; + } + + public void setArtifactId(String artifactId) { + this.artifactId = artifactId; + } + + @XmlElement(required = true, name = "version") + public String getVersion() { + return version; + } + + public void setVersion(String version) { + this.version = version; + } + + public boolean isSnapshot() { + return version.endsWith("-SNAPSHOT"); + } + + public String toExternalForm() { + return groupId + ":" + artifactId + ":" + version; + } + + @Override + public String toString() { + return toExternalForm(); + } + + + +} diff --git a/kie-server/kie-server-api/src/main/java/org/kie/server/api/model/ServiceResponse.java b/kie-server/kie-server-api/src/main/java/org/kie/server/api/model/ServiceResponse.java new file mode 100644 index 0000000000..eccaef0010 --- /dev/null +++ b/kie-server/kie-server-api/src/main/java/org/kie/server/api/model/ServiceResponse.java @@ -0,0 +1,73 @@ +package org.kie.server.api.model; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlAttribute; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlElements; +import javax.xml.bind.annotation.XmlRootElement; + +@XmlRootElement(name="response") +@XmlAccessorType(XmlAccessType.NONE) +public class ServiceResponse { + public static enum ResponseType { + SUCCESS, FAILURE; + } + + @XmlAttribute + private ServiceResponse.ResponseType type; + @XmlAttribute + private String msg; + @XmlElements({ + @XmlElement(name = "kie-server-info", type = KieServerInfo.class), + @XmlElement(name = "kie-container", type = KieContainerResource.class), + @XmlElement(name = "results", type = String.class), + @XmlElement(name = "kie-containers", type = KieContainerResourceList.class), + @XmlElement(name = "kie-scanner", type = KieScannerResource.class) + }) + private T result; + + + public ServiceResponse() { + } + + public ServiceResponse(ServiceResponse.ResponseType type, String msg) { + this.type = type; + this.msg = msg; + } + + public ServiceResponse(ServiceResponse.ResponseType type, String msg, T result ) { + this.type = type; + this.msg = msg; + this.result = result; + } + + public ServiceResponse.ResponseType getType() { + return type; + } + + public String getMsg() { + return msg; + } + + public void setType(ServiceResponse.ResponseType type) { + this.type = type; + } + + public void setMsg(String msg) { + this.msg = msg; + } + + public T getResult() { + return result; + } + + public void setResult(T result) { + this.result = result; + } + + @Override + public String toString() { + return "ServiceResponse[" + type + ", msg='" + msg + "']"; + } +} \ No newline at end of file diff --git a/kie-server/kie-server-client/.gitignore b/kie-server/kie-server-client/.gitignore new file mode 100644 index 0000000000..4e841117e9 --- /dev/null +++ b/kie-server/kie-server-client/.gitignore @@ -0,0 +1,31 @@ +/target +/local + +# Eclipse, Netbeans and IntelliJ files +/.* +!.gitignore +/nbproject +/*.ipr +/*.iws +/*.iml + +# Repository wide ignore mac DS_Store files +.DS_Store + +# Original jbpm ignores +bin/ +*~ +*.tlog + +# Test info +/settings*.xml +/lib-jdbc/ +bitronix-default-config.properties +*.db + +# modules that don't exist in this branch +/jbpm-human-task-war/ + +# files used for external db testing +jdbc_driver.jar +db-settings.xml diff --git a/kie-server/kie-server-client/pom.xml b/kie-server/kie-server-client/pom.xml new file mode 100644 index 0000000000..8b141139e8 --- /dev/null +++ b/kie-server/kie-server-client/pom.xml @@ -0,0 +1,40 @@ + + 4.0.0 + + org.kie + kie-server + 6.2.0-SNAPSHOT + + + kie-server-client + jar + + KIE :: Execution Server :: Client + KIE Execution Server Client + + + + + org.kie + kie-server-api + + + + + org.jboss.resteasy + resteasy-jaxrs + + + + org.jboss.resteasy + jaxrs-api + + + org.jboss.resteasy + resteasy-jaxb-provider + + + + + diff --git a/kie-server/kie-server-client/src/main/java/org/kie/server/client/KieServicesClient.java b/kie-server/kie-server-client/src/main/java/org/kie/server/client/KieServicesClient.java new file mode 100644 index 0000000000..08b77f6f8c --- /dev/null +++ b/kie-server/kie-server-client/src/main/java/org/kie/server/client/KieServicesClient.java @@ -0,0 +1,172 @@ +package org.kie.server.client; + +import java.util.List; + +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; + +import org.jboss.resteasy.client.ClientRequest; +import org.jboss.resteasy.client.ClientResponse; +import org.jboss.resteasy.client.ClientResponseFailure; +import org.jboss.resteasy.util.GenericType; +import org.kie.server.api.commands.CommandScript; +import org.kie.server.api.model.KieContainerResource; +import org.kie.server.api.model.KieContainerResourceList; +import org.kie.server.api.model.KieScannerResource; +import org.kie.server.api.model.KieServerInfo; +import org.kie.server.api.model.ServiceResponse; + + +public class KieServicesClient { + + private final String baseURI; + + public KieServicesClient(String baseURI) { + this.baseURI = baseURI; + } + + public ServiceResponse getServerInfo() throws ClientResponseFailure { + ClientResponse> response = null; + try { + ClientRequest clientRequest = new ClientRequest(baseURI); + response = clientRequest.get(new GenericType>(){}); + if( response.getStatus() == Response.Status.OK.getStatusCode() ) { + return response.getEntity(); + } + throw new ClientResponseFailure("Unexpected response code: "+response.getStatus(), response ); + } catch (ClientResponseFailure e) { + throw e; + } catch (Exception e) { + throw new ClientResponseFailure("Unexpected exception retrieving server info.", e, response ); + } + } + + public ServiceResponse listContainers() throws ClientResponseFailure { + ClientResponse> response = null; + try { + ClientRequest clientRequest = new ClientRequest(baseURI+"/containers"); + response = clientRequest.get(new GenericType>(){}); + if( response.getStatus() == Response.Status.OK.getStatusCode() ) { + return response.getEntity(); + } + throw new ClientResponseFailure("Unexpected response code: "+response.getStatus(), response ); + } catch (ClientResponseFailure e) { + throw e; + } catch (Exception e) { + throw new ClientResponseFailure("Unexpected exception retrieving list of containers.", e, response ); + } + } + + public ServiceResponse createContainer(String id, KieContainerResource resource) throws ClientResponseFailure { + ClientResponse> response = null; + try { + ClientRequest clientRequest = new ClientRequest(baseURI+"/containers/"+id); + response = clientRequest.body(MediaType.APPLICATION_XML_TYPE, resource).put(new GenericType>(){}); + if( response.getStatus() == Response.Status.CREATED.getStatusCode() ) { + return response.getEntity(); + } + throw new ClientResponseFailure("Unexpected response code: "+response.getStatus(), response ); + } catch (ClientResponseFailure e) { + throw e; + } catch (Exception e) { + throw new ClientResponseFailure("Unexpected exception creating container: "+id+" with release-id "+resource.getReleaseId(), e, response ); + } + } + + public ServiceResponse getContainerInfo(String id) throws ClientResponseFailure { + ClientResponse> response = null; + try { + ClientRequest clientRequest = new ClientRequest(baseURI+"/containers/"+id); + response = clientRequest.get(new GenericType>(){}); + if( response.getStatus() == Response.Status.OK.getStatusCode() ) { + return response.getEntity(); + } + throw new ClientResponseFailure("Unexpected response code: "+response.getStatus(), response ); + } catch (ClientResponseFailure e) { + throw e; + } catch (Exception e) { + throw new ClientResponseFailure("Unexpected exception retrieving container info.", e, response ); + } + } + + public ServiceResponse disposeContainer(String id) throws ClientResponseFailure { + ClientResponse> response = null; + try { + ClientRequest clientRequest = new ClientRequest(baseURI+"/containers/"+id); + response = clientRequest.delete(new GenericType>(){}); + if( response.getStatus() == Response.Status.OK.getStatusCode() ) { + return response.getEntity(); + } + throw new ClientResponseFailure("Unexpected response code: "+response.getStatus(), response ); + } catch (ClientResponseFailure e) { + throw e; + } catch (Exception e) { + throw new ClientResponseFailure("Unexpected exception disposing container: "+id, e, response ); + } + } + + public ServiceResponse executeCommands(String id, String payload) throws ClientResponseFailure { + ClientResponse> response = null; + try { + ClientRequest clientRequest = new ClientRequest(baseURI+"/containers/"+id); + response = clientRequest.body(MediaType.APPLICATION_XML_TYPE, payload).post(new GenericType>(){}); + if( response.getStatus() == Response.Status.OK.getStatusCode() ) { + return response.getEntity(); + } + throw new ClientResponseFailure("Unexpected response code: "+response.getStatus(), response ); + } catch (ClientResponseFailure e) { + throw e; + } catch (Exception e) { + throw new ClientResponseFailure("Unexpected exception executing commands on container "+id, e, response ); + } + } + + public List> executeScript(CommandScript script) throws ClientResponseFailure { + ClientResponse>> response = null; + try { + ClientRequest clientRequest = new ClientRequest(baseURI); + response = clientRequest.body(MediaType.APPLICATION_XML_TYPE, script).post(new GenericType>>() {}); + if( response.getStatus() == Response.Status.OK.getStatusCode() ) { + return response.getEntity(); + } + throw new ClientResponseFailure("Unexpected response code: "+response.getStatus(), response ); + } catch (ClientResponseFailure e) { + throw e; + } catch (Exception e) { + throw new ClientResponseFailure("Unexpected exception retrieving server info.", e, response ); + } + } + + public ServiceResponse getScannerInfo( String id ) { + ClientResponse> response = null; + try { + ClientRequest clientRequest = new ClientRequest(baseURI+"/containers/"+id+"/scanner"); + response = clientRequest.get(new GenericType>(){}); + if( response.getStatus() == Response.Status.OK.getStatusCode() ) { + return response.getEntity(); + } + throw new ClientResponseFailure("Unexpected response code: "+response.getStatus(), response ); + } catch (ClientResponseFailure e) { + throw e; + } catch (Exception e) { + throw new ClientResponseFailure("Unexpected exception retrieving scanner info for container '"+id+"'.", e, response ); + } + } + + public ServiceResponse updateScanner( String id, KieScannerResource resource ) { + ClientResponse> response = null; + try { + ClientRequest clientRequest = new ClientRequest(baseURI+"/containers/"+id+"/scanner"); + response = clientRequest.body(MediaType.APPLICATION_XML_TYPE, resource).post(new GenericType>(){}); + if( response.getStatus() == Response.Status.OK.getStatusCode() ) { + return response.getEntity(); + } + throw new ClientResponseFailure("Unexpected response code: "+response.getStatus(), response ); + } catch (ClientResponseFailure e) { + throw e; + } catch (Exception e) { + throw new ClientResponseFailure("Unexpected exception scanner for container '"+id+"'.", e, response ); + } + } + +} diff --git a/kie-server/kie-server-services/.gitignore b/kie-server/kie-server-services/.gitignore new file mode 100644 index 0000000000..4e841117e9 --- /dev/null +++ b/kie-server/kie-server-services/.gitignore @@ -0,0 +1,31 @@ +/target +/local + +# Eclipse, Netbeans and IntelliJ files +/.* +!.gitignore +/nbproject +/*.ipr +/*.iws +/*.iml + +# Repository wide ignore mac DS_Store files +.DS_Store + +# Original jbpm ignores +bin/ +*~ +*.tlog + +# Test info +/settings*.xml +/lib-jdbc/ +bitronix-default-config.properties +*.db + +# modules that don't exist in this branch +/jbpm-human-task-war/ + +# files used for external db testing +jdbc_driver.jar +db-settings.xml diff --git a/kie-server/kie-server-services/pom.xml b/kie-server/kie-server-services/pom.xml new file mode 100644 index 0000000000..2286715160 --- /dev/null +++ b/kie-server/kie-server-services/pom.xml @@ -0,0 +1,152 @@ + + 4.0.0 + + org.kie + kie-server + 6.2.0-SNAPSHOT + + + kie-server-services + war + + KIE :: Execution Server :: Services + KIE Execution Server Services + + + + + org.jboss.resteasy + resteasy-spring + 2.3.7.Final + + + javax.servlet + servlet-api + 2.5 + test + + + org.jboss.resteasy + tjws + 2.3.7.Final + + + + + + + + org.kie + kie-server-api + + + org.kie + kie-server-client + + + + + org.kie + kie-api + + + + org.drools + drools-compiler + + + + org.kie + kie-ci + + + + + + org.jboss.resteasy + resteasy-jaxrs + + + + org.jboss.resteasy + jaxrs-api + + + org.jboss.resteasy + resteasy-jaxb-provider + + + + org.jboss.resteasy + resteasy-spring + + + + + + org.springframework + spring-context + + + + org.springframework + spring-web + + + + commons-collections + commons-collections + + + + + + org.slf4j + slf4j-api + + + + ch.qos.logback + logback-classic + + + + + + javax.servlet + servlet-api + test + + + org.jboss.resteasy + tjws + + + + + + + + maven-surefire-plugin + + always + + + + + maven-war-plugin + 2.1 + + src/main/webapp/WEB-INF/web.xml + + + + + + + diff --git a/kie-server/kie-server-services/src/main/java/org/kie/server/services/KieServerApplication.java b/kie-server/kie-server-services/src/main/java/org/kie/server/services/KieServerApplication.java new file mode 100644 index 0000000000..aadb1b84ff --- /dev/null +++ b/kie-server/kie-server-services/src/main/java/org/kie/server/services/KieServerApplication.java @@ -0,0 +1,34 @@ +package org.kie.server.services; + +import java.util.Set; +import java.util.concurrent.CopyOnWriteArraySet; + +import javax.ws.rs.core.Application; + +import org.kie.server.services.impl.KieServerImpl; + +public class KieServerApplication extends Application { + + private final Set> classes = new CopyOnWriteArraySet>() { + private static final long serialVersionUID = 1763183096852523317L; + { + add(KieServerImpl.class); + }}; + + private final Set instances = new CopyOnWriteArraySet() { + private static final long serialVersionUID = 1763183096852523317L; + { + add(new KieServerImpl()); + }}; + + @Override + public Set> getClasses() { + return classes; + } + + @Override + public Set getSingletons() { + return instances; + } + +} diff --git a/kie-server/kie-server-services/src/main/java/org/kie/server/services/api/KieServer.java b/kie-server/kie-server-services/src/main/java/org/kie/server/services/api/KieServer.java new file mode 100644 index 0000000000..4e2ac642d7 --- /dev/null +++ b/kie-server/kie-server-services/src/main/java/org/kie/server/services/api/KieServer.java @@ -0,0 +1,68 @@ +package org.kie.server.services.api; + +import javax.ws.rs.Consumes; +import javax.ws.rs.DELETE; +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.PUT; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; + +import org.kie.server.api.commands.CommandScript; +import org.kie.server.api.model.KieContainerResource; +import org.kie.server.api.model.KieScannerResource; + +@Path("/server") +public interface KieServer { + + @GET + @Produces(MediaType.APPLICATION_XML) + public Response getInfo(); + + @POST + @Consumes(MediaType.APPLICATION_XML) + @Produces(MediaType.APPLICATION_XML) + public Response execute( CommandScript command ); + + @GET + @Path("containers") + @Produces(MediaType.APPLICATION_XML) + public Response listContainers(); + + @GET + @Path("containers/{id}") + @Produces(MediaType.APPLICATION_XML) + public Response getContainerInfo( @PathParam("id") String id ); + + @PUT + @Path("containers/{id}") + @Consumes(MediaType.APPLICATION_XML) + @Produces(MediaType.APPLICATION_XML) + public Response createContainer( @PathParam("id") String id, KieContainerResource container ); + + @DELETE + @Path("containers/{id}") + @Produces(MediaType.APPLICATION_XML) + public Response disposeContainer( @PathParam("id") String id ); + + @POST + @Path("containers/{id}") + @Consumes(MediaType.APPLICATION_XML) + @Produces(MediaType.APPLICATION_XML) + public Response execute( @PathParam("id") String id, String cmdPayload ); + + @GET + @Path("containers/{id}/scanner") + @Produces(MediaType.APPLICATION_XML) + public Response getScannerInfo( @PathParam("id") String id ); + + @POST + @Path("containers/{id}/scanner") + @Consumes(MediaType.APPLICATION_XML) + @Produces(MediaType.APPLICATION_XML) + public Response updateScanner( @PathParam("id") String id, KieScannerResource resource ); + +} diff --git a/kie-server/kie-server-services/src/main/java/org/kie/server/services/impl/KieContainerInstance.java b/kie-server/kie-server-services/src/main/java/org/kie/server/services/impl/KieContainerInstance.java new file mode 100644 index 0000000000..8581657bd7 --- /dev/null +++ b/kie-server/kie-server-services/src/main/java/org/kie/server/services/impl/KieContainerInstance.java @@ -0,0 +1,74 @@ +package org.kie.server.services.impl; + +import org.drools.compiler.kie.builder.impl.InternalKieContainer; +import org.drools.compiler.kie.builder.impl.InternalKieScanner; +import org.kie.server.api.model.KieContainerResource; +import org.kie.server.api.model.KieContainerStatus; +import org.kie.server.api.model.ReleaseId; + +public class KieContainerInstance { + + private KieContainerResource resource; + private InternalKieContainer kieContainer; + private InternalKieScanner scanner; + + public KieContainerInstance(String containerId, KieContainerStatus status) { + this(containerId, status, null); + } + + public KieContainerInstance(String containerId, KieContainerStatus status, InternalKieContainer kieContainer) { + super(); + this.resource = new KieContainerResource(containerId, kieContainer != null ? new ReleaseId(kieContainer.getContainerReleaseId()) : null, status); + this.kieContainer = kieContainer; + } + + public String getContainerId() { + return resource.getContainerId(); + } + + public void setContainerId(String containerId) { + this.resource.setContainerId(containerId); + } + + public InternalKieContainer getKieContainer() { + return kieContainer; + } + + public void setKieContainer(InternalKieContainer kieContainer) { + this.kieContainer = kieContainer; + if (kieContainer != null) { + this.resource.setReleaseId(new ReleaseId(kieContainer.getReleaseId())); + this.resource.setResolvedReleaseId(new ReleaseId(kieContainer.getContainerReleaseId())); + } + } + + public KieContainerStatus getStatus() { + return resource.getStatus(); + } + + public void setStatus(KieContainerStatus status) { + this.resource.setStatus(status); + } + + public KieContainerResource getResource() { + return resource; + } + + public void setResource(KieContainerResource resource) { + this.resource = resource; + } + + public void setScanner(InternalKieScanner scanner) { + this.scanner = scanner; + } + + public InternalKieScanner getScanner() { + return this.scanner; + } + + @Override + public String toString() { + return resource.toString(); + } + +} diff --git a/kie-server/kie-server-services/src/main/java/org/kie/server/services/impl/KieContainersRegistry.java b/kie-server/kie-server-services/src/main/java/org/kie/server/services/impl/KieContainersRegistry.java new file mode 100644 index 0000000000..c139c5f107 --- /dev/null +++ b/kie-server/kie-server-services/src/main/java/org/kie/server/services/impl/KieContainersRegistry.java @@ -0,0 +1,36 @@ +package org.kie.server.services.impl; + +import java.util.List; + +public interface KieContainersRegistry { + + /** + * Adds a KieContainerInstance to the registry if one does not exists yet. + * @param containerId the id of the container + * @param ci the container instance + * @return null if it was added or the previous instance if one exists + */ + KieContainerInstance addIfDoesntExist(String containerId, KieContainerInstance ci); + + /** + * Returns the container instance for the given container id + * @param id + * @return + */ + KieContainerInstance getContainer(String containerId); + + /** + * Removes container instance from the registry + * @param containerId + * @return the instance or null if it did not exist + */ + KieContainerInstance removeContainer(String containerId); + + /** + * Returns a list of all instantiated containers + * @return + */ + List getContainers(); + + +} diff --git a/kie-server/kie-server-services/src/main/java/org/kie/server/services/impl/KieServerImpl.java b/kie-server/kie-server-services/src/main/java/org/kie/server/services/impl/KieServerImpl.java new file mode 100644 index 0000000000..e8bd3f6822 --- /dev/null +++ b/kie-server/kie-server-services/src/main/java/org/kie/server/services/impl/KieServerImpl.java @@ -0,0 +1,485 @@ +package org.kie.server.services.impl; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import javax.ws.rs.Path; +import javax.ws.rs.core.GenericEntity; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.Response.Status; + +import org.drools.compiler.kie.builder.impl.InternalKieContainer; +import org.drools.compiler.kie.builder.impl.InternalKieScanner; +import org.drools.core.command.impl.GenericCommand; +import org.drools.core.command.runtime.BatchExecutionCommandImpl; +import org.kie.api.KieServices; +import org.kie.api.command.Command; +import org.kie.api.runtime.ExecutionResults; +import org.kie.api.runtime.KieSession; +import org.kie.server.api.KieServerEnvironment; +import org.kie.server.api.commands.CallContainerCommand; +import org.kie.server.api.commands.CommandScript; +import org.kie.server.api.commands.CreateContainerCommand; +import org.kie.server.api.commands.DisposeContainerCommand; +import org.kie.server.api.commands.ListContainersCommand; +import org.kie.server.api.model.KieContainerResource; +import org.kie.server.api.model.KieContainerResourceList; +import org.kie.server.api.model.KieContainerStatus; +import org.kie.server.api.model.KieScannerResource; +import org.kie.server.api.model.KieScannerStatus; +import org.kie.server.api.model.KieServerCommand; +import org.kie.server.api.model.KieServerInfo; +import org.kie.server.api.model.ReleaseId; +import org.kie.server.api.model.ServiceResponse; +import org.kie.server.api.model.ServiceResponse.ResponseType; +import org.kie.server.services.api.KieServer; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.thoughtworks.xstream.XStream; + +@Path("/server") +public class KieServerImpl implements KieServer { + + private static final Pattern LOOKUP = Pattern.compile("[\"']?lookup[\"']?\\s*[:=]\\s*[\"']([^\"']+)[\"']"); + private static final Logger logger = LoggerFactory.getLogger(KieServerImpl.class); + + private final KieContainersRegistry context; + + public KieServerImpl() { + this.context = new KieContainersRegistryImpl(); + } + + @Override + public Response getInfo() { + return Response.ok(getInfo(context)).build(); + } + + @Override + public Response execute(CommandScript command) { + return Response.ok(new GenericEntity>>(executeScript(context, command)) { + }).build(); + } + + @Override + public Response listContainers() { + return Response.ok(listContainers(context)).build(); + } + + @Override + public Response createContainer(String id, KieContainerResource container) { + return Response.status(Status.CREATED).entity(createContainer(context, id, container)).build(); + } + + @Override + public Response getContainerInfo(String id) { + return Response.ok(getContainerInfo(context, id)).build(); + } + + @Override + public Response disposeContainer(String id) { + return Response.ok(disposeContainer(context, id)).build(); + } + + @Override + public Response execute(String id, String cmdPayload) { + return Response.ok(callContainer(context, id, cmdPayload)).build(); + } + + @Override + public Response getScannerInfo(String id) { + return Response.ok(getScannerInfo(context, id)).build(); + } + + @Override + public Response updateScanner(String id, KieScannerResource resource) { + return Response.ok(updateScanner(context, id, resource)).build(); + }; + + private List> executeScript(KieContainersRegistry context, CommandScript commands) { + List> response = new ArrayList>(); + for (KieServerCommand command : commands.getCommands()) { + if (command instanceof CreateContainerCommand) { + response.add(createContainer(context, ((CreateContainerCommand) command).getContainer().getContainerId(), ((CreateContainerCommand) command).getContainer())); + } else if (command instanceof ListContainersCommand) { + response.add(listContainers(context)); + } else if (command instanceof CallContainerCommand) { + response.add(callContainer(context, ((CallContainerCommand) command).getContainerId(), ((CallContainerCommand) command).getPayload())); + } else if (command instanceof DisposeContainerCommand) { + response.add(disposeContainer(context, ((DisposeContainerCommand) command).getContainerId())); + } + } + return response; + } + + private ServiceResponse getInfo(KieContainersRegistry context) { + try { + return new ServiceResponse(ServiceResponse.ResponseType.SUCCESS, "Kie Server info", new KieServerInfo(KieServerEnvironment.getVersion().toString())); + } catch (Exception e) { + logger.error("Error retrieving server info:", e); + return new ServiceResponse(ServiceResponse.ResponseType.FAILURE, "Error retrieving kie server info: " + + e.getClass().getName() + ": " + e.getMessage()); + } + } + + private ServiceResponse createContainer(KieContainersRegistry context, String containerId, KieContainerResource container) { + ReleaseId releaseId = container.getReleaseId(); + if( releaseId == null ) { + logger.error("Error creating container. Release Id is null: "+container); + return new ServiceResponse(ServiceResponse.ResponseType.FAILURE, "Failed to create container " + containerId + ". Release Id is null: " + container + "."); + } + try { + KieContainerInstance ci = new KieContainerInstance(containerId, KieContainerStatus.CREATING); + KieContainerInstance previous = null; + // have to synchronize on the ci or a concurrent call to dispose may create inconsistencies + synchronized (ci) { + if ((previous = context.addIfDoesntExist(containerId, ci)) == null) { + try { + KieServices ks = KieServices.Factory.get(); + InternalKieContainer kieContainer = (InternalKieContainer) ks.newKieContainer(releaseId); + if (kieContainer != null) { + ci.setKieContainer(kieContainer); + ci.getResource().setStatus(KieContainerStatus.STARTED); + return new ServiceResponse(ServiceResponse.ResponseType.SUCCESS, "Container " + containerId + " successfully deployed with module " + releaseId + ".", ci.getResource()); + } else { + ci.getResource().setStatus(KieContainerStatus.FAILED); + return new ServiceResponse(ServiceResponse.ResponseType.FAILURE, "Failed to create container " + containerId + " with module " + releaseId + "."); + } + } catch (Exception e) { + logger.error("Error creating container '"+containerId+"' for module '"+releaseId+"'", e); + ci.getResource().setStatus(KieContainerStatus.FAILED); + return new ServiceResponse(ServiceResponse.ResponseType.FAILURE, "Failed to create container " + containerId + " with module " + releaseId + ": " + e.getClass().getName() + ": " + e.getMessage()); + } + } else { + return new ServiceResponse(ServiceResponse.ResponseType.FAILURE, "Container " + containerId + " already exists.", previous.getResource()); + } + } + } catch (Exception e) { + logger.error("Error creating container '"+containerId+"' for module '"+releaseId+"'", e); + return new ServiceResponse(ServiceResponse.ResponseType.FAILURE, "Error creating container " + containerId + + " with module " + releaseId + ": " + e.getClass().getName() + ": " + e.getMessage()); + } + } + + private ServiceResponse listContainers(KieContainersRegistry context) { + try { + List containers = new ArrayList(); + for (KieContainerInstance instance : context.getContainers()) { + containers.add(instance.getResource()); + } + KieContainerResourceList cil = new KieContainerResourceList(containers); + return new ServiceResponse(ServiceResponse.ResponseType.SUCCESS, "List of created containers", cil); + } catch (Exception e) { + logger.error("Error retrieving list of containers", e); + return new ServiceResponse(ServiceResponse.ResponseType.FAILURE, "Error listing containers: " + + e.getClass().getName() + ": " + e.getMessage()); + } + } + + private ServiceResponse getContainerInfo(KieContainersRegistry context, String id) { + try { + KieContainerInstance ci = context.getContainer(id); + if (ci != null) { + return new ServiceResponse(ServiceResponse.ResponseType.SUCCESS, "Info for container " + id, ci.getResource()); + } + return new ServiceResponse(ServiceResponse.ResponseType.FAILURE, "Container " + id + " is not instantiated."); + } catch (Exception e) { + logger.error("Error retrieving info for container '"+id+"'", e); + return new ServiceResponse(ServiceResponse.ResponseType.FAILURE, "Error retrieving container info: " + + e.getClass().getName() + ": " + e.getMessage()); + } + } + + private ServiceResponse callContainer(KieContainersRegistry context, String containerId, String payload) { + try { + KieContainerInstance kci = (KieContainerInstance) context.getContainer(containerId); + // the following code is subject to a concurrent call to dispose(), but the cost of synchronizing it + // would likely not be worth it. At this point a decision was made to fail the execution if a concurrent + // call do dispose() is executed. + if (kci != null && kci.getKieContainer() != null) { + String sessionId = null; + // this is a weak way of finding the lookup, but it is the same used in kie-camel. Will keep it for now. + Matcher m = LOOKUP.matcher(payload); + if (m.find()) { + sessionId = m.group(1); + } + + KieSession ks = null; + if (sessionId != null) { + ks = kci.getKieContainer().getKieSession(sessionId); + } else { + ks = kci.getKieContainer().getKieSession(); + } + if (ks != null) { + ClassLoader moduleClassLoader = kci.getKieContainer().getClassLoader(); + XStream xs = XStreamXml.newXStreamMarshaller(moduleClassLoader); + Command cmd = (Command) xs.fromXML(payload); + + if (cmd == null) { + return new ServiceResponse(ServiceResponse.ResponseType.FAILURE, "Body of in message not of the expected type '" + Command.class.getName() + "'"); + } + if (!(cmd instanceof BatchExecutionCommandImpl)) { + cmd = new BatchExecutionCommandImpl(Arrays.asList(new GenericCommand[]{(GenericCommand) cmd})); + } + + ExecutionResults results = ks.execute((BatchExecutionCommandImpl) cmd); + String result = xs.toXML(results); + return new ServiceResponse(ServiceResponse.ResponseType.SUCCESS, "Container " + containerId + " successfully called.", result); + } else { + return new ServiceResponse(ServiceResponse.ResponseType.FAILURE, "Session '" + sessionId + "' not found on container '" + containerId + "'."); + } + } else { + return new ServiceResponse(ServiceResponse.ResponseType.FAILURE, "Container " + containerId + " is not instantiated."); + } + } catch (Exception e) { + logger.error("Error calling container '"+containerId+"'", e); + return new ServiceResponse(ServiceResponse.ResponseType.FAILURE, "Error calling container " + containerId + ": " + + e.getClass().getName() + ": " + e.getMessage()); + } + } + + private ServiceResponse disposeContainer(KieContainersRegistry context, String containerId) { + try { + KieContainerInstance kci = (KieContainerInstance) context.removeContainer(containerId); + if (kci != null) { + synchronized (kci) { + kci.setStatus(KieContainerStatus.DISPOSING); // just in case + if (kci.getKieContainer() != null) { + InternalKieContainer kieContainer = kci.getKieContainer(); + kci.setKieContainer(null); // helps reduce concurrent access issues + try { + // this may fail, but we already removed the container from the registry + kieContainer.dispose(); + } catch (Exception e) { + logger.warn("Container '"+containerId+"' disposed, but an unnexpected exception was raised", e); + return new ServiceResponse(ServiceResponse.ResponseType.SUCCESS, "Container " + containerId + + " disposed, but exception was raised: " + e.getClass().getName() + ": " + e.getMessage()); + } + return new ServiceResponse(ServiceResponse.ResponseType.SUCCESS, "Container " + containerId + " successfully disposed."); + } else { + return new ServiceResponse(ServiceResponse.ResponseType.SUCCESS, "Container " + containerId + " was not instantiated."); + } + } + } else { + return new ServiceResponse(ServiceResponse.ResponseType.SUCCESS, "Container " + containerId + " was not instantiated."); + } + } catch (Exception e) { + logger.error("Error disposing Container '"+containerId+"'", e); + return new ServiceResponse(ServiceResponse.ResponseType.FAILURE, "Error disposing container " + containerId + ": " + + e.getClass().getName() + ": " + e.getMessage()); + } + } + + private ServiceResponse getScannerInfo(KieContainersRegistry context, String id) { + try { + KieContainerInstance kci = (KieContainerInstance) context.getContainer(id); + if (kci != null && kci.getKieContainer() != null) { + InternalKieScanner scanner = kci.getScanner(); + KieScannerResource info = null; + if( scanner != null ) { + info = new KieScannerResource(mapStatus(scanner.getStatus())); + } else { + info = new KieScannerResource(KieScannerStatus.DISPOSED); + } + return new ServiceResponse(ServiceResponse.ResponseType.SUCCESS, "Scanner info successfully retrieved", info ); + } else { + return new ServiceResponse(ServiceResponse.ResponseType.FAILURE, + "Unknown container "+id+"."); + } + } catch (Exception e) { + logger.error("Error retrieving scanner info for container '"+id+"'.", e); + return new ServiceResponse(ServiceResponse.ResponseType.FAILURE, "Error retrieving scanner info for container '"+id+"': " + + e.getClass().getName() + ": " + e.getMessage()); + } + } + + private ServiceResponse updateScanner(KieContainersRegistry context, String id, KieScannerResource resource) { + KieScannerStatus status = resource.getStatus(); + if( status == null ) { + logger.error("Error updating scanner for container "+id+". Status is null: "+resource); + return new ServiceResponse(ServiceResponse.ResponseType.FAILURE, "Error updating scanner for container "+id+". Status is null: "+resource); + } + try { + KieContainerInstance kci = (KieContainerInstance) context.getContainer(id); + if (kci != null && kci.getKieContainer() != null) { + switch( status ) { + case CREATED: + // create the scanner + return createScanner(id, kci); + case STARTED: + // start the scanner + return startScanner(id, resource, kci); + case STOPPED: + // stop the scanner + return stopScanner(id, resource, kci); + case SCANNING: + // scan now + return scanNow(id, resource, kci); + case DISPOSED: + // dispose + return disposeScanner(id, resource, kci); + default: + // error + return new ServiceResponse(ServiceResponse.ResponseType.FAILURE, + "Unknown status '"+status+"' for scanner on container "+id+"."); + } + } else { + return new ServiceResponse(ServiceResponse.ResponseType.FAILURE, + "Unknown container "+id+"."); + } + } catch (Exception e) { + logger.error("Error updating scanner for container '"+id+"': "+resource, e); + return new ServiceResponse(ServiceResponse.ResponseType.FAILURE, "Error updating scanner for container '"+id+ + "': "+resource + ": " + e.getClass().getName() + ": " + e.getMessage()); + } + } + + private ServiceResponse startScanner(String id, KieScannerResource resource, KieContainerInstance kci) { + if( kci.getScanner() == null ) { + ServiceResponse response = createScanner(id, kci); + if( ResponseType.FAILURE.equals( response.getType() ) ) { + return response; + } + } + if( KieScannerStatus.STOPPED.equals( mapStatus( kci.getScanner().getStatus() ) ) && + resource.getPollInterval() != null ) { + kci.getScanner().start( resource.getPollInterval() ); + return new ServiceResponse(ServiceResponse.ResponseType.SUCCESS, + "Kie scanner successfuly created.", + new KieScannerResource( mapStatus( kci.getScanner().getStatus() ) ) ); + } else if(!KieScannerStatus.STOPPED.equals( mapStatus( kci.getScanner().getStatus() ) )) { + return new ServiceResponse(ServiceResponse.ResponseType.FAILURE, + "Invalid kie scanner status: "+mapStatus( kci.getScanner().getStatus() ), + new KieScannerResource( mapStatus( kci.getScanner().getStatus() ) )); + } else if( resource.getPollInterval() == null ) { + return new ServiceResponse(ServiceResponse.ResponseType.FAILURE, + "Invalid polling interval: "+resource.getPollInterval(), + new KieScannerResource( mapStatus( kci.getScanner().getStatus() ) )); + } + return new ServiceResponse(ServiceResponse.ResponseType.FAILURE, + "Unknown error starting scanner. Scanner was not started."+resource, + new KieScannerResource( mapStatus( kci.getScanner().getStatus() ) )); + } + + private ServiceResponse stopScanner(String id, KieScannerResource resource, KieContainerInstance kci) { + if( kci.getScanner() == null ) { + return new ServiceResponse(ServiceResponse.ResponseType.FAILURE, + "Invalid call. Scanner is not instantiated. ", + new KieScannerResource( KieScannerStatus.DISPOSED )); + } + if( KieScannerStatus.STARTED.equals( mapStatus( kci.getScanner().getStatus() ) ) || + KieScannerStatus.SCANNING.equals( mapStatus( kci.getScanner().getStatus() ) ) ) { + kci.getScanner().stop(); + return new ServiceResponse(ServiceResponse.ResponseType.SUCCESS, + "Kie scanner successfuly stopped.", + new KieScannerResource( mapStatus( kci.getScanner().getStatus() ) ) ); + } else { + return new ServiceResponse(ServiceResponse.ResponseType.FAILURE, + "Invalid kie scanner status: "+mapStatus( kci.getScanner().getStatus() ), + new KieScannerResource( mapStatus( kci.getScanner().getStatus() ) )); + } + } + + private ServiceResponse scanNow(String id, KieScannerResource resource, KieContainerInstance kci) { + if( kci.getScanner() == null ) { + return new ServiceResponse(ServiceResponse.ResponseType.FAILURE, + "Invalid call. Scanner is not instantiated. ", + new KieScannerResource( KieScannerStatus.DISPOSED )); + } + if( KieScannerStatus.STOPPED.equals( mapStatus( kci.getScanner().getStatus() ) ) ) { + kci.getScanner().scanNow(); + return new ServiceResponse(ServiceResponse.ResponseType.SUCCESS, + "Scan successfully executed.", + new KieScannerResource( mapStatus( kci.getScanner().getStatus() ) ) ); + } else { + return new ServiceResponse(ServiceResponse.ResponseType.FAILURE, + "Invalid kie scanner status: "+mapStatus( kci.getScanner().getStatus() ), + new KieScannerResource( mapStatus( kci.getScanner().getStatus() ) )); + } + } + + private ServiceResponse disposeScanner(String id, KieScannerResource resource, KieContainerInstance kci) { + if( kci.getScanner() == null ) { + return new ServiceResponse(ServiceResponse.ResponseType.SUCCESS, + "Invalid call. Scanner already disposed. ", + new KieScannerResource( KieScannerStatus.DISPOSED )); + } + if( KieScannerStatus.STARTED.equals( mapStatus( kci.getScanner().getStatus() ) ) || + KieScannerStatus.SCANNING.equals( mapStatus( kci.getScanner().getStatus() ) ) ) { + ServiceResponse response = stopScanner(id, resource, kci); + if( ResponseType.FAILURE.equals( response.getType() ) ) { + return response; + } + } + kci.getScanner().shutdown(); + kci.setScanner(null); + return new ServiceResponse(ServiceResponse.ResponseType.SUCCESS, + "Kie scanner successfuly shutdown.", + new KieScannerResource( KieScannerStatus.DISPOSED ) ); + } + + private ServiceResponse createScanner(String id, KieContainerInstance kci) { + if( kci.getScanner() == null ) { + InternalKieScanner scanner = (InternalKieScanner) KieServices.Factory.get().newKieScanner(kci.getKieContainer()); + kci.setScanner( scanner ); + return new ServiceResponse(ServiceResponse.ResponseType.SUCCESS, + "Kie scanner successfuly created.", + new KieScannerResource( mapStatus( scanner.getStatus() ) ) ); + } else { + return new ServiceResponse(ServiceResponse.ResponseType.FAILURE, + "Error creating the scanner for container "+id+". Scanner already exists."); + + } + } + + private KieScannerStatus mapStatus( InternalKieScanner.Status status ) { + switch( status ) { + case STARTING: + return KieScannerStatus.CREATED; + case RUNNING: + return KieScannerStatus.STARTED; + case SCANNING: + case UPDATING: + return KieScannerStatus.SCANNING; + case STOPPED: + return KieScannerStatus.STOPPED; + case SHUTDOWN: + return KieScannerStatus.DISPOSED; + default: + return KieScannerStatus.UNKNOWN; + } + } + + public static class KieContainersRegistryImpl implements KieContainersRegistry { + + private final ConcurrentMap containers; + + public KieContainersRegistryImpl() { + this.containers = new ConcurrentHashMap(); + } + + public KieContainerInstance addIfDoesntExist(String containerId, KieContainerInstance ci) { + return containers.putIfAbsent(containerId, ci); + } + + public List getContainers() { + // instantiating a new array list to prevent iteration problems when concurrently changing the map + return new ArrayList(containers.values()); + } + + public KieContainerInstance getContainer(String containerId) { + return containers.get(containerId); + } + + public KieContainerInstance removeContainer(String containerId) { + return containers.remove(containerId); + } + + } + +} diff --git a/kie-server/kie-server-services/src/main/java/org/kie/server/services/impl/XStreamXml.java b/kie-server/kie-server-services/src/main/java/org/kie/server/services/impl/XStreamXml.java new file mode 100644 index 0000000000..b72a46d601 --- /dev/null +++ b/kie-server/kie-server-services/src/main/java/org/kie/server/services/impl/XStreamXml.java @@ -0,0 +1,133 @@ +/* + * Copyright 2010 JBoss Inc + * + * 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. + */ + +package org.kie.server.services.impl; + +import org.drools.core.command.runtime.BatchExecutionCommandImpl; +import org.drools.core.command.runtime.GetGlobalCommand; +import org.drools.core.command.runtime.SetGlobalCommand; +import org.drools.core.command.runtime.process.AbortWorkItemCommand; +import org.drools.core.command.runtime.process.CompleteWorkItemCommand; +import org.drools.core.command.runtime.process.SignalEventCommand; +import org.drools.core.command.runtime.process.StartProcessCommand; +import org.drools.core.command.runtime.rule.DeleteCommand; +import org.drools.core.command.runtime.rule.FireAllRulesCommand; +import org.drools.core.command.runtime.rule.GetObjectCommand; +import org.drools.core.command.runtime.rule.GetObjectsCommand; +import org.drools.core.command.runtime.rule.InsertElementsCommand; +import org.drools.core.command.runtime.rule.InsertObjectCommand; +import org.drools.core.command.runtime.rule.ModifyCommand; +import org.drools.core.command.runtime.rule.ModifyCommand.SetterImpl; +import org.drools.core.command.runtime.rule.QueryCommand; +import org.drools.core.common.DefaultFactHandle; +import org.drools.core.runtime.help.impl.XStreamXML.AbortWorkItemConverter; +import org.drools.core.runtime.help.impl.XStreamXML.BatchExecutionResultConverter; +import org.drools.core.runtime.help.impl.XStreamXML.CompleteWorkItemConverter; +import org.drools.core.runtime.help.impl.XStreamXML.FactHandleConverter; +import org.drools.core.runtime.help.impl.XStreamXML.FireAllRulesConverter; +import org.drools.core.runtime.help.impl.XStreamXML.GetGlobalConverter; +import org.drools.core.runtime.help.impl.XStreamXML.GetObjectConverter; +import org.drools.core.runtime.help.impl.XStreamXML.GetObjectsConverter; +import org.drools.core.runtime.help.impl.XStreamXML.InsertConverter; +import org.drools.core.runtime.help.impl.XStreamXML.InsertElementsConverter; +import org.drools.core.runtime.help.impl.XStreamXML.ModifyConverter; +import org.drools.core.runtime.help.impl.XStreamXML.QueryConverter; +import org.drools.core.runtime.help.impl.XStreamXML.QueryResultsConverter; +import org.drools.core.runtime.help.impl.XStreamXML.RetractConverter; +import org.drools.core.runtime.help.impl.XStreamXML.SetGlobalConverter; +import org.drools.core.runtime.help.impl.XStreamXML.SignalEventConverter; +import org.drools.core.runtime.help.impl.XStreamXML.StartProcessConvert; +import org.drools.core.runtime.impl.ExecutionResultImpl; +import org.drools.core.runtime.rule.impl.FlatQueryResults; + +import com.thoughtworks.xstream.XStream; + +public class XStreamXml { + + public static XStream newXStreamMarshaller(ClassLoader classLoader) { + XStream xstream = new XStream(); + xstream.setClassLoader(classLoader); + setAliases(xstream); + + xstream.addImplicitCollection(BatchExecutionCommandImpl.class, "commands"); + + registerConverters(xstream); + + return xstream; + } + + private static void registerConverters(XStream xstream) { + xstream.registerConverter(new InsertConverter(xstream)); + xstream.registerConverter(new RetractConverter(xstream)); + xstream.registerConverter(new ModifyConverter(xstream)); + xstream.registerConverter(new GetObjectConverter(xstream)); + xstream.registerConverter(new InsertElementsConverter(xstream)); + xstream.registerConverter(new FireAllRulesConverter(xstream)); + xstream.registerConverter(new StartProcessConvert(xstream)); + xstream.registerConverter(new SignalEventConverter(xstream)); + xstream.registerConverter(new CompleteWorkItemConverter(xstream)); + xstream.registerConverter(new AbortWorkItemConverter(xstream)); + xstream.registerConverter(new QueryConverter(xstream)); + xstream.registerConverter(new SetGlobalConverter(xstream)); + xstream.registerConverter(new GetGlobalConverter(xstream)); + xstream.registerConverter(new GetObjectsConverter(xstream)); + xstream.registerConverter(new BatchExecutionResultConverter(xstream)); + xstream.registerConverter(new QueryResultsConverter(xstream)); + xstream.registerConverter(new FactHandleConverter(xstream)); + } + + public static void setAliases(XStream xstream) { + xstream.alias("batch-execution", + BatchExecutionCommandImpl.class); + xstream.alias("insert", + InsertObjectCommand.class); + xstream.alias("modify", + ModifyCommand.class); + xstream.alias("setters", + SetterImpl.class); + xstream.alias("retract", + DeleteCommand.class); + xstream.alias("insert-elements", + InsertElementsCommand.class); + xstream.alias("start-process", + StartProcessCommand.class); + xstream.alias("signal-event", + SignalEventCommand.class); + xstream.alias("complete-work-item", + CompleteWorkItemCommand.class); + xstream.alias("abort-work-item", + AbortWorkItemCommand.class); + xstream.alias("set-global", + SetGlobalCommand.class); + xstream.alias("get-global", + GetGlobalCommand.class); + xstream.alias("get-object", + GetObjectCommand.class); + xstream.alias("get-objects", + GetObjectsCommand.class); + xstream.alias("execution-results", + ExecutionResultImpl.class); + xstream.alias("fire-all-rules", + FireAllRulesCommand.class); + xstream.alias("query", + QueryCommand.class); + xstream.alias("query-results", + FlatQueryResults.class); + xstream.alias("fact-handle", + DefaultFactHandle.class); + } + +} diff --git a/kie-server/kie-server-services/src/main/java/org/kie/server/services/impl/adapters/ExecutionResultsAdapter.java b/kie-server/kie-server-services/src/main/java/org/kie/server/services/impl/adapters/ExecutionResultsAdapter.java new file mode 100644 index 0000000000..fe66a1ad5d --- /dev/null +++ b/kie-server/kie-server-services/src/main/java/org/kie/server/services/impl/adapters/ExecutionResultsAdapter.java @@ -0,0 +1,21 @@ +package org.kie.server.services.impl.adapters; + +import javax.xml.bind.annotation.adapters.XmlAdapter; + +import org.drools.core.runtime.impl.ExecutionResultImpl; +import org.kie.api.runtime.ExecutionResults; + + +public class ExecutionResultsAdapter extends XmlAdapter{ + + @Override + public ExecutionResults unmarshal(ExecutionResultImpl v) throws Exception { + return v; + } + + @Override + public ExecutionResultImpl marshal(ExecutionResults v) throws Exception { + return (ExecutionResultImpl)v; + } + +} diff --git a/kie-server/kie-server-services/src/main/resources/applicationContext.xml b/kie-server/kie-server-services/src/main/resources/applicationContext.xml new file mode 100644 index 0000000000..ecb6f39999 --- /dev/null +++ b/kie-server/kie-server-services/src/main/resources/applicationContext.xml @@ -0,0 +1,17 @@ + + + + + + + + + + diff --git a/kie-server/kie-server-services/src/main/webapp/WEB-INF/web.xml b/kie-server/kie-server-services/src/main/webapp/WEB-INF/web.xml new file mode 100644 index 0000000000..4d6436c2c8 --- /dev/null +++ b/kie-server/kie-server-services/src/main/webapp/WEB-INF/web.xml @@ -0,0 +1,32 @@ + + + + + org.jboss.resteasy.plugins.server.servlet.ResteasyBootstrap + + + org.jboss.resteasy.plugins.spring.SpringContextLoaderListener + + + Resteasy + org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher + + javax.ws.rs.Application + org.kie.server.services.KieServerApplication + + + + Resteasy + /services/rest/* + + + contextConfigLocation + classpath:applicationContext.xml + + + resteasy.servlet.mapping.prefix + /services/rest + + \ No newline at end of file diff --git a/kie-server/kie-server-services/src/test/java/org/kie/server/impl/KieServerTest.java b/kie-server/kie-server-services/src/test/java/org/kie/server/impl/KieServerTest.java new file mode 100644 index 0000000000..c2e3397f85 --- /dev/null +++ b/kie-server/kie-server-services/src/test/java/org/kie/server/impl/KieServerTest.java @@ -0,0 +1,351 @@ +package org.kie.server.impl; + +import static org.kie.scanner.MavenRepository.getMavenRepository; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.lang.reflect.Method; +import java.net.ServerSocket; +import java.net.URL; +import java.net.URLClassLoader; +import java.util.Arrays; +import java.util.List; + +import org.drools.compiler.kie.builder.impl.InternalKieModule; +import org.jboss.resteasy.plugins.providers.RegisterBuiltin; +import org.jboss.resteasy.plugins.server.tjws.TJWSEmbeddedJaxrsServer; +import org.jboss.resteasy.spi.ResteasyProviderFactory; +import org.junit.After; +import org.junit.AfterClass; +import org.junit.Assert; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; +import org.kie.api.KieServices; +import org.kie.api.builder.KieBuilder; +import org.kie.api.builder.KieFileSystem; +import org.kie.api.command.BatchExecutionCommand; +import org.kie.api.command.Command; +import org.kie.api.command.KieCommands; +import org.kie.api.runtime.ExecutionResults; +import org.kie.internal.runtime.helper.BatchExecutionHelper; +import org.kie.scanner.MavenRepository; +import org.kie.server.api.KieServerEnvironment; +import org.kie.server.api.commands.CallContainerCommand; +import org.kie.server.api.commands.CommandScript; +import org.kie.server.api.commands.CreateContainerCommand; +import org.kie.server.api.commands.DisposeContainerCommand; +import org.kie.server.api.model.KieContainerResource; +import org.kie.server.api.model.KieContainerResourceList; +import org.kie.server.api.model.KieContainerStatus; +import org.kie.server.api.model.KieScannerResource; +import org.kie.server.api.model.KieScannerStatus; +import org.kie.server.api.model.KieServerCommand; +import org.kie.server.api.model.KieServerInfo; +import org.kie.server.api.model.ReleaseId; +import org.kie.server.api.model.ServiceResponse; +import org.kie.server.api.model.ServiceResponse.ResponseType; +import org.kie.server.client.KieServicesClient; +import org.kie.server.services.impl.KieServerImpl; + +import com.thoughtworks.xstream.XStream; + +public class KieServerTest { + + private static final int PORT = findFreePort(); + private static MavenRepository repository; + private static ReleaseId releaseId; + private TJWSEmbeddedJaxrsServer server; + private KieServicesClient client; + + @BeforeClass + public static void initialize() throws Exception { + createAndDeployKJar(); + // this initialization only needs to be done once per VM + RegisterBuiltin.register(ResteasyProviderFactory.getInstance()); + } + + @AfterClass + public static void destroy() throws Exception { + } + + @Before + public void setup() throws Exception { + startServer(); + startClient(); + } + + @After + public void tearDown() { + server.stop(); + } + + @Test + public void testGetServerInfo() throws Exception { + ServiceResponse reply = client.getServerInfo(); + Assert.assertEquals(ServiceResponse.ResponseType.SUCCESS, reply.getType()); + KieServerInfo info = reply.getResult(); + Assert.assertEquals(KieServerEnvironment.getVersion().toString(), info.getVersion()); + System.out.println(reply.getResult()); + } + + @Test + public void testCreateContainer() throws Exception { + ServiceResponse reply = client.createContainer("kie1", new KieContainerResource("kie1", releaseId)); + Assert.assertEquals(ServiceResponse.ResponseType.SUCCESS, reply.getType()); + } + + @Test + public void testGetContainerInfo() throws Exception { + client.createContainer("kie1", new KieContainerResource("kie1", releaseId)); + ServiceResponse reply = client.getContainerInfo("kie1"); + Assert.assertEquals(ServiceResponse.ResponseType.SUCCESS, reply.getType()); + + KieContainerResource info = reply.getResult(); + Assert.assertEquals( KieContainerStatus.STARTED, info.getStatus() ); + } + + @Test + public void testGetContainerInfoNonExisting() throws Exception { + ServiceResponse reply = client.getContainerInfo("kie1"); + Assert.assertEquals(ServiceResponse.ResponseType.FAILURE, reply.getType()); + } + + @Test + public void testListContainers() throws Exception { + client.createContainer("kie1", new KieContainerResource("kie1", releaseId)); + client.createContainer("kie2", new KieContainerResource("kie2", releaseId)); + ServiceResponse reply = client.listContainers(); + Assert.assertEquals(ServiceResponse.ResponseType.SUCCESS, reply.getType()); + Assert.assertEquals(2, reply.getResult().getContainers().size()); + } + + @Test + public void testDisposeContainer() throws Exception { + client.createContainer("kie1", new KieContainerResource("kie1", releaseId)); + ServiceResponse reply = client.disposeContainer("kie1"); + Assert.assertEquals(ServiceResponse.ResponseType.SUCCESS, reply.getType()); + } + + @Test + public void testCallContainer() throws Exception { + client.createContainer("kie1", new KieContainerResource("kie1", releaseId)); + + String payload = "\n" + + " \n" + + " \n" + + " Hello World\n" + + " \n" + + " \n" + + " \n" + + ""; + + ServiceResponse reply = client.executeCommands("kie1", payload); + Assert.assertEquals(ServiceResponse.ResponseType.SUCCESS, reply.getType()); + } + + @Test + public void testCallContainerMarshallCommands() throws Exception { + client.createContainer("kie1", new KieContainerResource("kie1", releaseId)); + + KieServices ks = KieServices.Factory.get(); + File jar = MavenRepository.getMavenRepository().resolveArtifact(releaseId).getFile(); + URLClassLoader cl = new URLClassLoader(new URL[]{jar.toURI().toURL()}); + Class messageClass = cl.loadClass("org.pkg1.Message"); + Object message = messageClass.newInstance(); + Method setter = messageClass.getMethod("setText", String.class); + Method getter = messageClass.getMethod("getText"); + setter.invoke(message, "HelloWorld"); + + KieCommands kcmd = ks.getCommands(); + Command insert = kcmd.newInsert(message, "message"); + Command fire = kcmd.newFireAllRules(); + BatchExecutionCommand batch = kcmd.newBatchExecution(Arrays.asList(insert, fire), "defaultKieSession"); + + String payload = BatchExecutionHelper.newXStreamMarshaller().toXML(batch); + + ServiceResponse reply = client.executeCommands("kie1", payload); + Assert.assertEquals(ServiceResponse.ResponseType.SUCCESS, reply.getType()); + + XStream xs = BatchExecutionHelper.newXStreamMarshaller(); + xs.setClassLoader(cl); + ExecutionResults results = (ExecutionResults) xs.fromXML(reply.getResult()); + Object value = results.getValue("message"); + Assert.assertEquals("echo:HelloWorld", getter.invoke(value)); + } + + @Test + public void testCommandScript() throws Exception { + KieServices ks = KieServices.Factory.get(); + File jar = MavenRepository.getMavenRepository().resolveArtifact(releaseId).getFile(); + URLClassLoader cl = new URLClassLoader(new URL[]{jar.toURI().toURL()}); + Class messageClass = cl.loadClass("org.pkg1.Message"); + Object message = messageClass.newInstance(); + Method setter = messageClass.getMethod("setText", String.class); + setter.invoke(message, "HelloWorld"); + + KieCommands kcmd = ks.getCommands(); + Command insert = kcmd.newInsert(message, "message"); + Command fire = kcmd.newFireAllRules(); + BatchExecutionCommand batch = kcmd.newBatchExecution(Arrays.asList(insert, fire), "defaultKieSession"); + + String payload = BatchExecutionHelper.newXStreamMarshaller().toXML(batch); + + KieServerCommand create = new CreateContainerCommand(new KieContainerResource( "kie1", releaseId, null)); + KieServerCommand call = new CallContainerCommand("kie1", payload); + KieServerCommand dispose = new DisposeContainerCommand("kie1"); + + List cmds = Arrays.asList(create, call, dispose); + CommandScript script = new CommandScript(cmds); + + List> reply = client.executeScript(script); + + for (ServiceResponse r : reply) { + Assert.assertEquals(ServiceResponse.ResponseType.SUCCESS, r.getType()); + } + } + + @Test + public void testCallContainerLookupError() throws Exception { + client.createContainer("kie1", new KieContainerResource("kie1", releaseId)); + + String payload = "\n" + + " \n" + + " \n" + + " Hello World\n" + + " \n" + + " \n" + + ""; + + ServiceResponse reply = client.executeCommands("kie1", payload); + Assert.assertEquals(ServiceResponse.ResponseType.FAILURE, reply.getType()); + } + + @Test + public void testScanner() throws Exception { + client.createContainer("kie1", new KieContainerResource("kie1", releaseId)); + ServiceResponse reply = client.getContainerInfo("kie1"); + Assert.assertEquals(ServiceResponse.ResponseType.SUCCESS, reply.getType()); + + ServiceResponse si = client.getScannerInfo("kie1"); + Assert.assertEquals( ResponseType.SUCCESS, si.getType() ); + KieScannerResource info = si.getResult(); + Assert.assertEquals( KieScannerStatus.DISPOSED, info.getStatus() ); + + si = client.updateScanner("kie1", new KieScannerResource(KieScannerStatus.STARTED, 10000l)); + Assert.assertEquals( si.getMsg(), ResponseType.SUCCESS, si.getType() ); + info = si.getResult(); + Assert.assertEquals( KieScannerStatus.STARTED, info.getStatus() ); + + si = client.getScannerInfo("kie1"); + Assert.assertEquals( si.getMsg(), ResponseType.SUCCESS, si.getType() ); + info = si.getResult(); + Assert.assertEquals( KieScannerStatus.STARTED, info.getStatus() ); + + si = client.updateScanner("kie1", new KieScannerResource(KieScannerStatus.STOPPED, 10000l)); + Assert.assertEquals( si.getMsg(), ResponseType.SUCCESS, si.getType() ); + info = si.getResult(); + Assert.assertEquals( KieScannerStatus.STOPPED, info.getStatus() ); + + si = client.getScannerInfo("kie1"); + Assert.assertEquals( si.getMsg(), ResponseType.SUCCESS, si.getType() ); + info = si.getResult(); + Assert.assertEquals( KieScannerStatus.STOPPED, info.getStatus() ); + + si = client.updateScanner("kie1", new KieScannerResource(KieScannerStatus.DISPOSED, 10000l)); + Assert.assertEquals( si.getMsg(), ResponseType.SUCCESS, si.getType() ); + info = si.getResult(); + Assert.assertEquals( KieScannerStatus.DISPOSED, info.getStatus() ); + + si = client.getScannerInfo("kie1"); + Assert.assertEquals( si.getMsg(), ResponseType.SUCCESS, si.getType() ); + info = si.getResult(); + Assert.assertEquals( KieScannerStatus.DISPOSED, info.getStatus() ); + } + + public static byte[] createAndDeployJar(KieServices ks, + ReleaseId releaseId, + String... drls) { + KieFileSystem kfs = ks.newKieFileSystem().generateAndWritePomXML( + releaseId); + for (int i = 0; i < drls.length; i++) { + if (drls[i] != null) { + kfs.write("src/main/resources/org/pkg1/r" + i + ".drl", drls[i]); + } + } + byte[] pom = kfs.read("pom.xml"); + KieBuilder kb = ks.newKieBuilder(kfs).buildAll(); + Assert.assertFalse(kb.getResults().getMessages(org.kie.api.builder.Message.Level.ERROR).toString(), + kb.getResults().hasMessages(org.kie.api.builder.Message.Level.ERROR)); + InternalKieModule kieModule = (InternalKieModule) ks.getRepository().getKieModule(releaseId); + byte[] jar = kieModule.getBytes(); + + try { + FileOutputStream fos = new FileOutputStream("target/baz-2.1.0.GA.jar"); + fos.write(jar); + fos.close(); + } catch (FileNotFoundException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } + + repository = getMavenRepository(); + repository.deployArtifact(releaseId, jar, pom); + return jar; + } + + private void startServer() throws Exception { + server = new TJWSEmbeddedJaxrsServer(); + server.setPort(PORT); + server.start(); + server.getDeployment().getRegistry().addSingletonResource(new KieServerImpl()); + } + + private void startClient() throws Exception { + client = new KieServicesClient("http://localhost:" + PORT + "/server"); + } + + private static void createAndDeployKJar() { + String drl = "package org.pkg1\n" + + "global java.util.List list;" + + "declare Message\n" + + " text : String\n" + + "end\n" + + "rule echo dialect \"mvel\"\n" + + "when\n" + + " $m : Message()\n" + + "then\n" + + " $m.text = \"echo:\" + $m.text;\n" + + "end\n" + + "rule X when\n" + + " msg : String()\n" + + "then\n" + + " list.add(msg);\n" + + "end\n"; + KieServices ks = KieServices.Factory.get(); + releaseId = new ReleaseId("foo.bar", "baz", "2.1.0.GA"); + createAndDeployJar(ks, releaseId, drl); + + // make sure it is not deployed in the in-memory repository + ks.getRepository().removeKieModule(releaseId); + } + + public static int findFreePort() { + int port = 0; + try { + ServerSocket server = + new ServerSocket(0); + port = server.getLocalPort(); + server.close(); + } catch (IOException e) { + // failed to dynamically allocate port, try to use hard coded one + port = 9789; + } + System.out.println("Allocating port: "+port); + return port; + } + +} diff --git a/kie-server/pom.xml b/kie-server/pom.xml new file mode 100644 index 0000000000..d7b8462616 --- /dev/null +++ b/kie-server/pom.xml @@ -0,0 +1,54 @@ + + 4.0.0 + + + org.kie + kie-parent-with-dependencies + 6.2.0-SNAPSHOT + + + org.kie + kie-server + pom + + KIE :: Execution Server + KIE Execution Server + + + kie-server-api + kie-server-client + kie-server-services + + + + + + + org.kie + kie-server-api + ${project.version} + + + org.kie + kie-server-client + ${project.version} + + + org.kie + kie-server-services + ${project.version} + + + org.apache.cxf + cxf-rt-management + 2.7.11 + + + org.apache.cxf + cxf-rt-transports-local + 2.7.11 + + + +