1 /*
2 * The Kuali Financial System, a comprehensive financial management system for higher education.
3 *
4 * Copyright 2005-2014 The Kuali Foundation
5 *
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU Affero General Public License as
8 * published by the Free Software Foundation, either version 3 of the
9 * License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU Affero General Public License for more details.
15 *
16 * You should have received a copy of the GNU Affero General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19 package org.kuali.kfs.sys.context;
20
21 import java.util.concurrent.Executor;
22 import java.util.concurrent.Executors;
23
24 /**
25 * 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.
26 */
27 public class BatchStepLauncher implements Runnable {
28 private static final String LOG_PREFIX = BatchStepLauncher.class.getName() +": ";
29 private static final String batchContainerStep = "batchContainerStep";
30
31 private static BatchStepTriggerParameters batchStepTriggerParms;
32
33 /**
34 * This class validates the arguments, adds a shutdown hook to Runtime to clean up BatchContainer's semaphore, starts the batch container,
35 * and executes steps using the BatchStepTrigger.
36 *
37 * The BatchStepTrigger will exit the system using calls to System.exit(). This will cause this Launcher class to exit immediately without executing any further
38 * 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
39 * added in order for this cleanup to occur.
40 *
41 * @param args the String[] arguments normally passed to BatchStepTrigger
42 */
43 public static void main(String[] args) {
44
45 //check arguments for the trigger
46 checkArguments(args);
47
48 //run the Batch Container in its own thread
49 startBatchContainer();
50
51 //confirm that the container started up before executing the steps
52 //-uses batch container directory specified in args
53 confirmStartUp();
54
55 //execute one or more steps
56 executeSteps(args);
57
58 //the batch container will be shut down by the thread hook added to the Runtime in setUp()
59 }
60
61 /**
62 * Run the Batch Container in its own thread
63 */
64 @Override
65 public void run() {
66 String[] args = new String[2];
67 args[0] = batchContainerStep;
68 args[1] = (batchStepTriggerParms != null ? batchStepTriggerParms.getJobName(): "unknown");
69
70 BatchStepRunner.main(args);
71 }
72
73 /**
74 * Uses the BatchStepTriggerParameters class to validate the arguments passed to the launcher.
75 *
76 * @param args String[] of arguments that would normally passed to BatchStepTrigger
77 */
78 private static void checkArguments(String[] args) {
79 logToOut("checking arguments");
80
81 batchStepTriggerParms = new BatchStepTriggerParameters(args);
82
83 logToOut("received valid arguments");
84 }
85
86 /**
87 * Start the batch container in its own Thread
88 */
89 private static void startBatchContainer() {
90 logToOut("starting the batch container");
91 Executor executor = Executors.newCachedThreadPool();
92
93 BatchStepLauncher batchStepLauncher = new BatchStepLauncher();
94 executor.execute(batchStepLauncher);
95 }
96
97 /**
98 * Loops and polls for the batch container start up (looks for the .runlock)
99 */
100 private static void confirmStartUp() {
101 logToOut("confirming batch container start up");
102
103 while (!batchStepTriggerParms.getBatchContainerDirectory().isBatchContainerRunning()) {
104 logToOut("waiting for the batch container to start up");
105 try {
106 Thread.sleep(batchStepTriggerParms.getSleepInterval());
107 }
108 catch (InterruptedException e) {
109 throw new RuntimeException("BatchStepLauncher encountered interrupt exception while trying to wait for the batch container to start up", e);
110 }
111 }
112
113 logToOut("batch container is running");
114 }
115
116 /**
117 * Calls BatchStepTrigger to execute steps
118 *
119 * @param args String[] arguments normally passed to the BatchStepTrigger
120 */
121 private static void executeSteps(String[] args) {
122 logToOut("executing step(s)");
123
124 BatchStepTrigger.main(args);
125
126 logToOut("finished executing step(s)");
127 }
128
129 /**
130 * Removes the batch container semaphore (used by the shutdown hook added to Runtime)
131 * This is necessary because the Launcher exits immediately when the Trigger exits. Shutdown hook cleans up the semaphore.
132 */
133 private static void removeBatchContainerSemaphore() {
134 logToOut("removing batch container semaphore file");
135
136 if (batchStepTriggerParms.getBatchContainerDirectory().isBatchContainerRunning()) {
137 batchStepTriggerParms.getBatchContainerDirectory().removeBatchContainerSemaphore();
138 }
139
140 logToOut("batch container semaphore file has been removed");
141 }
142
143 /**
144 * Logs statement to System.out with a prefix.
145 *
146 * @param statement the statement to log
147 */
148 private static void logToOut(String statement) {
149 System.out.println(LOG_PREFIX + statement);
150 }
151 }