/**
* 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.drools.guvnor.server;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.Reader;
import java.io.StringReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.drools.definition.process.Connection;
import org.drools.definition.process.Node;
import org.drools.guvnor.client.rpc.RuleAsset;
import org.drools.guvnor.client.rpc.RuleFlowContentModel;
import org.drools.guvnor.server.contenthandler.BPMN2ProcessHandler;
import org.drools.guvnor.server.util.LoggingHelper;
import org.drools.xml.SemanticModules;
import org.jbpm.bpmn2.xml.BPMNDISemanticModule;
import org.jbpm.bpmn2.xml.BPMNSemanticModule;
import org.jbpm.bpmn2.xml.XmlBPMNProcessDumper;
import org.jbpm.compiler.xml.XmlProcessReader;
import org.jbpm.ruleflow.core.RuleFlowProcess;
import org.jbpm.workflow.core.Constraint;
import org.jbpm.workflow.core.impl.ConstraintImpl;
import org.jbpm.workflow.core.node.Split;
import org.jbpm.workflow.core.node.StartNode;
import com.google.gwt.user.client.rpc.SerializationException;
/**
* A servlet opening an API into the Guvnor services.
*
* @author <a href="mailto:atoulme@intalio.com">Antoine Toulme</a>
*/
public class GuvnorAPIServlet extends HttpServlet {
private static final LoggingHelper log = LoggingHelper.getLogger(GuvnorAPIServlet.class);
public void service(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
log.debug("Incoming request for Guvnor API:" + request.getRequestURL());
String action = request.getParameter("action");
if ("load".equals(action)) {
String uuid = request.getParameter("uuid");
if (uuid == null) {
throw new ServletException(new IllegalArgumentException("The load action requires the parameter uuid"));
}
try {
RuleAsset asset = RepositoryServiceServlet.getService().loadRuleAsset(uuid);
if (asset.content != null) {
response.setContentType("application/json");
String content = null;
if (asset.content instanceof RuleFlowContentModel) {
content = ((RuleFlowContentModel) asset.content).getXml();
} else {
content = asset.content.toString();
}
try {
// TODO fix for non-localhost
content = deserialize(
"http://localhost:8080/designer/bpmn2_0deserialization", content);
} catch (IOException e) {
log.error(e.getMessage(), e);
throw new ServletException(e.getMessage(), e);
}
log.debug("Sending model");
log.debug(content);
log.debug("End of sending model");
response.setContentLength(content.getBytes().length);
response.getOutputStream().write(content.getBytes());
response.getOutputStream().close();
}
} catch (SerializationException e) {
log.error(e.getMessage(), e);
throw new ServletException(e.getMessage(), e);
}
} else if ("extract".equals(action)) {
String json = request.getParameter("json");
try {
Map<String, String[]> result = extract(json);
response.setContentType("application/json");
log.debug("extracting");
String s = "";
int i = 0;
for (Map.Entry<String, String[]> entry: result.entrySet()) {
log.debug(entry.getKey() + " " + entry.getValue()[0] + " " + entry.getValue()[1]);
s += entry.getKey() + "#" + entry.getValue()[0] + "#" + entry.getValue()[1];
if (i++ != result.size() - 1) {
s += "###";
}
}
log.debug("End of extracting");
response.setContentLength(s.length());
response.getOutputStream().write(s.getBytes());
response.getOutputStream().close();
} catch (Throwable t) {
throw new ServletException(t);
}
} else if ("inject".equals(action)) {
String json = request.getParameter("json");
try {
Map<String, String> constraints = new HashMap<String, String>();
String[] s = request.getParameterValues("constraint");
for (String c: s) {
String nodeId = c.substring(0, c.indexOf(":"));
String rule = c.substring(c.indexOf(":") + 1);
constraints.put(nodeId, rule);
}
String result = inject(json, constraints);
response.setContentType("application/json");
log.debug("injecting");
for (Map.Entry<String, String> entry: constraints.entrySet()) {
log.debug(entry.getKey() + " " + entry.getValue());
}
log.debug(result);
log.debug("End of injecting");
response.setContentLength(result.length());
response.getOutputStream().write(result.getBytes());
response.getOutputStream().close();
} catch (Throwable t) {
throw new ServletException(t);
}
} else {
throw new ServletException(new IllegalArgumentException("The servlet requires a parameter named action"));
}
}
public static String deserialize(String deserializeUrl, String modelXml) throws IOException {
OutputStream out = null;
InputStream content = null;
ByteArrayOutputStream bos = null;
try {
URL bpmn2_0SerializationURL = new URL(deserializeUrl);
modelXml = "data=" + URLEncoder.encode(modelXml, "UTF-8");
byte[] bytes = modelXml.getBytes("UTF-8");
HttpURLConnection connection = (HttpURLConnection) bpmn2_0SerializationURL.openConnection();
connection.setRequestMethod("POST");
connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
connection.setFixedLengthStreamingMode(bytes.length);
connection.setDoOutput(true);
out = connection.getOutputStream();
out.write(bytes);
out.close();
content = connection.getInputStream();
bos = new ByteArrayOutputStream();
int b = 0;
while ((b = content.read()) > -1) {
bos.write(b);
}
bytes = bos.toByteArray();
content.close();
bos.close();
return new String(bytes);
} finally {
try {
if (out != null) {
out.close();
}
if (content != null) {
content.close();
}
if (bos != null) {
bos.close();
}
} catch (IOException e) {
}
}
}
public static Map<String, String[]> extract(String json) throws Exception {
Map<String, String[]> result = null;
String xml = BPMN2ProcessHandler.serialize(
"http://localhost:8080/designer/bpmn2_0serialization", json);
Reader isr = new StringReader(xml);
SemanticModules semanticModules = new SemanticModules();
semanticModules.addSemanticModule(new BPMNSemanticModule());
semanticModules.addSemanticModule(new BPMNDISemanticModule());
XmlProcessReader xmlReader = new XmlProcessReader(semanticModules);
RuleFlowProcess process = (RuleFlowProcess) xmlReader.read(isr);
if (process == null) {
throw new IllegalArgumentException("Could not read process");
} else {
log.debug("Processing " + process.getId());
result = new HashMap<String, String[]>();
StartNode start = process.getStart();
Node target = start.getTo().getTo();
if (target instanceof Split) {
Split split = (Split) target;
for (Connection connection: split.getDefaultOutgoingConnections()) {
Constraint constraint = split.getConstraint(connection);
if (constraint != null) {
System.out.println("Found constraint to node " + connection.getTo().getName() + " [" + connection.getTo().getId() + "]: " + constraint.getConstraint());
result.put(XmlBPMNProcessDumper.getUniqueNodeId(connection.getTo()), new String[] { connection.getTo().getName(), constraint.getConstraint() });
}
}
}
}
if (isr != null) {
isr.close();
}
return result;
}
public static String inject(String json, Map<String, String> constraints) throws Exception {
String xml = BPMN2ProcessHandler.serialize(
"http://localhost:8080/designer/bpmn2_0serialization", json);
Reader isr = new StringReader(xml);
SemanticModules semanticModules = new SemanticModules();
semanticModules.addSemanticModule(new BPMNSemanticModule());
semanticModules.addSemanticModule(new BPMNDISemanticModule());
XmlProcessReader xmlReader = new XmlProcessReader(semanticModules);
RuleFlowProcess process = (RuleFlowProcess) xmlReader.read(isr);
isr.close();
if (process == null) {
throw new IllegalArgumentException("Could not read process");
} else {
log.debug("Processing " + process.getId());
StartNode start = process.getStart();
Node target = start.getTo().getTo();
if (target instanceof Split) {
Split split = (Split) target;
for (Connection connection: split.getDefaultOutgoingConnections()) {
String s = constraints.get(XmlBPMNProcessDumper.getUniqueNodeId(connection.getTo()));
if (s != null) {
System.out.println("Found constraint to node " + connection.getTo().getName() + ": " + s);
Constraint constraint = split.getConstraint(connection);
if (constraint == null) {
constraint = new ConstraintImpl();
split.setConstraint(connection, constraint);
}
constraint.setConstraint(s);
}
}
}
String newXml = XmlBPMNProcessDumper.INSTANCE.dump(process);
System.out.println(newXml);
return deserialize("http://localhost:8080/designer/bpmn2_0deserialization", newXml);
}
}
}