001/* 002 * Copyright 2006-2007 the original author or authors. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * https://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017package org.springframework.batch.repeat.support; 018 019import org.springframework.batch.repeat.RepeatCallback; 020import org.springframework.batch.repeat.RepeatContext; 021import org.springframework.batch.repeat.RepeatOperations; 022 023/** 024 * Global variable support for repeat clients. Normally it is not necessary for 025 * clients to be aware of the surrounding environment because a 026 * {@link RepeatCallback} can always use the context it is passed by the 027 * enclosing {@link RepeatOperations}. But occasionally it might be helpful to 028 * have lower level access to the ongoing {@link RepeatContext} so we provide a 029 * global accessor here. The mutator methods ({@link #clear()} and 030 * {@link #register(RepeatContext)} should not be used except internally by 031 * {@link RepeatOperations} implementations. 032 * 033 * @author Dave Syer 034 * 035 */ 036public final class RepeatSynchronizationManager { 037 038 private static final ThreadLocal<RepeatContext> contextHolder = new ThreadLocal<RepeatContext>(); 039 040 private RepeatSynchronizationManager() { 041 } 042 043 /** 044 * Getter for the current context. A context is shared by all items in the 045 * batch, so this method is intended to return the same context object 046 * independent of whether the callback is running synchronously or 047 * asynchronously with the surrounding {@link RepeatOperations}. 048 * 049 * @return the current {@link RepeatContext} or null if there is none (if we 050 * are not in a batch). 051 */ 052 public static RepeatContext getContext() { 053 return contextHolder.get(); 054 } 055 056 /** 057 * Convenience method to set the current repeat operation to complete if it 058 * exists. 059 */ 060 public static void setCompleteOnly() { 061 RepeatContext context = getContext(); 062 if (context != null) { 063 context.setCompleteOnly(); 064 } 065 } 066 067 /** 068 * Method for registering a context - should only be used by 069 * {@link RepeatOperations} implementations to ensure that 070 * {@link #getContext()} always returns the correct value. 071 * 072 * @param context a new context at the start of a batch. 073 * @return the old value if there was one. 074 */ 075 public static RepeatContext register(RepeatContext context) { 076 RepeatContext oldSession = getContext(); 077 RepeatSynchronizationManager.contextHolder.set(context); 078 return oldSession; 079 } 080 081 /** 082 * Clear the current context at the end of a batch - should only be used by 083 * {@link RepeatOperations} implementations. 084 * 085 * @return the old value if there was one. 086 */ 087 public static RepeatContext clear() { 088 RepeatContext context = getContext(); 089 RepeatSynchronizationManager.contextHolder.set(null); 090 return context; 091 } 092 093 /** 094 * Set current session and all ancestors (via parent) to complete., 095 */ 096 public static void setAncestorsCompleteOnly() { 097 RepeatContext context = getContext(); 098 while (context != null) { 099 context.setCompleteOnly(); 100 context = context.getParent(); 101 } 102 } 103 104}