1 | /* |
2 | * Copyright 2006-2007 the original author or authors. |
3 | * |
4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
5 | * you may not use this file except in compliance with the License. |
6 | * You may obtain a copy of the License at |
7 | * |
8 | * http://www.apache.org/licenses/LICENSE-2.0 |
9 | * |
10 | * Unless required by applicable law or agreed to in writing, software |
11 | * distributed under the License is distributed on an "AS IS" BASIS, |
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
13 | * See the License for the specific language governing permissions and |
14 | * limitations under the License. |
15 | */ |
16 | |
17 | package org.springframework.batch.repeat.support; |
18 | |
19 | import org.springframework.batch.repeat.RepeatCallback; |
20 | import org.springframework.batch.repeat.RepeatContext; |
21 | import org.springframework.batch.repeat.RepeatOperations; |
22 | |
23 | /** |
24 | * Global variable support for repeat clients. Normally it is not necessary for |
25 | * clients to be aware of the surrounding environment because a |
26 | * {@link RepeatCallback} can always use the context it is passed by the |
27 | * enclosing {@link RepeatOperations}. But occasionally it might be helpful to |
28 | * have lower level access to the ongoing {@link RepeatContext} so we provide a |
29 | * global accessor here. The mutator methods ({@link #clear()} and |
30 | * {@link #register(RepeatContext)} should not be used except internally by |
31 | * {@link RepeatOperations} implementations. |
32 | * |
33 | * @author Dave Syer |
34 | * |
35 | */ |
36 | public class RepeatSynchronizationManager { |
37 | |
38 | private static final ThreadLocal contextHolder = new ThreadLocal(); |
39 | |
40 | private RepeatSynchronizationManager() { |
41 | } |
42 | |
43 | /** |
44 | * Getter for the current context. A context is shared by all items in the |
45 | * batch, so this method is intended to return the same context object |
46 | * independent of whether the callback is running synchronously or |
47 | * asynchronously with the surrounding {@link RepeatOperations}. |
48 | * |
49 | * @return the current {@link RepeatContext} or null if there is none (if we |
50 | * are not in a batch). |
51 | */ |
52 | public static RepeatContext getContext() { |
53 | return (RepeatContext) contextHolder.get(); |
54 | } |
55 | |
56 | /** |
57 | * Convenience method to set the current repeat operation to complete if it |
58 | * exists. |
59 | */ |
60 | public static void setCompleteOnly() { |
61 | RepeatContext context = getContext(); |
62 | if (context != null) { |
63 | context.setCompleteOnly(); |
64 | } |
65 | } |
66 | |
67 | /** |
68 | * Method for registering a context - should only be used by |
69 | * {@link RepeatOperations} implementations to ensure that |
70 | * {@link #getContext()} always returns the correct value. |
71 | * |
72 | * @param context a new context at the start of a batch. |
73 | * @return the old value if there was one. |
74 | */ |
75 | public static RepeatContext register(RepeatContext context) { |
76 | RepeatContext oldSession = getContext(); |
77 | RepeatSynchronizationManager.contextHolder.set(context); |
78 | return oldSession; |
79 | } |
80 | |
81 | /** |
82 | * Clear the current context at the end of a batch - should only be used by |
83 | * {@link RepeatOperations} implementations. |
84 | * |
85 | * @return the old value if there was one. |
86 | */ |
87 | public static RepeatContext clear() { |
88 | RepeatContext context = getContext(); |
89 | RepeatSynchronizationManager.contextHolder.set(null); |
90 | return context; |
91 | } |
92 | |
93 | /** |
94 | * Set current session and all ancestors (via parent) to complete., |
95 | */ |
96 | public static void setAncestorsCompleteOnly() { |
97 | RepeatContext context = getContext(); |
98 | while (context != null) { |
99 | context.setCompleteOnly(); |
100 | context = context.getParent(); |
101 | } |
102 | } |
103 | |
104 | } |