1 package org.kuali.ole.sys.context;
2
3
4 import java.io.File;
5 import java.util.ArrayList;
6 import java.util.Date;
7 import java.util.List;
8
9 import org.apache.commons.lang.StringUtils;
10 import org.apache.log4j.Appender;
11 import org.apache.log4j.FileAppender;
12 import org.apache.log4j.Logger;
13 import org.apache.log4j.NDC;
14 import org.kuali.ole.sys.OLEConstants;
15 import org.kuali.ole.sys.batch.Job;
16 import org.kuali.ole.sys.batch.Step;
17 import org.kuali.rice.core.api.config.property.ConfigurationService;
18 import org.kuali.rice.core.api.datetime.DateTimeService;
19 import org.kuali.rice.coreservice.framework.parameter.ParameterService;
20 import org.kuali.rice.krad.service.KualiModuleService;
21 import org.kuali.rice.krad.service.ModuleService;
22
23
24
25
26
27
28
29
30
31 public class BatchStepExecutor implements Runnable {
32 private static org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(BatchStepExecutor.class);
33
34 private ParameterService parameterService;
35 private DateTimeService dateTimeService;
36 private BatchContainerDirectory batchContainerDirectory;
37 private BatchStepFileDescriptor batchStepFile;
38 private Step step;
39 private int stepIndex;
40
41 private Appender ndcAppender;
42 private boolean ndcSet;
43 private String logFileName;
44
45 private List<ContainerStepListener> containerStepListeners;
46
47
48
49
50
51
52
53
54
55 public BatchStepExecutor(ParameterService parameterService, DateTimeService dateTimeService, BatchContainerDirectory batchContainerDirectory, BatchStepFileDescriptor batchStepFile, Step step, int stepIndex) {
56 BatchLogger.addConsoleAppender(LOG);
57
58 this.parameterService = parameterService;
59 this.dateTimeService = dateTimeService;
60
61 this.batchContainerDirectory = batchContainerDirectory;
62 this.batchStepFile = batchStepFile;
63 this.step = step;
64 this.stepIndex = stepIndex;
65
66 this.containerStepListeners = new ArrayList<ContainerStepListener>();
67
68 LOG.info("Initialized thread executor for "+ batchStepFile);
69 }
70
71
72
73
74
75 @Override
76 public void run() {
77 Date stepRunDate = dateTimeService.getCurrentDate();
78 batchStepFile.setStartedDate(stepRunDate);
79 batchStepFile.setStepIndex(new Integer(stepIndex));
80
81 setupNDCLogging();
82 notifyStepStarted();
83
84 try {
85 LOG.info("Running "+ batchStepFile);
86
87 boolean result = Job.runStep(parameterService, batchStepFile.getJobName(), stepIndex, step, stepRunDate);
88
89 if (result) {
90 LOG.info("Step returned true");
91 batchContainerDirectory.writeBatchStepSuccessfulResultFile(batchStepFile);
92 }
93 else {
94 LOG.info("Step returned false");
95 batchContainerDirectory.writeBatchStepErrorResultFile(batchStepFile);
96 }
97
98 } catch (Throwable throwable) {
99 LOG.info("Step threw an error: ", throwable);
100 batchContainerDirectory.writeBatchStepErrorResultFile(batchStepFile, throwable);
101
102 } finally {
103
104 notifyStepFinished();
105 resetNDCLogging();
106 }
107 }
108
109
110
111
112
113
114 public void addContainerStepListener(ContainerStepListener listener) {
115 this.containerStepListeners.add(listener);
116 }
117
118
119
120
121 private void setupNDCLogging() {
122 String nestedDiagnosticContext = getNestedDiagnosticContext();
123 logFileName = getLogFileName(nestedDiagnosticContext);
124
125 ndcAppender = null;
126 ndcSet = false;
127 try {
128 ndcAppender = new FileAppender(BatchLogger.getLogFileAppenderLayout(), logFileName);
129 ndcAppender.addFilter(new NDCFilter(nestedDiagnosticContext));
130 Logger.getRootLogger().addAppender(ndcAppender);
131 NDC.push(nestedDiagnosticContext);
132 ndcSet = true;
133 } catch (Exception ex) {
134 LOG.warn("Could not initialize custom logging for step: " + step.getName(), ex);
135 }
136 }
137
138
139
140
141 private void resetNDCLogging() {
142 if ( ndcSet ) {
143 ndcAppender.close();
144 Logger.getRootLogger().removeAppender(ndcAppender);
145 NDC.pop();
146 }
147 }
148
149
150
151
152
153
154
155 private String getLogFileName(String nestedDiagnosticContext) {
156 return SpringContext.getBean( ConfigurationService.class ).getPropertyValueAsString(OLEConstants.REPORTS_DIRECTORY_KEY)
157 + File.separator
158 + nestedDiagnosticContext + ".log";
159 }
160
161
162
163
164 @SuppressWarnings("unchecked")
165 private String getNestedDiagnosticContext() {
166 Step unProxiedStep = (Step) ProxyUtils.getTargetIfProxied(step);
167 Class stepClass = unProxiedStep.getClass();
168 ModuleService module = SpringContext.getBean(KualiModuleService.class).getResponsibleModuleService( stepClass );
169
170 String nestedDiagnosticContext =
171 StringUtils.substringAfter( module.getModuleConfiguration().getNamespaceCode(), "-").toLowerCase()
172 + File.separator + step.getName()
173 + "-" + dateTimeService.toDateTimeStringForFilename(dateTimeService.getCurrentDate());
174
175 return nestedDiagnosticContext;
176 }
177
178
179
180
181 private void notifyStepStarted() {
182 String shortLogFileName = getShortLogFileName();
183
184 for(ContainerStepListener listener : this.containerStepListeners) {
185 listener.stepStarted(batchStepFile, shortLogFileName);
186 }
187 }
188
189
190
191
192 private void notifyStepFinished() {
193 BatchStepFileDescriptor resultFile = batchContainerDirectory.getResultFile(batchStepFile);
194 resultFile.setCompletedDate(dateTimeService.getCurrentDate());
195 resultFile.setStepIndex(new Integer(stepIndex));
196
197 String shortLogFileName = getShortLogFileName();
198
199 for(ContainerStepListener listener : this.containerStepListeners) {
200 listener.stepFinished(resultFile, shortLogFileName);
201 }
202 }
203
204
205
206
207
208
209 private String getShortLogFileName() {
210 String shortLogFileName = logFileName;
211
212 File logFile = new File(logFileName);
213 if (logFile.exists()) {
214 shortLogFileName = logFile.getName();
215 }
216 return shortLogFileName;
217 }
218 }