View Javadoc
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 }