From 76991edce753e42411d0e7550f4733bf9f863e09 Mon Sep 17 00:00:00 2001 From: dsyer Date: Wed, 26 Mar 2008 19:43:19 +0000 Subject: [PATCH] RESOLVED - issue BATCH-447: ItemOrientedStep implementation causes mandatory dependency on backport-util-concurrent Added AtomicCounter to remove backport dependency --- .../batch/repeat/context/AtomicCounter.java | 35 +++++++++++++ .../repeat/context/AtomicCounterFactory.java | 52 +++++++++++++++++++ .../BackportConcurrentAtomicCounter.java | 19 +++++++ .../context/JdkConcurrentAtomicCounter.java | 19 +++++++ .../repeat/context/RepeatContextCounter.java | 11 ++-- 5 files changed, 130 insertions(+), 6 deletions(-) create mode 100644 spring-batch-infrastructure/src/main/java/org/springframework/batch/repeat/context/AtomicCounter.java create mode 100644 spring-batch-infrastructure/src/main/java/org/springframework/batch/repeat/context/AtomicCounterFactory.java create mode 100644 spring-batch-infrastructure/src/main/java/org/springframework/batch/repeat/context/BackportConcurrentAtomicCounter.java create mode 100644 spring-batch-infrastructure/src/main/java/org/springframework/batch/repeat/context/JdkConcurrentAtomicCounter.java diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/repeat/context/AtomicCounter.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/repeat/context/AtomicCounter.java new file mode 100644 index 000000000..d51838938 --- /dev/null +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/repeat/context/AtomicCounter.java @@ -0,0 +1,35 @@ +/* + * Copyright 2006-2007 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.repeat.context; + +/** + * @author Dave Syer + * + */ +interface AtomicCounter { + + /** + * Atomic addition. + * @param delta the delta to add to the value + */ + void addAndGet(int delta); + + /** + * @return the current value + */ + int intValue(); + +} diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/repeat/context/AtomicCounterFactory.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/repeat/context/AtomicCounterFactory.java new file mode 100644 index 000000000..ff13858ab --- /dev/null +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/repeat/context/AtomicCounterFactory.java @@ -0,0 +1,52 @@ +/* + * Copyright 2002-2007 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.batch.repeat.context; + +import org.springframework.core.JdkVersion; +import org.springframework.util.ClassUtils; + +/** + * A factory that properly determines which version of the {@link AtomicCounter} + * to return based on the availability of Java 5 or Backport Concurrent. + * + * @author Dave Syer + */ +class AtomicCounterFactory { + + /** Whether the backport-concurrent library is present on the classpath */ + private static final boolean backportConcurrentAvailable = ClassUtils.isPresent( + "edu.emory.mathcs.backport.java.util.concurrent.Semaphore", AtomicCounterFactory.class.getClassLoader()); + + private final AtomicCounter counter; + + public AtomicCounterFactory() { + if (JdkVersion.isAtLeastJava15()) { + counter = new JdkConcurrentAtomicCounter(); + } + else if (backportConcurrentAvailable) { + counter = new BackportConcurrentAtomicCounter(); + } + else { + throw new IllegalStateException("Cannot create AtomicCounter - " + + "neither JDK 1.5 nor backport-concurrent available on the classpath"); + } + } + + public AtomicCounter getAtomicCounter() { + return counter; + } +} diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/repeat/context/BackportConcurrentAtomicCounter.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/repeat/context/BackportConcurrentAtomicCounter.java new file mode 100644 index 000000000..82e4e3a37 --- /dev/null +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/repeat/context/BackportConcurrentAtomicCounter.java @@ -0,0 +1,19 @@ +package org.springframework.batch.repeat.context; + +/** + * @author Dave Syer + * + */ +class BackportConcurrentAtomicCounter implements AtomicCounter { + + private edu.emory.mathcs.backport.java.util.concurrent.atomic.AtomicInteger counter = new edu.emory.mathcs.backport.java.util.concurrent.atomic.AtomicInteger(); + + public void addAndGet(int delta) { + counter.addAndGet(delta); + } + + public int intValue() { + return counter.intValue(); + } + +} \ No newline at end of file diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/repeat/context/JdkConcurrentAtomicCounter.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/repeat/context/JdkConcurrentAtomicCounter.java new file mode 100644 index 000000000..c88550112 --- /dev/null +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/repeat/context/JdkConcurrentAtomicCounter.java @@ -0,0 +1,19 @@ +package org.springframework.batch.repeat.context; + +/** + * @author Dave Syer + * + */ +class JdkConcurrentAtomicCounter implements AtomicCounter { + + private java.util.concurrent.atomic.AtomicInteger counter = new java.util.concurrent.atomic.AtomicInteger(); + + public void addAndGet(int delta) { + counter.addAndGet(delta); + } + + public int intValue() { + return counter.intValue(); + } + +} \ No newline at end of file diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/repeat/context/RepeatContextCounter.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/repeat/context/RepeatContextCounter.java index 5b1bbf080..bdc2e2d9e 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/repeat/context/RepeatContextCounter.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/repeat/context/RepeatContextCounter.java @@ -19,8 +19,6 @@ package org.springframework.batch.repeat.context; import org.springframework.batch.repeat.RepeatContext; import org.springframework.util.Assert; -import edu.emory.mathcs.backport.java.util.concurrent.atomic.AtomicInteger; - /** * Helper class for policies that need to count the number of occurrences of * some event (e.g. an exception type in the context) in the scope of a batch. @@ -49,7 +47,7 @@ public class RepeatContextCounter { * @param delta the amount by which to increment the counter. */ final public void increment(int delta) { - AtomicInteger count = getCounter(); + AtomicCounter count = getCounter(); count.addAndGet(delta); } @@ -96,7 +94,8 @@ public class RepeatContextCounter { this.context = context; } if (!this.context.hasAttribute(countKey)) { - this.context.setAttribute(countKey, new AtomicInteger(0)); + AtomicCounterFactory factory = new AtomicCounterFactory(); + this.context.setAttribute(countKey, factory.getAtomicCounter()); } } @@ -108,8 +107,8 @@ public class RepeatContextCounter { return getCounter().intValue(); } - private AtomicInteger getCounter() { - return ((AtomicInteger) context.getAttribute(countKey)); + private AtomicCounter getCounter() { + return ((AtomicCounter) context.getAttribute(countKey)); } }