TaskThreadedInitializationWrapper.java

/**
 * The contents of this file are subject to the OpenMRS Public License
 * Version 1.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://license.openmrs.org
 *
 * Software distributed under the License is distributed on an "AS IS"
 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
 * License for the specific language governing rights and limitations
 * under the License.
 *
 * Copyright (C) OpenMRS, LLC.  All Rights Reserved.
 */
package org.openmrs.scheduler.tasks;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.openmrs.scheduler.Task;
import org.openmrs.scheduler.TaskDefinition;

/**
 * This class executes the Task.initialize method in a new thread. Extend this class if you want
 * your {@link #initialize(TaskDefinition)} method to run in a new thread (and hence not hold up the
 * "startup" processes)
 */
public class TaskThreadedInitializationWrapper implements Task {
	
	// Logger 
	private Log log = LogFactory.getLog(TaskThreadedInitializationWrapper.class);
	
	private Task task;
	
	private boolean initialized = false;
	
	private final Lock lock = new ReentrantLock();
	
	private final Condition initializedCond = lock.newCondition();
	
	/**
	 * Default constructor to create this wrapper
	 * 
	 * @param task the Task to wrap around
	 */
	public TaskThreadedInitializationWrapper(Task task) {
		this.task = task;
	}
	
	/**
	 * @throws InterruptedException
	 * @see org.openmrs.scheduler.Task#execute() Executes the task defined in the task definition
	 *      but waits until the initialize method has finished
	 */
	public void execute() {
		lock.lock();
		try {
			while (!initialized) {
				initializedCond.await();
			}
		}
		catch (InterruptedException e) {
			log.error("Task could not be initialized hence not be executed.", e);
			return;
		}
		finally {
			lock.unlock();
		}
		
		task.execute();
	}
	
	/**
	 * @see org.openmrs.scheduler.Task#initialize(org.openmrs.scheduler.TaskDefinition) Initializes
	 *      the task and sets the task definition. This method is non-blocking by executing in a new
	 *      thread.
	 */
	public void initialize(final TaskDefinition config) {
		Runnable r = new Runnable() {
			
			public void run() {
				lock.lock();
				try {
					task.initialize(config);
					initialized = true;
					initializedCond.signalAll();
				}
				finally {
					lock.unlock();
				}
			}
		};
		
		new Thread(r).start();
	}
	
	/**
	 * @see org.openmrs.scheduler.Task#getTaskDefinition()
	 */
	public TaskDefinition getTaskDefinition() {
		return task != null ? task.getTaskDefinition() : null;
	}
	
	/**
	 * @see org.openmrs.scheduler.Task#isExecuting()
	 */
	public boolean isExecuting() {
		return task.isExecuting();
	}
	
	/**
	 * @see org.openmrs.scheduler.Task#shutdown()
	 */
	public void shutdown() {
		task.shutdown();
	}
}