/**
* Copyright 2010 Red Hat, Inc. and/or its affiliates.
*
* 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.jbpm.services.task;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.io.StringWriter;
import java.lang.reflect.Field;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
import org.jbpm.persistence.util.PersistenceUtil;
import org.jbpm.process.instance.impl.util.LoggingPrintStream;
import org.jbpm.services.task.impl.model.xml.JaxbContent;
import org.jbpm.services.task.util.CountDownTaskEventListener;
import org.jbpm.services.task.utils.ContentMarshallerHelper;
import org.jbpm.services.task.utils.MVELUtils;
import org.junit.AfterClass;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.kie.api.task.TaskLifeCycleEventListener;
import org.kie.api.task.model.Content;
import org.kie.internal.task.api.EventService;
import org.kie.internal.task.api.InternalTaskService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import bitronix.tm.TransactionManagerServices;
import bitronix.tm.resource.jdbc.PoolingDataSource;
public abstract class HumanTaskServicesBaseTest {
private static final Logger logger = LoggerFactory.getLogger(HumanTaskServicesBaseTest.class);
protected InternalTaskService taskService;
@BeforeClass
public static void configure() {
LoggingPrintStream.interceptSysOutSysErr();
}
@AfterClass
public static void reset() {
LoggingPrintStream.resetInterceptSysOutSysErr();
}
public void tearDown() {
if( taskService != null ) {
int removeAllTasks = taskService.removeAllTasks();
logger.debug("Number of tasks removed {}", removeAllTasks);
}
}
@SuppressWarnings({"unchecked", "rawtypes"})
public static Map fillUsersOrGroups(String mvelFileName) throws Exception {
Map<String, Object> vars = new HashMap<String, Object>();
Reader reader = null;
Map<String, Object> result = null;
try {
reader = new InputStreamReader(HumanTaskServicesBaseTest.class.getResourceAsStream(mvelFileName));
result = (Map<String, Object>) MVELUtils.eval(reader, vars);
} finally {
if (reader != null) {
reader.close();
}
}
return result;
}
protected final static String mySubject = "My Subject";
protected final static String myBody = "My Body";
protected static Map<String, String> fillMarshalSubjectAndBodyParams() {
Map<String, String> params = new HashMap<String, String>();
params.put("subject", mySubject);
params.put("body", myBody);
return params;
}
protected static void checkContentSubjectAndBody(Object unmarshalledObject) {
assertTrue("Content is null.", unmarshalledObject != null && unmarshalledObject.toString() != null);
String content = unmarshalledObject.toString();
boolean match = false;
if (("{body=" + myBody + ", subject=" + mySubject + "}").equals(content)
|| ("{subject=" + mySubject + ", body=" + myBody + "}").equals(content)) {
match = true;
}
assertTrue("Content does not match.", match);
}
protected void printTestName() {
logger.info("Running {}.{} ", this.getClass().getSimpleName(), Thread.currentThread().getStackTrace()[2].getMethodName());
}
/**
* Creates date using default format - "yyyy-MM-dd"
*/
protected Date createDate(String dateString) {
return createDate(dateString, "yyyy-MM-dd");
}
protected Date createDate(String dateString, String dateFormat) {
SimpleDateFormat fmt = new SimpleDateFormat(dateFormat);
try {
return fmt.parse(dateString);
} catch (ParseException e) {
throw new RuntimeException("Can't create date from string '" + dateString + "' using '" + dateFormat + "' format!", e);
}
}
protected JaxbContent xmlRoundTripContent(Content content) {
JaxbContent xmlContent = new JaxbContent(content);
JaxbContent xmlCopy = null;
try {
Marshaller marshaller = JAXBContext.newInstance(JaxbContent.class).createMarshaller();
// marshal
StringWriter stringWriter = new StringWriter();
marshaller.marshal(xmlContent, stringWriter);
// unmarshal
Unmarshaller unmarshaller = JAXBContext.newInstance(JaxbContent.class).createUnmarshaller();
ByteArrayInputStream inputStream = new ByteArrayInputStream(stringWriter.toString().getBytes());
xmlCopy = (JaxbContent) unmarshaller.unmarshal(inputStream);
for(Field field : JaxbContent.class.getDeclaredFields()) {
field.setAccessible(true);
Object orig = field.get(xmlContent);
Object roundTrip = field.get(xmlCopy);
if( orig instanceof byte[] ) {
Assert.assertTrue(Arrays.equals((byte[]) orig, (byte[]) roundTrip));
} else {
Assert.assertEquals(field.getName(), orig, roundTrip);
}
}
} catch(Exception e) {
logger.error("Unable to complete round trip: " + e.getMessage(), e );
Assert.fail("Unable to complete round trip: " + e.getMessage());
}
Object orig = ContentMarshallerHelper.unmarshall(content.getContent(), null);
assertNotNull( "Round tripped JaxbContent is null!", xmlCopy );
Object roundTrip = ContentMarshallerHelper.unmarshall(xmlCopy.getContent(), null);
Assert.assertEquals(orig, roundTrip);
return xmlCopy;
}
protected static final String DATASOURCE_PROPERTIES = "/datasource.properties";
protected static final String MAX_POOL_SIZE = "maxPoolSize";
protected static final String ALLOW_LOCAL_TXS = "allowLocalTransactions";
protected static final String DATASOURCE_CLASS_NAME = "className";
protected static final String DRIVER_CLASS_NAME = "driverClassName";
protected static final String USER = "user";
protected static final String PASSWORD = "password";
protected static final String JDBC_URL = "url";
protected static PoolingDataSource setupPoolingDataSource() {
Properties dsProps = getDatasourceProperties();
PoolingDataSource pds = PersistenceUtil.setupPoolingDataSource(dsProps, "jdbc/jbpm-ds", false);
pds.init();
return pds;
}
/**
* This reads in the (maven filtered) datasource properties from the test
* resource directory.
*
* @return Properties containing the datasource properties.
*/
private static Properties getDatasourceProperties() {
boolean propertiesNotFound = false;
// Central place to set additional H2 properties
System.setProperty("h2.lobInDatabase", "true");
InputStream propsInputStream = HumanTaskServicesBaseTest.class.getResourceAsStream(DATASOURCE_PROPERTIES);
Properties props = new Properties();
if (propsInputStream != null) {
try {
props.load(propsInputStream);
} catch (IOException ioe) {
propertiesNotFound = true;
logger.warn("Unable to find properties, using default H2 properties: " + ioe.getMessage());
ioe.printStackTrace();
}
} else {
propertiesNotFound = true;
}
String password = props.getProperty("password");
if ("${maven.jdbc.password}".equals(password) || propertiesNotFound) {
logger.warn( "Unable to load datasource properties [" + DATASOURCE_PROPERTIES + "]" );
// If maven filtering somehow doesn't work the way it should..
setDefaultProperties(props);
}
return props;
}
/**
* Return the default database/datasource properties - These properties use
* an in-memory H2 database
*
* This is used when the developer is somehow running the tests but
* bypassing the maven filtering that's been turned on in the pom.
*
* @return Properties containing the default properties
*/
private static void setDefaultProperties(Properties props) {
String[] keyArr = {
"serverName", "portNumber", "databaseName", JDBC_URL,
USER, PASSWORD,
DRIVER_CLASS_NAME, DATASOURCE_CLASS_NAME,
MAX_POOL_SIZE, ALLOW_LOCAL_TXS };
String[] defaultPropArr = {
"", "", "", "jdbc:h2:mem:jbpm-db;MVCC=true",
"sa", "",
"org.h2.Driver", "bitronix.tm.resource.jdbc.lrc.LrcXADataSource",
"5", "true" };
Assert.assertTrue("Unequal number of keys for default properties", keyArr.length == defaultPropArr.length);
for (int i = 0; i < keyArr.length; ++i) {
if( ! props.containsKey(keyArr[i]) ) {
props.put(keyArr[i], defaultPropArr[i]);
}
}
}
protected void addCountDownListner(CountDownTaskEventListener countDownListener) {
if (taskService instanceof EventService) {
((EventService<TaskLifeCycleEventListener>) taskService).registerTaskEventListener(countDownListener);
}
}
}