/*
* JBoss, Home of Professional Open Source
* Copyright 2006, JBoss Inc., and individual contributors as indicated
* by the @authors tag. See the copyright.txt in the distribution for a
* full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.jboss.soa.esb.services.jbpm;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import java.io.IOException;
import java.io.Serializable;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.HashMap;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.KeyGenerator;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SealedObject;
import javax.crypto.SecretKey;
import junit.framework.JUnit4TestAdapter;
import org.apache.log4j.Logger;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.dom4j.tree.DefaultElement;
import org.jboss.soa.esb.message.Message;
import org.jboss.soa.esb.message.format.MessageFactory;
import org.jboss.soa.esb.services.security.SecurityService;
import org.jbpm.graph.def.Node;
import org.jbpm.graph.def.ProcessDefinition;
import org.jbpm.graph.def.Transition;
import org.jbpm.graph.exe.ExecutionContext;
import org.jbpm.graph.exe.ProcessInstance;
import org.jbpm.graph.exe.Token;
import org.junit.BeforeClass;
import org.junit.Test;
/**
* Tests the capabilities of the JBpmObjectMapper.
*
* @author kstam
* @author <a href="mailto:dbevenius@jboss.com">Daniel Bevenius</a>
*
*/
public class JBpmObjectMapperUnitTest
{
private static String PROCESS_DEF_XML = "JBpmObjectMapperTestProcessDefinition.xml";
private static Logger logger = Logger.getLogger(JBpmObjectMapperUnitTest.class);
private static ProcessInstance processInstance = null;
private static JBpmObjectMapper mapper;
@BeforeClass
public static void setup()
{
logger.info("Setting up jBPM");
//Extract a process definition from the processdefinition.xml file.
ProcessDefinition processDefinition
= ProcessDefinition.parseXmlResource(PROCESS_DEF_XML);
assertNotNull(processDefinition);
//Create an instance of the process definition.
processInstance = new ProcessInstance(processDefinition);
assertTrue(
"Instance is in start state",
"start".equals(processInstance.getRootToken().getNode().getName()));
mapper = new JBpmObjectMapper();
}
/**
* Tests obtaining variables from the jBPM variableMap and setting them on the EsbMessage.
* We are making sure the jBPM -> EsbMessage works using
*
* <pre>
* <jbpmToEsbVars>
* <mapping jbpm="v1" esb="esbObj1" />
* <mapping jbpm="g2" esb="esbObj2" process-scope="true" />
* </jbpmToEsbVars>
* <pre>
*
* @throws Exception
*/
@Test
public void jBpmVariableMap() throws Exception
{
SAXReader reader = new SAXReader();
Document document = reader.read(this.getClass().getResourceAsStream("/" + PROCESS_DEF_XML));
Element element = document.getRootElement();
DefaultElement bpmToEsbVars = (DefaultElement) element.element("start-state").element("transition").element("action").element("bpmToEsbVars");
String helloWorldTokenScope = "Hello world token scope";
String helloWorldGlobalScope = "Hello world process-instance scope";
TestJBPMVariable objectTokenScope = new TestJBPMVariable("Object token scope") ;
TestJBPMVariable objectGlobalScope = new TestJBPMVariable("Object global scope") ;
Token token = processInstance.getRootToken();
processInstance.getContextInstance().setVariable("v1", helloWorldTokenScope, token);
processInstance.getContextInstance().setVariable("g2", helloWorldGlobalScope);
processInstance.getContextInstance().setVariable("h3", objectTokenScope, token);
processInstance.getContextInstance().setVariable("i4", objectGlobalScope);
ExecutionContext executionContext = new ExecutionContext(token);
JBpmObjectMapper mapper = new JBpmObjectMapper();
Message message = mapper.mapFromJBpmToEsbMessage(bpmToEsbVars, Boolean.FALSE, executionContext);
assertEquals(helloWorldTokenScope,String.valueOf(message.getBody().get("esbObj1")));
assertEquals(helloWorldGlobalScope,String.valueOf(message.getBody().get("esbObj2")));
assertEquals(objectTokenScope.getInternal(), String.valueOf(message.getBody().get("esbObj3")));
assertEquals(objectGlobalScope.getInternal(), String.valueOf(message.getBody().get("esbObj4")));
}
/**
* Tests obtaining *no* variables from the jBPM variableMap.
*
* @throws Exception
*/
@Test
public void jBpmCompleteVariableMap() throws Exception
{
//Let's NOT give a mapping, this should get us all the variables in the VariableMap.
DefaultElement jbpmToEsbVars = null;
String helloWorldTokenScope = "Hello world token scope";
String helloWorldGlobalScope = "Hello world process-instance scope";
TestJBPMVariable objectTokenScope = new TestJBPMVariable("Object token scope") ;
TestJBPMVariable objectGlobalScope = new TestJBPMVariable("Object global scope") ;
Token token = processInstance.getRootToken();
processInstance.getContextInstance().createVariable("v1", helloWorldTokenScope, token);
processInstance.getContextInstance().createVariable("g2", helloWorldGlobalScope);
processInstance.getContextInstance().createVariable("h3", objectTokenScope, token);
processInstance.getContextInstance().createVariable("i4", objectGlobalScope);
ExecutionContext executionContext = new ExecutionContext(token);
JBpmObjectMapper mapper = new JBpmObjectMapper();
Message message = mapper.mapFromJBpmToEsbMessage(jbpmToEsbVars, Boolean.FALSE, executionContext);
assertEquals(message.getBody().getNames().length,0);
}
/**
* Tests obtaining *all* variables from the jBPM variableMap and setting them on the EsbMessage.
*
* @throws Exception
*/
@Test
public void jBpmGetNothingFromVariableMap() throws Exception
{
SAXReader reader = new SAXReader();
Document document = reader.read(this.getClass().getResourceAsStream("/" + PROCESS_DEF_XML));
Element element = document.getRootElement();
Element secondMiddleState = (Element) element.elements("state").toArray()[0];
DefaultElement bpmToEsbVars = (DefaultElement) secondMiddleState.element("transition").element("action").element("bpmToEsbVars");
String helloWorldTokenScope = "Hello world token scope";
String helloWorldGlobalScope = "Hello world process-instance scope";
TestJBPMVariable objectTokenScope = new TestJBPMVariable("Object token scope") ;
TestJBPMVariable objectGlobalScope = new TestJBPMVariable("Object global scope") ;
Token token = processInstance.getRootToken();
processInstance.getContextInstance().createVariable("v1", helloWorldTokenScope, token);
processInstance.getContextInstance().createVariable("g2", helloWorldGlobalScope);
processInstance.getContextInstance().createVariable("h3", objectTokenScope, token);
processInstance.getContextInstance().createVariable("i4", objectGlobalScope);
ExecutionContext executionContext = new ExecutionContext(token);
JBpmObjectMapper mapper = new JBpmObjectMapper();
Message message = mapper.mapFromJBpmToEsbMessage(bpmToEsbVars, Boolean.FALSE, executionContext);
//We should find 2 variables which are named just like their jBPM counterparts.
assertEquals(message.getBody().getNames().length,4);
assertEquals(String.valueOf(message.getBody().get("v1")),helloWorldTokenScope);
assertEquals(String.valueOf(message.getBody().get("g2")),helloWorldGlobalScope);
assertEquals(message.getBody().get("h3"), objectTokenScope);
assertEquals(message.getBody().get("i4"), objectGlobalScope);
}
/**
* Tests obtaining info about the jBPM ExecutionContext, such as current token and node, transition etc.
* <PRE>
* <jbpmToEsbVars>
* <mapping jbpm="token.id" esb="esbTokenId" />
* <mapping jbpm="token.name" esb="esbTokenName" />
* <mapping jbpm="node.name" esb="NodeName" />
* <mapping jbpm="node.id" esb="esbNodeId" />
* <mapping jbpm="node.leavingTransitions[0].name" esb="transName" />
* <mapping jbpm="processInstance.id" esb="piId" />
<mapping jbpm="processInstance.version" esb="piVersion" />
* </jbpmToEsbVars>
* </PRE>
* @throws Exception
*/
@Test
public void jBpmTokenInfo() throws Exception
{
SAXReader reader = new SAXReader();
Document document = reader.read(this.getClass().getResourceAsStream("/" + PROCESS_DEF_XML));
Element element = document.getRootElement();
Element secondMiddleState = (Element) element.elements("state").toArray()[1];
DefaultElement bpmToEsbVars = (DefaultElement) secondMiddleState.element("transition").element("action").element("bpmToEsbVars");
Token token = processInstance.getRootToken();
ExecutionContext executionContext = new ExecutionContext(token);
Node node = executionContext.getNode();
Transition transition = (Transition) node.getLeavingTransitions().get(0);
JBpmObjectMapper mapper = new JBpmObjectMapper();
Message message = mapper.mapFromJBpmToEsbMessage(bpmToEsbVars, Boolean.FALSE, executionContext);
assertEquals(message.getBody().getNames().length,6);
assertEquals(String.valueOf(String.valueOf(message.getBody().get("TokenId"))), String.valueOf(token.getId()));
//The token name is null.
assertNull(message.getBody().get("TokenName"));
//Get info about the node.
assertEquals(String.valueOf(String.valueOf(message.getBody().get("NodeName"))), String.valueOf(node.getName()));
assertEquals(String.valueOf(String.valueOf(message.getBody().get("esbNodeId"))), String.valueOf(node.getId()));
assertEquals(String.valueOf(String.valueOf(message.getBody().get("transName"))), String.valueOf(transition.getName()));
assertEquals(String.valueOf(String.valueOf(message.getBody().get("piId"))), String.valueOf(processInstance.getId()));
assertEquals(String.valueOf(String.valueOf(message.getBody().get("piVersion"))), String.valueOf(processInstance.getVersion()));
logger.info("Message=" + message);
}
@Test
public void ensureSecurityContextWasMappedToJbpmMap() throws InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException, IllegalBlockSizeException, IOException
{
final SealedObject securityContext = createSealedObject("dummy string");
final Message message = MessageFactory.getInstance().getMessage();
message.getContext().setContext(SecurityService.CONTEXT, securityContext);
final HashMap<String,?> map = mapper.mapSecurityContextFromEsbMessageToJBpmMap(message);
assertNotNull("Should never return null. Can return an empty map though", map);
assertTrue(map.containsKey(Constants.SECURITY_CONTEXT));
}
@Test
public void ensureAuthRequestWasMappedToJbpmMap() throws InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException, IllegalBlockSizeException, IOException
{
// Doesn't need to be encrypted as this is only passed along and never descrypted.
byte[] encryptedAuthRequest = new byte[100];
final Message message = MessageFactory.getInstance().getMessage();
message.getContext().setContext(SecurityService.AUTH_REQUEST, encryptedAuthRequest);
final HashMap<String,?> map = mapper.mapAuthRequestFromEsbMessageToJBpmMap(message);
assertNotNull("Should never return null. Can return an empty map though", map);
assertTrue(map.containsKey(Constants.AUTH_REQUEST));
}
public static junit.framework.Test suite(){
return new JUnit4TestAdapter(JBpmObjectMapperUnitTest.class);
}
private SealedObject createSealedObject(final Serializable ser) throws NoSuchAlgorithmException, NoSuchPaddingException, IllegalBlockSizeException, IOException, InvalidKeyException
{
final KeyGenerator kpg = KeyGenerator.getInstance("TripleDES");
kpg.init(112);
final SecretKey secretKey = kpg.generateKey();
final Cipher cipher = Cipher.getInstance("TripleDES");
cipher.init(Cipher.ENCRYPT_MODE, secretKey);
return new SealedObject(ser, cipher);
}
}