1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.springframework.batch.core.scope.context;
17
18 import java.util.ArrayList;
19 import java.util.Collections;
20 import java.util.HashMap;
21 import java.util.HashSet;
22 import java.util.List;
23 import java.util.Map;
24 import java.util.Properties;
25 import java.util.Set;
26 import java.util.Map.Entry;
27
28 import org.springframework.batch.core.JobInstance;
29 import org.springframework.batch.core.JobParameter;
30 import org.springframework.batch.core.JobParameters;
31 import org.springframework.batch.core.StepExecution;
32 import org.springframework.batch.core.UnexpectedJobExecutionException;
33 import org.springframework.batch.core.scope.StepScope;
34 import org.springframework.batch.item.ExecutionContext;
35 import org.springframework.batch.repeat.context.SynchronizedAttributeAccessor;
36 import org.springframework.util.Assert;
37
38
39
40
41
42
43
44
45
46
47
48
49 public class StepContext extends SynchronizedAttributeAccessor {
50
51 private StepExecution stepExecution;
52
53 private Map<String, Set<Runnable>> callbacks = new HashMap<String, Set<Runnable>>();
54
55
56
57
58
59
60
61 public StepContext(StepExecution stepExecution) {
62 super();
63 Assert.notNull(stepExecution, "A StepContext must have a non-null StepExecution");
64 this.stepExecution = stepExecution;
65 }
66
67
68
69
70
71
72
73
74 public String getStepName() {
75 return stepExecution.getStepName();
76 }
77
78
79
80
81
82
83
84 public String getJobName() {
85 Assert.state(stepExecution.getJobExecution() != null, "StepExecution does not have a JobExecution");
86 Assert.state(stepExecution.getJobExecution().getJobInstance() != null,
87 "StepExecution does not have a JobInstance");
88 return stepExecution.getJobExecution().getJobInstance().getJobName();
89 }
90
91
92
93
94
95
96
97 public Properties getSystemProperties() {
98 return System.getProperties();
99 }
100
101
102
103
104 public Map<String, Object> getStepExecutionContext() {
105 Map<String, Object> result = new HashMap<String, Object>();
106 for (Entry<String, Object> entry : stepExecution.getExecutionContext().entrySet()) {
107 result.put(entry.getKey(), entry.getValue());
108 }
109 return Collections.unmodifiableMap(result);
110 }
111
112
113
114
115 public Map<String, Object> getJobExecutionContext() {
116 Map<String, Object> result = new HashMap<String, Object>();
117 for (Entry<String, Object> entry : stepExecution.getJobExecution().getExecutionContext().entrySet()) {
118 result.put(entry.getKey(), entry.getValue());
119 }
120 return Collections.unmodifiableMap(result);
121 }
122
123
124
125
126 public Map<String, Object> getJobParameters() {
127 Map<String, Object> result = new HashMap<String, Object>();
128 for (Entry<String, JobParameter> entry : stepExecution.getJobParameters().getParameters().entrySet()) {
129 result.put(entry.getKey(), entry.getValue().getValue());
130 }
131 return Collections.unmodifiableMap(result);
132 }
133
134
135
136
137
138
139
140 public void registerDestructionCallback(String name, Runnable callback) {
141 synchronized (callbacks) {
142 Set<Runnable> set = callbacks.get(name);
143 if (set == null) {
144 set = new HashSet<Runnable>();
145 callbacks.put(name, set);
146 }
147 set.add(callback);
148 }
149 }
150
151 private void unregisterDestructionCallbacks(String name) {
152 synchronized (callbacks) {
153 callbacks.remove(name);
154 }
155 }
156
157
158
159
160
161
162
163 @Override
164 public Object removeAttribute(String name) {
165 unregisterDestructionCallbacks(name);
166 return super.removeAttribute(name);
167 }
168
169
170
171
172
173
174 public void close() {
175
176 List<Exception> errors = new ArrayList<Exception>();
177
178 Map<String, Set<Runnable>> copy = Collections.unmodifiableMap(callbacks);
179
180 for (Entry<String, Set<Runnable>> entry : copy.entrySet()) {
181 Set<Runnable> set = entry.getValue();
182 for (Runnable callback : set) {
183 if (callback != null) {
184
185
186
187
188
189 try {
190 callback.run();
191 }
192 catch (RuntimeException t) {
193 errors.add(t);
194 }
195 }
196 }
197 }
198
199 if (errors.isEmpty()) {
200 return;
201 }
202
203 Exception error = errors.get(0);
204 if (error instanceof RuntimeException) {
205 throw (RuntimeException) error;
206 }
207 else {
208 throw new UnexpectedJobExecutionException("Could not close step context, rethrowing first of "
209 + errors.size() + " exceptions.", error);
210 }
211 }
212
213
214
215
216
217
218 public StepExecution getStepExecution() {
219 return stepExecution;
220 }
221
222
223
224
225 public String getId() {
226 Assert.state(stepExecution.getId() != null, "StepExecution has no id. "
227 + "It must be saved before it can be used in step scope.");
228 return "execution#" + stepExecution.getId();
229 }
230
231
232
233
234
235
236
237
238 @Override
239 public boolean equals(Object other) {
240 if (!(other instanceof StepContext))
241 return false;
242 if (other == this)
243 return true;
244 StepContext context = (StepContext) other;
245 if (context.stepExecution == stepExecution) {
246 return true;
247 }
248 return stepExecution.equals(context.stepExecution);
249 }
250
251
252
253
254
255
256
257 @Override
258 public int hashCode() {
259 return stepExecution.hashCode();
260 }
261
262 @Override
263 public String toString() {
264 return super.toString() + ", stepExecutionContext=" + getStepExecutionContext() + ", jobExecutionContext="
265 + getJobExecutionContext() + ", jobParameters=" + getJobParameters();
266 }
267
268 }