Rationalise BatchResourceFactoryBean and allow %{key}% values in replacement patterns for JobParameters

This commit is contained in:
dsyer
2008-02-04 18:38:09 +00:00
parent 241609e09f
commit a40a362d9a
2 changed files with 69 additions and 74 deletions

View File

@@ -17,8 +17,14 @@
package org.springframework.batch.execution.resource;
import java.io.File;
import java.util.Iterator;
import java.util.Properties;
import java.util.Map.Entry;
import org.springframework.batch.core.domain.JobParameters;
import org.springframework.batch.core.domain.StepExecution;
import org.springframework.batch.core.runtime.JobParametersFactory;
import org.springframework.batch.execution.bootstrap.support.DefaultJobParametersFactory;
import org.springframework.batch.execution.scope.StepContext;
import org.springframework.batch.execution.scope.StepContextAware;
import org.springframework.beans.factory.FactoryBean;
@@ -40,14 +46,20 @@ import org.springframework.util.StringUtils;
* If no pattern is passed in, then following default is used:
*
* <pre>
* /%BATCH_ROOT%/job_data/%JOB_NAME%/%JOB_IDENTIFIER%-%STEP_NAME%.txt
* data/%JOB_NAME%/%STEP_NAME%.txt
* </pre>
*
* The %% variables are replaced with the corresponding bean property at run
* 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).<br/>
* time, when the factory method is executed. To insert {@link JobParameters}
* use a pattern with the parameter key surrounded by %%, e.g.
*
* <pre>
* //home/jobs/data/%JOB_NAME%/%STEP_NAME%-%schedule.date%.txt
* </pre>
*
* Note that the default pattern does not start with a separator. Because of the
* implementation of the Spring Core Resource abstractions, it would need to
* start with a double forward slash "//" to resolve to an absolute directory.<br/>
*
* 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
@@ -59,28 +71,36 @@ import org.springframework.util.StringUtils;
*
* @see FactoryBean
*/
public class BatchResourceFactoryBean extends AbstractFactoryBean implements
ResourceLoaderAware, StepContextAware {
private static final String BATCH_ROOT_PATTERN = "%BATCH_ROOT%";
public class BatchResourceFactoryBean extends AbstractFactoryBean implements ResourceLoaderAware, StepContextAware {
private static final String JOB_NAME_PATTERN = "%JOB_NAME%";
private static final String STEP_NAME_PATTERN = "%STEP_NAME%";
private static final String DEFAULT_PATTERN = "/%BATCH_ROOT%/data/%JOB_NAME%/"
+ "%STEP_NAME%.txt";
private static final String DEFAULT_PATTERN = "data/%JOB_NAME%/" + "%STEP_NAME%.txt";
private String filePattern = DEFAULT_PATTERN;
private String jobName = null;
private String rootDirectory = "";
private String stepName = "";
private JobParametersFactory jobParametersFactory = new DefaultJobParametersFactory();
private ResourceLoader resourceLoader = new FileSystemResourceLoader();
private Properties properties;
/**
* Public setter for the {@link JobParametersFactory} used to translate
* {@link JobParameters} into {@link Properties}. Defaults to a
* {@link DefaultJobParametersFactory}.
* @param jobParametersFactory the {@link JobParametersFactory} to set
*/
public void setJobParametersFactory(JobParametersFactory jobParametersFactory) {
this.jobParametersFactory = jobParametersFactory;
}
/**
* Always false because we are expecting to be step scoped.
*
@@ -106,11 +126,11 @@ public class BatchResourceFactoryBean extends AbstractFactoryBean implements
* @see org.springframework.batch.execution.scope.StepContextAware#setStepScopeContext(org.springframework.core.AttributeAccessor)
*/
public void setStepContext(StepContext context) {
Assert.state(context.getStepExecution() != null,
"The StepContext does not have an execution.");
Assert.state(context.getStepExecution() != null, "The StepContext does not have an execution.");
StepExecution execution = context.getStepExecution();
stepName = execution.getStep().getName();
jobName = execution.getStep().getJobInstance().getJobName();
properties = jobParametersFactory.getProperties(execution.getStep().getJobInstance().getJobParameters());
}
/**
@@ -130,8 +150,7 @@ public class BatchResourceFactoryBean extends AbstractFactoryBean implements
/**
* helper method for <code>createFileName()</code>
*/
private String replacePattern(String string, String pattern,
String replacement) {
private String replacePattern(String string, String pattern, String replacement) {
if (string == null)
return null;
@@ -155,11 +174,17 @@ public class BatchResourceFactoryBean extends AbstractFactoryBean implements
String fileName = filePattern;
fileName = replacePattern(fileName, BATCH_ROOT_PATTERN, rootDirectory);
fileName = replacePattern(fileName, JOB_NAME_PATTERN,
jobName == null ? "job" : jobName);
fileName = replacePattern(fileName, JOB_NAME_PATTERN, jobName == null ? "job" : jobName);
fileName = replacePattern(fileName, STEP_NAME_PATTERN, stepName);
if (properties != null) {
for (Iterator iterator = properties.entrySet().iterator(); iterator.hasNext();) {
Entry entry = (Entry) iterator.next();
String key = (String) entry.getKey();
fileName = replacePattern(fileName, "%" + key + "%", (String) entry.getValue());
}
}
return fileName;
}
@@ -167,12 +192,4 @@ public class BatchResourceFactoryBean extends AbstractFactoryBean implements
this.filePattern = replacePattern(filePattern, "\\", File.separator);
}
public void setRootDirectory(String rootDirectory) {
this.rootDirectory = replacePattern(rootDirectory, "\\", File.separator);
if (rootDirectory != null && rootDirectory.endsWith(File.separator)) {
this.rootDirectory = rootDirectory.substring(0, rootDirectory
.lastIndexOf(File.separator));
}
}
}

View File

@@ -21,17 +21,16 @@ import java.io.IOException;
import junit.framework.TestCase;
import org.springframework.batch.core.domain.JobSupport;
import org.springframework.batch.core.domain.JobExecution;
import org.springframework.batch.core.domain.JobInstance;
import org.springframework.batch.core.domain.JobParameters;
import org.springframework.batch.core.domain.StepExecution;
import org.springframework.batch.core.domain.JobParametersBuilder;
import org.springframework.batch.core.domain.JobSupport;
import org.springframework.batch.core.domain.StepInstance;
import org.springframework.batch.execution.scope.SimpleStepContext;
import org.springframework.core.io.ByteArrayResource;
import org.springframework.core.io.DefaultResourceLoader;
import org.springframework.core.io.Resource;
import org.springframework.util.StringUtils;
/**
* Unit tests for {@link BatchResourceFactoryBean}
@@ -47,41 +46,28 @@ public class BatchResourceFactoryBeanTests extends TestCase {
*/
private BatchResourceFactoryBean resourceFactory = new BatchResourceFactoryBean();
private String rootDir = getRootDir();
private char pathsep = File.separatorChar;
private String path = "data" + pathsep;
private JobInstance jobInstance;
private StepInstance stepInstance;
/**
* mock step context
*/
protected void setUp() throws Exception {
resourceFactory.setRootDirectory(rootDir);
jobInstance = new JobInstance(new Long(0), new JobParameters());
jobInstance.setJob(new JobSupport("testJob"));
JobExecution jobExecution = new JobExecution(jobInstance);
StepInstance step = new StepInstance(jobInstance, "bar");
StepExecution stepExecution = new StepExecution(step, jobExecution, null);
SimpleStepContext context = new SimpleStepContext(stepExecution);
resourceFactory.setStepContext(context);
JobExecution jobExecution = jobInstance.createJobExecution();
stepInstance = new StepInstance(jobInstance, "bar");
resourceFactory.setStepContext(new SimpleStepContext(jobExecution.createStepExecution(stepInstance)));
resourceFactory.afterPropertiesSet();
}
private String getRootDir() {
String rootDir = System.getProperty("java.io.tmpdir");
assertNotNull(rootDir);
if (rootDir != null && rootDir.endsWith(File.separator)) {
rootDir = rootDir.substring(0, rootDir.lastIndexOf(File.separator));
}
return rootDir;
}
/**
@@ -101,15 +87,26 @@ public class BatchResourceFactoryBeanTests extends TestCase {
try {
resourceFactory.getObject();
fail("Expected IllegalArgumentException");
} catch (IllegalArgumentException e) {
}
catch (IllegalArgumentException e) {
// expected
}
}
public void testNonStandardFilePattern() throws Exception {
resourceFactory.setFilePattern("/%BATCH_ROOT%/data/%JOB_NAME%/"
+ "%STEP_NAME%-job");
doTestPathName("bar-job", path);
resourceFactory.setFilePattern("foo/data/%JOB_NAME%/" + "%STEP_NAME%-job");
doTestPathName("bar-job", "foo" + pathsep + "data" + pathsep);
}
public void testNonStandardFilePatternWithJobParameters() throws Exception {
jobInstance = new JobInstance(new Long(0), new JobParametersBuilder().addString("job.key", "spam")
.toJobParameters());
jobInstance.setJob(new JobSupport("testJob"));
JobExecution jobExecution = jobInstance.createJobExecution();
stepInstance = new StepInstance(jobInstance, "bar");
resourceFactory.setStepContext(new SimpleStepContext(jobExecution.createStepExecution(stepInstance)));
resourceFactory.setFilePattern("foo/data/%JOB_NAME%/%job.key%-foo");
doTestPathName("spam-foo", "foo" + pathsep + "data" + pathsep);
}
public void testResoureLoaderAware() throws Exception {
@@ -125,30 +122,11 @@ public class BatchResourceFactoryBeanTests extends TestCase {
assertTrue(resource.exists());
}
public void testRootDirectoryEndsWithForwardSlash() throws Exception {
String rootDir = getRootDir();
rootDir = StringUtils.replace(rootDir, File.separator, "/") + "/";
resourceFactory.setRootDirectory(rootDir);
doTestPathName("bar.txt", path);
}
public void testRootDirectoryEndsWithBackSlash() throws Exception {
String rootDir = getRootDir();
rootDir = "/"+StringUtils.replace(rootDir, File.separator, "\\") + "\\";
resourceFactory.setRootDirectory(rootDir);
doTestPathName("bar.txt", path);
}
private void doTestPathName(String filename, String path) throws Exception, IOException {
Resource resource = (Resource) resourceFactory.getObject();
String returnedPath = resource.getFile().getAbsolutePath();
String absolutePath = new File("/" + rootDir + pathsep + path + jobInstance.getJobName() + pathsep + filename).getAbsolutePath();
// System.err.println(absolutePath);
// System.err.println(returnedPath);
String absolutePath = new File(path + jobInstance.getJobName() + pathsep + filename).getAbsolutePath();
assertEquals(absolutePath, returnedPath);
}
}