/*
* Copyright (c) 2011, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.wso2.carbon.humantask.core;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.wso2.carbon.humantask.core.api.event.HumanTaskEventListener;
import org.wso2.carbon.humantask.core.api.scheduler.Scheduler;
import org.wso2.carbon.humantask.core.configuration.HumanTaskServerConfiguration;
import org.wso2.carbon.humantask.core.dao.HumanTaskDAOConnectionFactory;
import org.wso2.carbon.humantask.core.db.Database;
import org.wso2.carbon.humantask.core.engine.HumanTaskEngine;
import org.wso2.carbon.humantask.core.engine.HumanTaskServerException;
import org.wso2.carbon.humantask.core.engine.PeopleQueryEvaluator;
import org.wso2.carbon.humantask.core.engine.event.processor.EventProcessor;
import org.wso2.carbon.humantask.core.scheduler.JobProcessorImpl;
import org.wso2.carbon.humantask.core.scheduler.NotificationScheduler;
import org.wso2.carbon.humantask.core.scheduler.SimpleScheduler;
import org.wso2.carbon.humantask.core.store.HumanTaskStoreManager;
import org.wso2.carbon.humantask.core.utils.GUID;
import org.wso2.carbon.utils.CarbonUtils;
import javax.transaction.TransactionManager;
import java.io.File;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;
/**
* Human Task Server which is responsible for initializing data sources, task store, schedulers and
* other resources used by Task Engine.
*/
public class HumanTaskServer {
private static final Log log = LogFactory.getLog(HumanTaskServer.class);
/**
* The human task server configurations
*/
private HumanTaskServerConfiguration serverConfig;
/**
* The task engine
*/
private HumanTaskEngine taskEngine;
/**
* The human task database representation
*/
private Database database;
/**
* The task store manager
*/
private HumanTaskStoreManager taskStoreManager;
/**
* The transaction manager
*/
private TransactionManager tnxManager;
/**
* The dao connection factory
*/
private HumanTaskDAOConnectionFactory daoConnectionFactory;
/**
* Human task scheduler
*/
private Scheduler scheduler;
private EventProcessor eventProcessor;
/**
* The initialisation logic for the human task server.
*
* @throws HumanTaskServerException : If the server initialisation fails.
*/
public void init() throws HumanTaskServerException {
loadHumanTaskServerConfiguration();
initTransactionManager();
initDataSource();
initDAO();
initEventProcessor();
initHumanTaskEngine();
initPeopleQueryEvaluator();
initHumanTaskStore();
initScheduler();
initNotificationScheduler();
}
/**
* Notification scheduler initialisation.
*/
private void initNotificationScheduler() {
NotificationScheduler notificationScheduler = new NotificationScheduler();
taskEngine.setNotificationScheduler(notificationScheduler);
}
/**
* Scheduler initialisation.
*/
private void initScheduler() {
ThreadFactory threadFactory = new ThreadFactory() {
private int threadNumber = 0;
public Thread newThread(Runnable r) {
threadNumber += 1;
Thread t = new Thread(r, "HumanTaskServer-" + threadNumber);
t.setDaemon(true);
return t;
}
};
ExecutorService executorService = Executors.
newFixedThreadPool(serverConfig.getThreadPoolMaxSize(), threadFactory);
SimpleScheduler simpleScheduler = new SimpleScheduler(new GUID().toString());
simpleScheduler.setExecutorService(executorService);
simpleScheduler.setTransactionManager(tnxManager);
taskEngine.setScheduler(simpleScheduler);
simpleScheduler.setJobProcessor(new JobProcessorImpl());
// Start the scheduler within the HumanTaskSchedulerInitializer to ensure that all the tasks are deployed
// when the scheduler actually starts.
// simpleScheduler.start();
scheduler = simpleScheduler;
}
/**
* @throws HumanTaskServerException :
*/
private void initPeopleQueryEvaluator() throws HumanTaskServerException {
try {
PeopleQueryEvaluator peopleQueryEvaluator = (PeopleQueryEvaluator)
Class.forName(serverConfig.getPeopleQueryEvaluatorClass()).newInstance();
taskEngine.setPeopleQueryEvaluator(peopleQueryEvaluator);
} catch (Exception ex) {
String errMsg = "Error instantiating the PeopleQueryEvaluator Class :" +
serverConfig.getPeopleQueryEvaluatorClass();
throw new HumanTaskServerException(errMsg, ex);
}
}
// Initialises the human task engine.
private void initHumanTaskEngine() {
HumanTaskEngine humanTaskEngine = new HumanTaskEngine();
humanTaskEngine.setDaoConnectionFactory(this.daoConnectionFactory);
humanTaskEngine.setEventProcessor(this.eventProcessor);
this.taskEngine = humanTaskEngine;
}
// Initialises the data source with the provided configuration parameters.
private void initDataSource() throws HumanTaskServerException {
database = new Database(serverConfig);
//TODO - need to handle the external transaction managers.
database.setTransactionManager(tnxManager);
try {
database.start();
} catch (Exception e) {
String errMsg = "Humantask Database Initialization failed.";
throw new HumanTaskServerException(errMsg, e);
}
}
/**
* Initialize the data access layer.
*
* @throws HumanTaskServerException : If the dao layer initializing fails..
*/
private void initDAO() throws HumanTaskServerException {
try {
this.daoConnectionFactory = database.createDAOConnectionFactory();
} catch (Exception e) {
String errMsg = "Error instantiating the DAO Connection Factory Class :" +
serverConfig.getDaoConnectionFactoryClass();
throw new HumanTaskServerException(errMsg, e);
}
}
//
/**
* Event processor initialisation logic.
* As of now we have a set of event listeners which we register at the server startup.
*
* @throws HumanTaskServerException : If the event listener object instantiation fails.
*/
private void initEventProcessor() throws HumanTaskServerException {
EventProcessor eventProcessor = new EventProcessor();
for (String eventListenerClassName : serverConfig.getEventListenerClassNames()) {
try {
Class eventListenerClass = this.getClass().getClassLoader().loadClass(eventListenerClassName);
HumanTaskEventListener eventListener = (HumanTaskEventListener) eventListenerClass.newInstance();
eventProcessor.addEventListener(eventListener);
} catch (Exception e) {
log.fatal("Couldn't initialize the event listener for class: "
+ eventListenerClassName, e);
throw new HumanTaskServerException("Couldn't initialize a event listener: "
+ eventListenerClassName, e);
}
}
this.eventProcessor = eventProcessor;
}
/**
* Initialize human task stores and reload existing tasks if necessary.
*/
private void initHumanTaskStore() {
taskStoreManager = new HumanTaskStoreManager();
}
/**
* Read the human task configuration file and load it to memory. If configuration file is not there default
* configuration will be created.
*/
private void loadHumanTaskServerConfiguration() {
if (log.isDebugEnabled()) {
log.debug("Loading Human Task Server Configuration...");
}
if (isHumanTaskConfigurationFileAvailable()) {
File htServerConfigFile = new File(calculateHumanTaskServerConfigurationFilePath());
serverConfig = new HumanTaskServerConfiguration(htServerConfigFile);
} else {
log.info("Humantask configuration file: " + HumanTaskConstants.HUMANTASK_CONFIG_FILE +
" not found. Loading default configurations.");
serverConfig = new HumanTaskServerConfiguration();
}
}
/**
* @return : true is the configuration file is in the file system false otherwise.
*/
private boolean isHumanTaskConfigurationFileAvailable() {
File humanTaskConfigurationFile = new File(calculateHumanTaskServerConfigurationFilePath());
return humanTaskConfigurationFile.exists();
}
/**
* Note: Need to figure out how to merge this with bps.xml
*
* @return Human task server configuration path.
*/
private String calculateHumanTaskServerConfigurationFilePath() {
return CarbonUtils.getCarbonConfigDirPath() + File.separator +
HumanTaskConstants.HUMANTASK_CONFIG_FILE;
}
/**
* @return : The human task store manager.
*/
public HumanTaskStoreManager getTaskStoreManager() {
return taskStoreManager;
}
/**
* @return : The taskEngine.
*/
public HumanTaskEngine getTaskEngine() {
return taskEngine;
}
/**
* @return : The human task database.
*/
public Database getDatabase() {
return this.database;
}
// initialize the external transaction manager.
private void initTransactionManager() throws HumanTaskServerException {
String transactionFactoryName = serverConfig.getTransactionFactoryClass();
if (log.isDebugEnabled()) {
log.debug("Initializing transaction manager using " + transactionFactoryName);
}
try {
Class txFactoryClass = this.getClass().getClassLoader().loadClass(transactionFactoryName);
Object txFactory = txFactoryClass.newInstance();
tnxManager = (TransactionManager) txFactoryClass.
getMethod("getTransactionManager", (Class[]) null).invoke(txFactory);
// Didn't use Debug Transaction manager which used in ODE.
// TODO: Look for the place we use this axis parameter.
//axisConfiguration.addParameter("ode.transaction.manager", transactionManager);
} catch (Exception e) {
log.fatal("Couldn't initialize a transaction manager with factory: "
+ transactionFactoryName, e);
throw new HumanTaskServerException("Couldn't initialize a transaction manager with factory: "
+ transactionFactoryName, e);
}
}
/**
* @return : The server configuration information.
*/
public HumanTaskServerConfiguration getServerConfig() {
return serverConfig;
}
/**
* @return : The DAO Connection Factory.
*/
public HumanTaskDAOConnectionFactory getDaoConnectionFactory() {
return daoConnectionFactory;
}
/**
* The shutdown logic for the human task server.
*/
public void shutdown() {
if (scheduler != null) {
try {
log.debug("shutting down scheduler.");
scheduler.shutdown();
scheduler = null;
} catch (Exception ex) {
log.error("Scheduler couldn't be shutdown.", ex);
}
}
}
}