/* * The Kuali Financial System, a comprehensive financial management system for higher education. * * Copyright 2005-2014 The Kuali Foundation * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * This program 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 Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package org.kuali.kfs.sys.context; import java.util.concurrent.Executor; import java.util.concurrent.Executors; /** * This class should be used in the development environment to run the batch container, execute one or more steps, then shut down the batch container. */ public class BatchStepLauncher implements Runnable { private static final String LOG_PREFIX = BatchStepLauncher.class.getName() +": "; private static final String batchContainerStep = "batchContainerStep"; private static BatchStepTriggerParameters batchStepTriggerParms; /** * This class validates the arguments, adds a shutdown hook to Runtime to clean up BatchContainer's semaphore, starts the batch container, * and executes steps using the BatchStepTrigger. * * The BatchStepTrigger will exit the system using calls to System.exit(). This will cause this Launcher class to exit immediately without executing any further * methods. Therefore the batch container cannot be shut down using the iu.stopBatchContainerStep which nicely cleans up its own semaphore. The shutdown hook has been * added in order for this cleanup to occur. * * @param args the String[] arguments normally passed to BatchStepTrigger */ public static void main(String[] args) { //check arguments for the trigger checkArguments(args); //run the Batch Container in its own thread startBatchContainer(); //confirm that the container started up before executing the steps //-uses batch container directory specified in args confirmStartUp(); //execute one or more steps executeSteps(args); //the batch container will be shut down by the thread hook added to the Runtime in setUp() } /** * Run the Batch Container in its own thread */ @Override public void run() { String[] args = new String[2]; args[0] = batchContainerStep; args[1] = (batchStepTriggerParms != null ? batchStepTriggerParms.getJobName(): "unknown"); BatchStepRunner.main(args); } /** * Uses the BatchStepTriggerParameters class to validate the arguments passed to the launcher. * * @param args String[] of arguments that would normally passed to BatchStepTrigger */ private static void checkArguments(String[] args) { logToOut("checking arguments"); batchStepTriggerParms = new BatchStepTriggerParameters(args); logToOut("received valid arguments"); } /** * Start the batch container in its own Thread */ private static void startBatchContainer() { logToOut("starting the batch container"); Executor executor = Executors.newCachedThreadPool(); BatchStepLauncher batchStepLauncher = new BatchStepLauncher(); executor.execute(batchStepLauncher); } /** * Loops and polls for the batch container start up (looks for the .runlock) */ private static void confirmStartUp() { logToOut("confirming batch container start up"); while (!batchStepTriggerParms.getBatchContainerDirectory().isBatchContainerRunning()) { logToOut("waiting for the batch container to start up"); try { Thread.sleep(batchStepTriggerParms.getSleepInterval()); } catch (InterruptedException e) { throw new RuntimeException("BatchStepLauncher encountered interrupt exception while trying to wait for the batch container to start up", e); } } logToOut("batch container is running"); } /** * Calls BatchStepTrigger to execute steps * * @param args String[] arguments normally passed to the BatchStepTrigger */ private static void executeSteps(String[] args) { logToOut("executing step(s)"); BatchStepTrigger.main(args); logToOut("finished executing step(s)"); } /** * Removes the batch container semaphore (used by the shutdown hook added to Runtime) * This is necessary because the Launcher exits immediately when the Trigger exits. Shutdown hook cleans up the semaphore. */ private static void removeBatchContainerSemaphore() { logToOut("removing batch container semaphore file"); if (batchStepTriggerParms.getBatchContainerDirectory().isBatchContainerRunning()) { batchStepTriggerParms.getBatchContainerDirectory().removeBatchContainerSemaphore(); } logToOut("batch container semaphore file has been removed"); } /** * Logs statement to System.out with a prefix. * * @param statement the statement to log */ private static void logToOut(String statement) { System.out.println(LOG_PREFIX + statement); } }