diff --git a/maven-config-processor-plugin/.gitignore b/maven-config-processor-plugin/.gitignore new file mode 100644 index 0000000..bc5fc18 --- /dev/null +++ b/maven-config-processor-plugin/.gitignore @@ -0,0 +1,4 @@ +.classpath +/target/ +.project +.settings/ diff --git a/maven-config-processor-plugin/pom.xml b/maven-config-processor-plugin/pom.xml index 7c8e469..c17bfbf 100644 --- a/maven-config-processor-plugin/pom.xml +++ b/maven-config-processor-plugin/pom.xml @@ -110,7 +110,7 @@ junit junit - 4.5 + 4.12 test diff --git a/maven-config-processor-plugin/src/main/java/com/google/code/configprocessor/ConfigProcessor.java b/maven-config-processor-plugin/src/main/java/com/google/code/configprocessor/ConfigProcessor.java index b6b9bc1..015dbb9 100644 --- a/maven-config-processor-plugin/src/main/java/com/google/code/configprocessor/ConfigProcessor.java +++ b/maven-config-processor-plugin/src/main/java/com/google/code/configprocessor/ConfigProcessor.java @@ -16,6 +16,7 @@ package com.google.code.configprocessor; import static com.google.code.configprocessor.util.IOUtils.*; + import static org.apache.commons.lang.StringUtils.*; import java.io.*; @@ -32,6 +33,7 @@ import com.google.code.configprocessor.processing.*; import com.google.code.configprocessor.processing.properties.*; import com.google.code.configprocessor.processing.xml.*; +import com.google.code.configprocessor.util.IOUtils; public class ConfigProcessor { @@ -104,32 +106,36 @@ public void execute(ExpressionResolver resolver, Transformation transformation) getLog().info("Using wildcard pattern based input [" + input + "]"); List inputFiles = getMatchingFiles(input); for (File inputFile : inputFiles) { - String type = getInputType(transformation, inputFile); - File outputFile; - if (actualOutputDirectory != null) { - // calculate a relative path below the output directory based on the input file - outputFile = new File(actualOutputDirectory, baseDir.toURI().relativize(inputFile.toURI()).getPath()); - createOutputFile(outputFile); - } else { - outputFile = inputFile; + String type = getInputType(transformation); + if (actualOutputDirectory == null) { + throw new ConfigProcessorException("Output directory must be set"); + } + // calculate a relative path below the output directory based on the input file + File outputFile = new File(actualOutputDirectory, baseDir.toURI().relativize(inputFile.toURI()).getPath()); + createOutputFile(outputFile); + if (!inputFile.exists()) { + throw new ConfigProcessorException("File not found: " + inputFile); } - process(resolver, inputFile.getPath(), inputFile, outputFile, configIdentifier, action, type); + InputStream inputStream = new FileInputStream(inputFile); + process(resolver, inputFile.getPath(), inputStream, outputFile, configIdentifier, action, type); } } else { - File inputFile = fileResolver.resolve(transformation.getInput()); - if (!inputFile.exists()) { - throw new ConfigProcessorException("Input file [" + inputFile + "] does not exist"); + InputStream inputStream; + try { + inputStream = fileResolver.resolve(transformation.getInput()); + } catch (Exception e) { + throw new ConfigProcessorException("Input file [" + transformation.getInput() + "] does not exist", e); } // use input file as output file if output is not set File output; if (StringUtils.isBlank(transformation.getOutput())) { - output = inputFile; + throw new ConfigProcessorException("Output must be set"); } else { output = new File(actualOutputDirectory, transformation.getOutput()); createOutputFile(output); } - String type = getInputType(transformation, inputFile); - process(resolver, transformation.getInput(), inputFile, output, configIdentifier, action, type); + String type = getInputType(transformation); + process(resolver, transformation.getInput(), inputStream, output, configIdentifier, action, type); } } @@ -155,13 +161,13 @@ protected Action getAction(Transformation transformation) throws ConfigProcessor sb.append(XmlHelper.ROOT_PROCESSOR_END); configReader = new StringReader(sb.toString()); } else { - File config = fileResolver.resolve(transformation.getConfig()); + InputStream config = fileResolver.resolve(transformation.getConfig()); - if (!config.exists()) { + if (config == null) { throw new ConfigProcessorException("Configuration file [" + config + "] does not exist"); } - configReader = new InputStreamReader(new FileInputStream(config), encoding); + configReader = new InputStreamReader(config, encoding); } try { @@ -255,13 +261,13 @@ protected List getMatchingFiles(String pattern) throws ConfigProcessorExce * contain a type * @return Input file type. */ - protected String getInputType(Transformation transformation, File input) { + protected String getInputType(Transformation transformation) { String type; - + String input = transformation.getInput(); if (transformation.getType() == null) { - if (input.getName().endsWith(".properties")) { + if (input.endsWith(".properties")) { type = Transformation.PROPERTIES_TYPE; - } else if (input.getName().endsWith(".xml")) { + } else if (input.endsWith(".xml")) { type = Transformation.XML_TYPE; } else { if (getLog() != null) { @@ -283,23 +289,21 @@ protected String getInputType(Transformation transformation, File input) { * * @param resolver * @param inputName Symbolic name of the input file to read from. - * @param input Input file to read from. + * @param inputStream2 Input file to read from. * @param output Output file to write to. * @param configName Symbolic name of the file containing rules to process the input. * @param action Action to be performed on the input file. * @param type Type of the input file. Properties, XML or null if it is to be auto-detected. * @throws ConfigProcessorException If processing cannot be performed. */ - protected void process(ExpressionResolver resolver, String inputName, File input, File output, String configName, Action action, String type) throws ConfigProcessorException { + protected void process(ExpressionResolver resolver, String inputName, InputStream inputStream, File output, String configName, Action action, String type) throws ConfigProcessorException { getLog().info("Processing file [" + inputName + "] using config [" + configName + "], outputing to [" + output + "]"); - InputStream inputStream = null; ByteArrayOutputStream outputStream = null; InputStreamReader inputStreamReader = null; OutputStreamWriter outputStreamWriter = null; try { - inputStream = new FileInputStream(input); outputStream = new ByteArrayOutputStream(); inputStreamReader = new InputStreamReader(inputStream, encoding); diff --git a/maven-config-processor-plugin/src/main/java/com/google/code/configprocessor/io/ClasspathFileResolver.java b/maven-config-processor-plugin/src/main/java/com/google/code/configprocessor/io/ClasspathFileResolver.java index d016120..235a27f 100644 --- a/maven-config-processor-plugin/src/main/java/com/google/code/configprocessor/io/ClasspathFileResolver.java +++ b/maven-config-processor-plugin/src/main/java/com/google/code/configprocessor/io/ClasspathFileResolver.java @@ -15,17 +15,18 @@ */ package com.google.code.configprocessor.io; -import java.io.*; -import java.net.*; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; public class ClasspathFileResolver implements FileResolver { - public File resolve(String name) throws IOException { - URL url = getClass().getResource(name); - if (url == null) { + public InputStream resolve(String name) throws IOException { + InputStream inputStream = getClass().getResourceAsStream(name); + if (inputStream == null) { throw new FileNotFoundException("Classpath resource [" + name + "] not found"); } - return new File(url.getPath()); + return inputStream; } } diff --git a/maven-config-processor-plugin/src/main/java/com/google/code/configprocessor/io/DefaultFileResolver.java b/maven-config-processor-plugin/src/main/java/com/google/code/configprocessor/io/DefaultFileResolver.java index c264255..b16372a 100644 --- a/maven-config-processor-plugin/src/main/java/com/google/code/configprocessor/io/DefaultFileResolver.java +++ b/maven-config-processor-plugin/src/main/java/com/google/code/configprocessor/io/DefaultFileResolver.java @@ -19,12 +19,18 @@ public class DefaultFileResolver implements FileResolver { - public File resolve(String name) throws IOException { + ClasspathFileResolver classpathFileResolver = new ClasspathFileResolver(); + + public InputStream resolve(String name) throws IOException { + if (name.startsWith("classpath:")) { + String resourcePath = name.replace("classpath:", ""); + return classpathFileResolver.resolve(resourcePath); + } File file = new File(name); if (!file.exists()) { throw new FileNotFoundException("File [" + name + "] does not exist"); } - return file; + return new FileInputStream(file); } } diff --git a/maven-config-processor-plugin/src/main/java/com/google/code/configprocessor/io/FileResolver.java b/maven-config-processor-plugin/src/main/java/com/google/code/configprocessor/io/FileResolver.java index 7406cf9..25f4f12 100644 --- a/maven-config-processor-plugin/src/main/java/com/google/code/configprocessor/io/FileResolver.java +++ b/maven-config-processor-plugin/src/main/java/com/google/code/configprocessor/io/FileResolver.java @@ -19,6 +19,6 @@ public interface FileResolver { - File resolve(String name) throws IOException; + InputStream resolve(String name) throws IOException; } diff --git a/maven-config-processor-plugin/src/main/java/com/google/code/configprocessor/maven/MavenFileResolver.java b/maven-config-processor-plugin/src/main/java/com/google/code/configprocessor/maven/MavenFileResolver.java index 3f62312..58c4698 100644 --- a/maven-config-processor-plugin/src/main/java/com/google/code/configprocessor/maven/MavenFileResolver.java +++ b/maven-config-processor-plugin/src/main/java/com/google/code/configprocessor/maven/MavenFileResolver.java @@ -31,7 +31,7 @@ public class MavenFileResolver implements FileResolver { private Locator locator; private LogAdapter logAdapter; - + public MavenFileResolver(MavenProject mavenProject, ArtifactFactory artifactFactory, ArtifactResolver artifactResolver, ArtifactRepository localRepository, List remoteRepositories, LogAdapter logAdapter) { this.logAdapter = logAdapter; locator = new Locator(); @@ -43,19 +43,18 @@ public MavenFileResolver(MavenProject mavenProject, ArtifactFactory artifactFact locator.setStrategies(strategies); } - public File resolve(String name) throws IOException { + public InputStream resolve(String name) throws IOException { Location location = locator.resolve(name); if (location == null) { throw new IOException("File not found [" + name + "]\n" + locator.getMessageHolder().render()); } - - try { - File file = location.getFile(); - logAdapter.debug("Resolved [" + name + "] to file [" + file + "]"); - return file; - } catch (IOException e) { - throw new IOException("Failed to load file [" + name + "]\n" + locator.getMessageHolder().render()); + + InputStream inputStream = location.getInputStream(); + if (inputStream != null) { + logAdapter.debug("Resolved [" + name + "] to an inputStream [" + location + "]"); + return inputStream; } + throw new IOException("Failed to load file [" + name + "]\n" + locator.getMessageHolder().render()); } } diff --git a/maven-config-processor-plugin/src/main/java/com/google/code/configprocessor/processing/properties/PropertiesActionProcessor.java b/maven-config-processor-plugin/src/main/java/com/google/code/configprocessor/processing/properties/PropertiesActionProcessor.java index e2d5447..211e951 100644 --- a/maven-config-processor-plugin/src/main/java/com/google/code/configprocessor/processing/properties/PropertiesActionProcessor.java +++ b/maven-config-processor-plugin/src/main/java/com/google/code/configprocessor/processing/properties/PropertiesActionProcessor.java @@ -34,13 +34,13 @@ public class PropertiesActionProcessor implements ActionProcessor { private FileResolver fileResolver; private ExpressionResolver expressionResolver; - private Set appendedFiles; + private Set appendedFiles; public PropertiesActionProcessor(String encoding, FileResolver fileResolver, ExpressionResolver expressionResolver) { this.encoding = encoding; this.fileResolver = fileResolver; this.expressionResolver = expressionResolver; - this.appendedFiles = new HashSet(); + this.appendedFiles = new HashSet(); } public void process(Reader input, Writer output, Action action) throws ParsingException, IOException { @@ -48,7 +48,7 @@ public void process(Reader input, Writer output, Action action) throws ParsingEx BufferedWriter writer = new BufferedWriter(output); process(reader, writer, action); } - + protected void process(BufferedReader reader, BufferedWriter writer, Action action) throws ParsingException, IOException { PropertiesActionProcessingAdvisor advisor = getAdvisorFor(action); @@ -165,12 +165,12 @@ protected void append(PropertiesFileItem item, BufferedWriter writer) throws IOE writer.append(LINE_SEPARATOR); } } - + protected void appendFile(PropertiesFileItem item, BufferedWriter writer, Action action) throws ParsingException, IOException { FilePropertiesFileItem aux = (FilePropertiesFileItem)item; - File file = fileResolver.resolve(aux.getFile()); - if (appendedFiles.add(file)) { // Prevent adding the same file twice - InputStreamReader reader = new InputStreamReader(new FileInputStream(file), encoding); + InputStream inputStream = fileResolver.resolve(aux.getFile()); + if (appendedFiles.add(aux.getFile())) { // Prevent adding the same file twice + InputStreamReader reader = new InputStreamReader(inputStream, encoding); try { process(reader, writer, action); } finally { diff --git a/maven-config-processor-plugin/src/main/java/com/google/code/configprocessor/processing/xml/XmlActionProcessor.java b/maven-config-processor-plugin/src/main/java/com/google/code/configprocessor/processing/xml/XmlActionProcessor.java index 1df93e2..4c3479b 100644 --- a/maven-config-processor-plugin/src/main/java/com/google/code/configprocessor/processing/xml/XmlActionProcessor.java +++ b/maven-config-processor-plugin/src/main/java/com/google/code/configprocessor/processing/xml/XmlActionProcessor.java @@ -40,9 +40,9 @@ public class XmlActionProcessor implements ActionProcessor { private ExpressionResolver expressionResolver; private MapBasedNamespaceContext namespaceContext; private List parserFeatures; - private boolean failOnMissingXpath; + private boolean failOnMissingXpath; - public XmlActionProcessor(String encoding, int lineWidth, int indentSize, FileResolver fileResolver, ExpressionResolver expressionResolver, Map contextMappings, + public XmlActionProcessor(String encoding, int lineWidth, int indentSize, FileResolver fileResolver, ExpressionResolver expressionResolver, Map contextMappings, List parserFeatures, boolean failOnMissingXpath) { this.encoding = encoding; this.lineWidth = lineWidth; @@ -51,7 +51,7 @@ public XmlActionProcessor(String encoding, int lineWidth, int indentSize, FileRe this.expressionResolver = expressionResolver; this.namespaceContext = new MapBasedNamespaceContext(contextMappings); this.parserFeatures = parserFeatures; - this.failOnMissingXpath = failOnMissingXpath; + this.failOnMissingXpath = failOnMissingXpath; } public void process(Reader input, Writer output, Action action) throws ParsingException, IOException { @@ -108,8 +108,8 @@ protected XmlActionProcessingAdvisor getAdvisorFor(Action rootAction, Action act } protected String getProcessedFile(String name, Action action) throws ParsingException, IOException { - File file = fileResolver.resolve(name); - InputStreamReader reader = new InputStreamReader(new FileInputStream(file), encoding); + InputStream inputStream = fileResolver.resolve(name); + InputStreamReader reader = new InputStreamReader(inputStream, encoding); StringWriter writer = new StringWriter(); try { process(reader, writer, action); diff --git a/maven-config-processor-plugin/src/test/java/com/google/code/configprocessor/ConfigProcessorTest.java b/maven-config-processor-plugin/src/test/java/com/google/code/configprocessor/ConfigProcessorTest.java index 7a9a3ba..1f36422 100644 --- a/maven-config-processor-plugin/src/test/java/com/google/code/configprocessor/ConfigProcessorTest.java +++ b/maven-config-processor-plugin/src/test/java/com/google/code/configprocessor/ConfigProcessorTest.java @@ -15,21 +15,41 @@ */ package com.google.code.configprocessor; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.PrintWriter; +import java.util.List; +import java.util.Map; +import java.util.Properties; + +import org.codehaus.plexus.util.IOUtil; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TemporaryFolder; + import static org.easymock.EasyMock.*; import static org.easymock.classextension.EasyMock.*; import static org.junit.Assert.*; -import java.io.*; - -import org.junit.*; +import com.google.code.configprocessor.expression.ExpressionResolver; +import com.google.code.configprocessor.io.DefaultFileResolver; +import com.google.code.configprocessor.io.FileResolver; +import com.google.code.configprocessor.log.LogAdapter; +import com.google.code.configprocessor.processing.properties.AbstractPropertiesActionProcessingAdvisorTest; +import com.google.code.configprocessor.processing.properties.PropertiesActionProcessorTest; public class ConfigProcessorTest { private ConfigProcessor configProcessor; + @Rule + public TemporaryFolder folder= new TemporaryFolder(); + @Before public void setup() throws Exception { - configProcessor = new ConfigProcessor("UTF-8", 80, 4, null, null, null, false, null, null, null, true); + configProcessor = createConfigProcessor(null, false, null); } @Test(expected = ConfigProcessorException.class) @@ -52,14 +72,94 @@ public void testEmptyPattern() throws Exception { public void testGetTypeFromTransformation() throws Exception { Transformation transformation = new Transformation(); transformation.setType(Transformation.PROPERTIES_TYPE); - assertEquals(Transformation.PROPERTIES_TYPE, configProcessor.getInputType(transformation, null)); + assertEquals(Transformation.PROPERTIES_TYPE, configProcessor.getInputType(transformation)); } @Test public void testGuessTypeFromInputFile() throws Exception { + assertEquals(Transformation.PROPERTIES_TYPE, configProcessor.getInputType(transformationWithInput("test.properties"))); + assertEquals(Transformation.XML_TYPE, configProcessor.getInputType(transformationWithInput("test.xml"))); + assertEquals(Transformation.XML_TYPE, configProcessor.getInputType(transformationWithInput("test.something"))); + } + + private Transformation transformationWithInput(String input) { Transformation transformation = new Transformation(); - assertEquals(Transformation.PROPERTIES_TYPE, configProcessor.getInputType(transformation, new File("test.properties"))); - assertEquals(Transformation.XML_TYPE, configProcessor.getInputType(transformation, new File("test.xml"))); - assertEquals(Transformation.XML_TYPE, configProcessor.getInputType(transformation, new File("test.something"))); + transformation.setInput(input); + return transformation; + } + + @Test + public void testTransformationFromClasspathResource() throws Exception + { + File configFile = folder.newFile(); + PrintWriter writer = new PrintWriter(new FileOutputStream(configFile)); + writer.println(""); + writer.println(""); + writer.println(""); + writer.println("property1.value"); + writer.println("NEWTESTVALUE"); + writer.println(""); + writer.println(""); + writer.close(); + File outputDirectory = null; + File output = folder.newFile(); + boolean useOutputDirectory = false; + FileResolver fileResolver = new DefaultFileResolver(); + configProcessor = createConfigProcessor(outputDirectory, useOutputDirectory, fileResolver); + configProcessor.init(); + Transformation transformation = new Transformation(); + transformation.setInput("classpath:" + PropertiesActionProcessorTest.PROPERTIES_PATH); + transformation.setOutput(output.getAbsolutePath()); + transformation.setConfig(configFile.getAbsolutePath()); + ExpressionResolver resolver = getExpressionResolver(); + configProcessor.execute(resolver, transformation); + Properties properties = new Properties(); + properties.load(new FileInputStream(output.getAbsolutePath())); + assertEquals("NEWTESTVALUE", properties.getProperty("property1.value")); + } + + protected ExpressionResolver getExpressionResolver() { + return new AbstractPropertiesActionProcessingAdvisorTest.TestExpressionResolver(); + } + + private ConfigProcessor createConfigProcessor(File outputDirectory, + boolean useOutputDirectory, + FileResolver fileResolver) + { + Map namespaceContexts = null; + File baseDir = null; + LogAdapter log = new TestLogAdapter(); + List parserFeatures = null; + boolean failOnMissingXPath = true; + int indentSize = 4; + int lineWidth = 80; + return new ConfigProcessor("UTF-8", indentSize, lineWidth, namespaceContexts, baseDir, + outputDirectory, useOutputDirectory, log, fileResolver, parserFeatures, + failOnMissingXPath); + } + + public static class TestLogAdapter implements LogAdapter { + + public void info(String msg) { + System.out.println(msg); + } + + public void debug(String msg) { + System.out.println(msg); + } + + public void warn(String msg) { + System.out.println(msg); + } + + public void error(String msg, Throwable t) { + System.out.println(msg); + t.printStackTrace(System.out); + } + + public void verbose(String msg) { + System.out.println(msg); + } + } } diff --git a/maven-config-processor-plugin/src/test/java/com/google/code/configprocessor/processing/properties/AbstractPropertiesActionProcessingAdvisorTest.java b/maven-config-processor-plugin/src/test/java/com/google/code/configprocessor/processing/properties/AbstractPropertiesActionProcessingAdvisorTest.java index 6464772..c248334 100644 --- a/maven-config-processor-plugin/src/test/java/com/google/code/configprocessor/processing/properties/AbstractPropertiesActionProcessingAdvisorTest.java +++ b/maven-config-processor-plugin/src/test/java/com/google/code/configprocessor/processing/properties/AbstractPropertiesActionProcessingAdvisorTest.java @@ -33,11 +33,11 @@ public class AbstractPropertiesActionProcessingAdvisorTest { private static final String ENCODING = "ISO-8859-1"; - + protected InputStream input; protected ByteArrayOutputStream output; protected ActionProcessor processor; - + public void setup() { processor = new PropertiesActionProcessor(ENCODING, new ClasspathFileResolver(), new MavenExpressionResolver(new DefaultExpressionEvaluator())); input = getClass().getResourceAsStream(PropertiesActionProcessorTest.PROPERTIES_PATH); @@ -57,19 +57,19 @@ protected void executeTest(Action action, String expected) throws Exception { setup(); processor.process(new InputStreamReader(input), new OutputStreamWriter(output), action); assertEquals(expected, getOutput()); - + setup(); NestedAction nestedAction = new NestedAction(); nestedAction.addAction(action); processor.process(new InputStreamReader(input), new OutputStreamWriter(output), nestedAction); assertEquals(expected, getOutput()); } - + protected String getOutput() { return new String(output.toByteArray()); } - private static class TestExpressionResolver implements ExpressionResolver { + public static class TestExpressionResolver implements ExpressionResolver { private List resolvedValues = new ArrayList(); public String resolve(String value, boolean isPropertiesValue) {