View Javadoc

1   /*
2    * Copyright 2006-2013 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.core.repository.dao;
18  
19  import java.io.Serializable;
20  import java.util.concurrent.ConcurrentMap;
21  
22  import org.springframework.batch.core.JobExecution;
23  import org.springframework.batch.core.StepExecution;
24  import org.springframework.batch.item.ExecutionContext;
25  import org.springframework.batch.support.SerializationUtils;
26  import org.springframework.batch.support.transaction.TransactionAwareProxyFactory;
27  
28  /**
29   * In-memory implementation of {@link ExecutionContextDao} backed by maps.
30   *
31   * @author Robert Kasanicky
32   * @author Dave Syer
33   */
34  @SuppressWarnings("serial")
35  public class MapExecutionContextDao implements ExecutionContextDao {
36  
37  	private final ConcurrentMap<ContextKey, ExecutionContext> contexts = TransactionAwareProxyFactory
38  			.createAppendOnlyTransactionalMap();
39  
40  	private static final class ContextKey implements Comparable<ContextKey>, Serializable {
41  
42  		private static enum Type { STEP, JOB; }
43  
44  		private final Type type;
45  		private final long id;
46  
47  		private ContextKey(Type type, long id) {
48  			if(type == null) {
49  				throw new IllegalStateException("Need a non-null type for a context");
50  			}
51  			this.type = type;
52  			this.id = id;
53  		}
54  
55  		@Override
56  		public int compareTo(ContextKey them) {
57  			if(them == null) {
58  				return 1;
59  			}
60  			final int idCompare = new Long(this.id).compareTo(new Long(them.id)); // JDK6 Make this Long.compare(x,y)
61  			if(idCompare != 0) {
62  				return idCompare;
63  			}
64  			final int typeCompare = this.type.compareTo(them.type);
65  			if(typeCompare != 0) {
66  				return typeCompare;
67  			}
68  			return 0;
69  		}
70  
71  		@Override
72  		public boolean equals(Object them) {
73  			if(them == null) {
74  				return false;
75  			}
76  			if(them instanceof ContextKey) {
77  				return this.equals((ContextKey)them);
78  			}
79  			return false;
80  		}
81  
82  		public boolean equals(ContextKey them) {
83  			if(them == null) {
84  				return false;
85  			}
86  			return this.id == them.id && this.type.equals(them.type);
87  		}
88  
89  		@Override
90  		public int hashCode() {
91  			int value = (int)(id^(id>>>32));
92  			switch(type) {
93  			case STEP: return value;
94  			case JOB: return ~value;
95  			default: throw new IllegalStateException("Unknown type encountered in switch: " + type);
96  			}
97  		}
98  
99  		public static ContextKey step(long id) { return new ContextKey(Type.STEP, id); }
100 
101 		public static ContextKey job(long id) { return new ContextKey(Type.JOB, id); }
102 	}
103 
104 	public void clear() {
105 		contexts.clear();
106 	}
107 
108 	private static ExecutionContext copy(ExecutionContext original) {
109 		return (ExecutionContext) SerializationUtils.deserialize(SerializationUtils.serialize(original));
110 	}
111 
112 	@Override
113 	public ExecutionContext getExecutionContext(StepExecution stepExecution) {
114 		return copy(contexts.get(ContextKey.step(stepExecution.getId())));
115 	}
116 
117 	@Override
118 	public void updateExecutionContext(StepExecution stepExecution) {
119 		ExecutionContext executionContext = stepExecution.getExecutionContext();
120 		if (executionContext != null) {
121 			contexts.put(ContextKey.step(stepExecution.getId()), copy(executionContext));
122 		}
123 	}
124 
125 	@Override
126 	public ExecutionContext getExecutionContext(JobExecution jobExecution) {
127 		return copy(contexts.get(ContextKey.job(jobExecution.getId())));
128 	}
129 
130 	@Override
131 	public void updateExecutionContext(JobExecution jobExecution) {
132 		ExecutionContext executionContext = jobExecution.getExecutionContext();
133 		if (executionContext != null) {
134 			contexts.put(ContextKey.job(jobExecution.getId()), copy(executionContext));
135 		}
136 	}
137 
138 	@Override
139 	public void saveExecutionContext(JobExecution jobExecution) {
140 		updateExecutionContext(jobExecution);
141 	}
142 
143 	@Override
144 	public void saveExecutionContext(StepExecution stepExecution) {
145 		updateExecutionContext(stepExecution);
146 	}
147 
148 }