diff --git a/execution/src/main/java/org/springframework/batch/execution/facade/BatchResourceFactoryBean.java b/execution/src/main/java/org/springframework/batch/execution/resource/BatchResourceFactoryBean.java similarity index 82% rename from execution/src/main/java/org/springframework/batch/execution/facade/BatchResourceFactoryBean.java rename to execution/src/main/java/org/springframework/batch/execution/resource/BatchResourceFactoryBean.java index 10040bd46..b15e8ff03 100644 --- a/execution/src/main/java/org/springframework/batch/execution/facade/BatchResourceFactoryBean.java +++ b/execution/src/main/java/org/springframework/batch/execution/resource/BatchResourceFactoryBean.java @@ -14,12 +14,13 @@ * limitations under the License. */ -package org.springframework.batch.execution.facade; +package org.springframework.batch.execution.resource; import java.io.File; import org.springframework.batch.core.domain.JobIdentifier; import org.springframework.batch.core.domain.StepExecution; +import org.springframework.batch.execution.resource.support.DefaultJobIdentifierLabelGenerator; import org.springframework.batch.execution.scope.StepContext; import org.springframework.batch.execution.scope.StepContextAware; import org.springframework.beans.factory.FactoryBean; @@ -48,7 +49,11 @@ import org.springframework.util.StringUtils; * time, when the factory method is executed. Note that the default pattern * starts with a forward slash "/", which means the root directory will be * interpreted as an absolute path if it too starts with "/" (because of the - * implementation of the Spring Core Resource abstractions). + * implementation of the Spring Core Resource abstractions).
+ * + * It doesn't make much sense to use this factory unless it is step scoped, but + * note that it is thread safe only if it is step scoped and its mutators are + * not used except for configuration. * * @author Tomas Slanina * @author Lucas Ward @@ -78,12 +83,14 @@ public class BatchResourceFactoryBean extends AbstractFactoryBean implements private String stepName = ""; - private ResourceLoader resourceLoader; + private ResourceLoader resourceLoader = new FileSystemResourceLoader(); private JobIdentifier jobIdentifier; + private JobIdentifierLabelGenerator jobIdentifierLabelGenerator = new DefaultJobIdentifierLabelGenerator(); + /** - * Always false because we are usually expecting to be step scoped. + * Always false because we are expecting to be step scoped. * * @see org.springframework.beans.factory.config.AbstractFactoryBean#isSingleton() */ @@ -100,8 +107,20 @@ public class BatchResourceFactoryBean extends AbstractFactoryBean implements this.resourceLoader = resourceLoader; } - /* - * (non-Javadoc) + /** + * Public setter for the {@link JobIdentifierLabelGenerator} property. + * + * @param jobIdentifierLabelGenerator + * the {@link JobIdentifierLabelGenerator} to set + */ + public void setJobIdentifierLabelGenerator( + JobIdentifierLabelGenerator jobIdentifierLabelGenerator) { + this.jobIdentifierLabelGenerator = jobIdentifierLabelGenerator; + } + + /** + * Collect the properties of the enclosing {@link StepExecution} that will + * be needed to create a file name. * * @see org.springframework.batch.execution.scope.StepContextAware#setStepScopeContext(org.springframework.core.AttributeAccessor) */ @@ -121,11 +140,6 @@ public class BatchResourceFactoryBean extends AbstractFactoryBean implements * @return a resource representing the file on the file system. */ protected Object createInstance() { - - if (resourceLoader == null) { - resourceLoader = new FileSystemResourceLoader(); - } - return resourceLoader.getResource(createFileName()); } @@ -168,7 +182,7 @@ public class BatchResourceFactoryBean extends AbstractFactoryBean implements jobName == null ? "job" : jobName); fileName = replacePattern(fileName, STEP_NAME_PATTERN, stepName); fileName = replacePattern(fileName, JOB_IDENTIFIER_PATTERN, - jobIdentifier == null ? "step" : jobIdentifier.getLabel()); + jobIdentifierLabelGenerator.getLabel(jobIdentifier)); return fileName; } diff --git a/execution/src/main/java/org/springframework/batch/execution/resource/JobIdentifierLabelGenerator.java b/execution/src/main/java/org/springframework/batch/execution/resource/JobIdentifierLabelGenerator.java new file mode 100644 index 000000000..ee0a2f7f0 --- /dev/null +++ b/execution/src/main/java/org/springframework/batch/execution/resource/JobIdentifierLabelGenerator.java @@ -0,0 +1,41 @@ +/* + * 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.execution.resource; + +import org.springframework.batch.core.domain.JobIdentifier; + +/** + * Strategy for generating a label (e.g. for a file name) from a + * {@link JobIdentifier}. A label is a short string with no special characters + * that can be used to recognise the {@link JobIdentifier}. + * + * @author Dave Syer + * + */ +public interface JobIdentifierLabelGenerator { + + /** + * Create a label from the {@link JobIdentifier}. + * + * @param jobIdentifier + * a {@link JobIdentifier} + * @return a short string describing the identifier with no whitespace or + * special characters. Return null if the identifier is null. + */ + String getLabel(JobIdentifier jobIdentifier); + +} diff --git a/execution/src/main/java/org/springframework/batch/execution/resource/support/DefaultJobIdentifierLabelGenerator.java b/execution/src/main/java/org/springframework/batch/execution/resource/support/DefaultJobIdentifierLabelGenerator.java new file mode 100644 index 000000000..54334c7c8 --- /dev/null +++ b/execution/src/main/java/org/springframework/batch/execution/resource/support/DefaultJobIdentifierLabelGenerator.java @@ -0,0 +1,61 @@ +/* + * 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.execution.resource.support; + +import java.text.DateFormat; +import java.text.SimpleDateFormat; + +import org.springframework.batch.core.domain.JobIdentifier; +import org.springframework.batch.core.runtime.SimpleJobIdentifier; +import org.springframework.batch.execution.resource.JobIdentifierLabelGenerator; +import org.springframework.batch.execution.runtime.ScheduledJobIdentifier; + +/** + * {@link JobIdentifierLabelGenerator} that knows about + * {@link SimpleJobIdentifier} and {@link ScheduledJobIdentifier} and provides a + * fixed format label for each. + * + * + * @author Dave Syer + * + */ +public class DefaultJobIdentifierLabelGenerator implements + JobIdentifierLabelGenerator { + + private static final DateFormat dateFormat = new SimpleDateFormat( + "yyyyMMdd"); + + /** + * Concatenate the properties of the {@link JobIdentifier}. From a + * {@link SimpleJobIdentifier} we just get the name, and from a + * {@link ScheduledJobIdentifier} we get the name, stream, run and schedule + * date (yyyyMMdd) joined by hyphens. + * + * @see org.springframework.batch.execution.resource.JobIdentifierLabelGenerator#getLabel(org.springframework.batch.core.domain.JobIdentifier) + */ + public String getLabel(JobIdentifier jobIdentifier) { + if (jobIdentifier == null) { + return null; + } + if (jobIdentifier instanceof ScheduledJobIdentifier) { + ScheduledJobIdentifier id = (ScheduledJobIdentifier) jobIdentifier; + return jobIdentifier.getName() + "-" + id.getJobStream() + "-" + + id.getJobRun() + "-" + + dateFormat.format(id.getScheduleDate()); + } + return jobIdentifier.getName(); + } +} diff --git a/execution/src/main/java/org/springframework/batch/execution/runtime/ScheduledJobIdentifier.java b/execution/src/main/java/org/springframework/batch/execution/runtime/ScheduledJobIdentifier.java index 646ed0f4e..26c345095 100644 --- a/execution/src/main/java/org/springframework/batch/execution/runtime/ScheduledJobIdentifier.java +++ b/execution/src/main/java/org/springframework/batch/execution/runtime/ScheduledJobIdentifier.java @@ -73,14 +73,7 @@ public class ScheduledJobIdentifier extends SimpleJobIdentifier implements JobId this.scheduleDate = scheduleDate; } - - - public String getLabel() { - return super.getLabel()+"-"+jobStream+"-"+jobRun+"-"+dateFormat.format(scheduleDate); - } - public String toString() { - return super.toString() + ",stream=" + jobStream + ",run=" + jobRun + ",scheduleDate=" + scheduleDate; } diff --git a/execution/src/test/java/org/springframework/batch/execution/facade/BatchResourceFactoryBeanTests.java b/execution/src/test/java/org/springframework/batch/execution/resource/BatchResourceFactoryBeanTests.java similarity index 90% rename from execution/src/test/java/org/springframework/batch/execution/facade/BatchResourceFactoryBeanTests.java rename to execution/src/test/java/org/springframework/batch/execution/resource/BatchResourceFactoryBeanTests.java index 5f334db45..6f139dcf8 100644 --- a/execution/src/test/java/org/springframework/batch/execution/facade/BatchResourceFactoryBeanTests.java +++ b/execution/src/test/java/org/springframework/batch/execution/resource/BatchResourceFactoryBeanTests.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.batch.execution.facade; +package org.springframework.batch.execution.resource; import java.io.File; import java.io.IOException; @@ -23,9 +23,11 @@ import java.text.SimpleDateFormat; import junit.framework.TestCase; import org.springframework.batch.core.domain.JobExecution; +import org.springframework.batch.core.domain.JobIdentifier; import org.springframework.batch.core.domain.JobInstance; import org.springframework.batch.core.domain.StepExecution; import org.springframework.batch.core.domain.StepInstance; +import org.springframework.batch.execution.resource.BatchResourceFactoryBean; import org.springframework.batch.execution.runtime.ScheduledJobIdentifier; import org.springframework.batch.execution.scope.SimpleStepContext; import org.springframework.core.io.ByteArrayResource; @@ -98,6 +100,18 @@ public class BatchResourceFactoryBeanTests extends TestCase { doTestPathName("testJob-testStream-11-20070730-bar.txt", path); } + /** + * regular use with valid context and pattern provided + */ + public void testSetLabelGenerator() throws Exception { + resourceFactory.setJobIdentifierLabelGenerator(new JobIdentifierLabelGenerator() { + public String getLabel(JobIdentifier jobIdentifier) { + return "foo"; + } + }); + doTestPathName("foo-bar.txt", path); + } + public void testObjectType() throws Exception { assertEquals(Resource.class, resourceFactory.getObjectType()); } diff --git a/execution/src/test/java/org/springframework/batch/execution/resource/support/DefaultJobIdentifierLabelGeneratorTests.java b/execution/src/test/java/org/springframework/batch/execution/resource/support/DefaultJobIdentifierLabelGeneratorTests.java new file mode 100644 index 000000000..edad7f36f --- /dev/null +++ b/execution/src/test/java/org/springframework/batch/execution/resource/support/DefaultJobIdentifierLabelGeneratorTests.java @@ -0,0 +1,47 @@ +package org.springframework.batch.execution.resource.support; + +import java.text.SimpleDateFormat; + +import junit.framework.TestCase; + +import org.springframework.batch.core.runtime.SimpleJobIdentifier; +import org.springframework.batch.execution.runtime.ScheduledJobIdentifier; + +public class DefaultJobIdentifierLabelGeneratorTests extends TestCase { + + DefaultJobIdentifierLabelGenerator instance = new DefaultJobIdentifierLabelGenerator(); + + /** + * Test method for {@link org.springframework.batch.execution.resource.support.DefaultJobIdentifierLabelGenerator#getLabel()}. + */ + public void testGetLabelFromNull() { + assertEquals(null, instance.getLabel(null)); + } + + /** + * Test method for {@link org.springframework.batch.execution.resource.support.DefaultJobIdentifierLabelGenerator#getLabel()}. + */ + public void testGetLabel() { + assertEquals("foo", instance.getLabel(new SimpleJobIdentifier("foo"))); + } + + /** + * Test method for {@link org.springframework.batch.execution.resource.support.DefaultJobIdentifierLabelGenerator#getLabel()}. + */ + public void testDefaultGetLabel() throws Exception { + assertEquals("null--0-19700101", instance.getLabel(new ScheduledJobIdentifier(null))); + } + + /** + * Test method for {@link org.springframework.batch.execution.resource.support.DefaultJobIdentifierLabelGenerator#getLabel()}. + */ + public void testGetLabelWithAllProperties() throws Exception { + ScheduledJobIdentifier identifier = new ScheduledJobIdentifier(null); + identifier.setName("foo"); + identifier.setJobStream("bar"); + identifier.setJobRun(11); + identifier.setScheduleDate(new SimpleDateFormat("yyyyMMdd").parse("20070730")); + assertEquals("foo-bar-11-20070730", instance.getLabel(identifier)); + } + +} diff --git a/execution/src/test/java/org/springframework/batch/execution/runtime/ScheduledJobIdentifierTests.java b/execution/src/test/java/org/springframework/batch/execution/runtime/ScheduledJobIdentifierTests.java index ce491048b..73e3b194f 100644 --- a/execution/src/test/java/org/springframework/batch/execution/runtime/ScheduledJobIdentifierTests.java +++ b/execution/src/test/java/org/springframework/batch/execution/runtime/ScheduledJobIdentifierTests.java @@ -16,7 +16,6 @@ package org.springframework.batch.execution.runtime; import java.sql.Date; -import java.text.SimpleDateFormat; import junit.framework.TestCase; @@ -64,22 +63,4 @@ public class ScheduledJobIdentifierTests extends TestCase { assertEquals(1, instance.getJobRun()); } - - /** - * Test method for {@link org.springframework.batch.core.domain.JobInstance#getLabel()}. - */ - public void testDefaultGetLabel() throws Exception { - assertEquals("null--0-19700101", instance.getLabel()); - } - - /** - * Test method for {@link org.springframework.batch.core.domain.JobInstance#getLabel()}. - */ - public void testGetLabelWithAllProperties() throws Exception { - instance.setName("foo"); - instance.setJobStream("bar"); - instance.setJobRun(11); - instance.setScheduleDate(new SimpleDateFormat("yyyyMMdd").parse("20070730")); - assertEquals("foo-bar-11-20070730", instance.getLabel()); - } }