diff --git a/pom.xml b/pom.xml
index cfb624e..068da3c 100644
--- a/pom.xml
+++ b/pom.xml
@@ -126,6 +126,26 @@
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+
+
+
+ org.eclipse.sisu
+ org.eclipse.sisu.inject
+ 0.9.0.M2
+
+
+
+
+
+
+
+
run-its
diff --git a/src/it/read-project/invoker.properties b/src/it/read-project/invoker.properties
new file mode 100644
index 0000000..6b7e315
--- /dev/null
+++ b/src/it/read-project/invoker.properties
@@ -0,0 +1 @@
+invoker.goals = clean process-resources
diff --git a/src/it/read-project/main.properties b/src/it/read-project/main.properties
new file mode 100644
index 0000000..7d46145
--- /dev/null
+++ b/src/it/read-project/main.properties
@@ -0,0 +1,6 @@
+
+# test properties for IT
+
+props1 = value1
+props2 = value2
+props3 = value3
diff --git a/src/it/read-project/main2.txt b/src/it/read-project/main2.txt
new file mode 100644
index 0000000..fdbf222
--- /dev/null
+++ b/src/it/read-project/main2.txt
@@ -0,0 +1,4 @@
+
+# test properties for IT
+
+props3 = value3
diff --git a/src/it/read-project/pom.xml b/src/it/read-project/pom.xml
new file mode 100644
index 0000000..24cb6b4
--- /dev/null
+++ b/src/it/read-project/pom.xml
@@ -0,0 +1,42 @@
+
+
+ 4.0.0
+
+ org.codehaus.mojo.properties.it
+ write-project
+ 0.0.1-SNAPSHOT
+
+
+
+
+
+ src/main/resources
+ true
+
+
+
+
+
+ org.codehaus.mojo
+ properties-maven-plugin
+ @project.version@
+
+
+ generate-resources
+
+ read-project-properties
+
+
+
+ main.properties
+
+ main2.txt
+
+
+
+
+
+
+
+
diff --git a/src/it/read-project/src/main/resources/test.txt b/src/it/read-project/src/main/resources/test.txt
new file mode 100644
index 0000000..23ec275
--- /dev/null
+++ b/src/it/read-project/src/main/resources/test.txt
@@ -0,0 +1,5 @@
+Test resource using properties from external files
+
+props1 has value ${props1}
+props2 has value ${props2}
+props3 has value ${props3}
diff --git a/src/it/read-project/verify.groovy b/src/it/read-project/verify.groovy
new file mode 100644
index 0000000..ad1e040
--- /dev/null
+++ b/src/it/read-project/verify.groovy
@@ -0,0 +1,30 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.
+ */
+File testFile = new File( basedir, 'target/classes/test.txt' )
+assert testFile.exists()
+
+String content = testFile.getText()
+assert content.contains('props1 has value value1')
+assert content.contains('props2 has value value2')
+assert content.contains('props3 has value value3')
+
+File buildLog = new File( basedir, 'build.log' )
+assert buildLog.exists()
+assert buildLog.getText().contains("[WARNING] Unknown properties resource extension: 'txt' assume as: 'properties'")
+
diff --git a/src/main/java/org/codehaus/mojo/properties/AbstractPropertiesMojo.java b/src/main/java/org/codehaus/mojo/properties/AbstractPropertiesMojo.java
new file mode 100644
index 0000000..084d383
--- /dev/null
+++ b/src/main/java/org/codehaus/mojo/properties/AbstractPropertiesMojo.java
@@ -0,0 +1,44 @@
+package org.codehaus.mojo.properties;
+
+import java.util.List;
+import java.util.Locale;
+import java.util.Optional;
+
+import org.apache.maven.plugin.AbstractMojo;
+import org.codehaus.mojo.properties.managers.PropertiesManager;
+
+/**
+ * Abstract Mojo with Properties managers support.
+ */
+public abstract class AbstractPropertiesMojo extends AbstractMojo {
+
+ private final List propertiesManagers;
+
+ protected AbstractPropertiesMojo(List propertiesManagers) {
+ this.propertiesManagers = propertiesManagers;
+ }
+
+ protected PropertiesManager getPropertiesManager(String resourceExtension) {
+ getLog().debug("Available properties managers: " + propertiesManagers);
+
+ String resourceExtensionLowerCase = resourceExtension.toLowerCase(Locale.ROOT);
+ Optional propertiesStore = propertiesManagers.stream()
+ .filter(manager -> manager.isExtensionSupport(resourceExtensionLowerCase))
+ .findFirst();
+
+ if (!propertiesStore.isPresent()) {
+ getLog().warn("Unknown properties resource extension: '" + resourceExtension + "' assume as: '"
+ + PropertiesManager.DEFAULT_MANAGER_EXTENSION + "'");
+ return getDefaultPropertiesManager();
+ } else {
+ return propertiesStore.get();
+ }
+ }
+
+ private PropertiesManager getDefaultPropertiesManager() {
+ return propertiesManagers.stream()
+ .filter(manager -> manager.isExtensionSupport(PropertiesManager.DEFAULT_MANAGER_EXTENSION))
+ .findFirst()
+ .orElseThrow(() -> new RuntimeException("Default properties manager not exist"));
+ }
+}
diff --git a/src/main/java/org/codehaus/mojo/properties/AbstractWritePropertiesMojo.java b/src/main/java/org/codehaus/mojo/properties/AbstractWritePropertiesMojo.java
index f2ee3b3..546912b 100644
--- a/src/main/java/org/codehaus/mojo/properties/AbstractWritePropertiesMojo.java
+++ b/src/main/java/org/codehaus/mojo/properties/AbstractWritePropertiesMojo.java
@@ -19,75 +19,56 @@
* under the License.
*/
-import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
-import java.io.PrintWriter;
-import java.io.StringReader;
-import java.io.StringWriter;
-import java.util.ArrayList;
-import java.util.Collections;
+import java.nio.file.Files;
import java.util.List;
import java.util.Properties;
-import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugins.annotations.Parameter;
import org.apache.maven.project.MavenProject;
+import org.codehaus.mojo.properties.managers.PropertiesManager;
+import org.codehaus.plexus.util.FileUtils;
/**
* @author Zarar Siddiqi
*/
-public abstract class AbstractWritePropertiesMojo extends AbstractMojo {
+public abstract class AbstractWritePropertiesMojo extends AbstractPropertiesMojo {
@Parameter(defaultValue = "${project}", required = true, readonly = true)
private MavenProject project;
+ /**
+ * Output file for storing properties.
+ *
+ * @since 1.0.0
+ */
@Parameter(required = true, property = "properties.outputFile")
private File outputFile;
+ protected AbstractWritePropertiesMojo(List propertiesManagers) {
+ super(propertiesManagers);
+ }
+
/**
* @param properties {@link Properties}
- * @param file {@link File}
* @throws MojoExecutionException {@link MojoExecutionException}
*/
- protected void writeProperties(Properties properties, File file) throws MojoExecutionException {
+ protected void writeProperties(Properties properties) throws MojoExecutionException {
try {
- storeWithoutTimestamp(properties, file, "Properties");
+ PropertiesManager manager = getPropertiesManager(FileUtils.extension(outputFile.getName()));
+ manager.save(properties, Files.newOutputStream(outputFile.toPath()), "Properties");
} catch (FileNotFoundException e) {
- getLog().error("Could not create FileOutputStream: " + file);
+ getLog().error("Could not create FileOutputStream: " + outputFile);
throw new MojoExecutionException(e.getMessage(), e);
} catch (IOException e) {
- getLog().error("Error writing properties: " + file);
+ getLog().error("Error writing properties: " + outputFile);
throw new MojoExecutionException(e.getMessage(), e);
}
}
- // https://github.com/apache/maven-archiver/blob/master/src/main/java/org/apache/maven/archiver/PomPropertiesUtil.java#L81
- private void storeWithoutTimestamp(Properties properties, File outputFile, String comments) throws IOException {
- try (PrintWriter pw = new PrintWriter(outputFile, "ISO-8859-1");
- StringWriter sw = new StringWriter()) {
- properties.store(sw, comments);
- comments = '#' + comments;
-
- List lines = new ArrayList<>();
- try (BufferedReader r = new BufferedReader(new StringReader(sw.toString()))) {
- String line;
- while ((line = r.readLine()) != null) {
- if (!line.startsWith("#") || line.equals(comments)) {
- lines.add(line);
- }
- }
- }
-
- Collections.sort(lines);
- for (String l : lines) {
- pw.println(l);
- }
- }
- }
-
/**
* @throws MojoExecutionException {@link MojoExecutionException}
*/
@@ -107,11 +88,4 @@ protected void validateOutputFile() throws MojoExecutionException {
public MavenProject getProject() {
return project;
}
-
- /**
- * @return {@link #outputFile}
- */
- public File getOutputFile() {
- return outputFile;
- }
}
diff --git a/src/main/java/org/codehaus/mojo/properties/ReadPropertiesMojo.java b/src/main/java/org/codehaus/mojo/properties/ReadPropertiesMojo.java
index 09c1342..747aaed 100644
--- a/src/main/java/org/codehaus/mojo/properties/ReadPropertiesMojo.java
+++ b/src/main/java/org/codehaus/mojo/properties/ReadPropertiesMojo.java
@@ -19,26 +19,30 @@
* under the License.
*/
+import javax.inject.Inject;
+
import java.io.BufferedInputStream;
import java.io.File;
-import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
+import java.nio.file.Files;
import java.util.Enumeration;
import java.util.HashMap;
+import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Properties;
-import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.plugins.annotations.LifecyclePhase;
import org.apache.maven.plugins.annotations.Mojo;
import org.apache.maven.plugins.annotations.Parameter;
import org.apache.maven.project.MavenProject;
+import org.codehaus.mojo.properties.managers.PropertiesManager;
+import org.codehaus.plexus.util.FileUtils;
import org.codehaus.plexus.util.cli.CommandLineUtils;
/**
@@ -48,54 +52,37 @@
*
* @author Zarar Siddiqi
* @author Krystian Nowak
+ *
+ * @since 1.0.0
*/
@Mojo(name = "read-project-properties", defaultPhase = LifecyclePhase.NONE, threadSafe = true)
-public class ReadPropertiesMojo extends AbstractMojo {
+public class ReadPropertiesMojo extends AbstractPropertiesMojo {
+
@Parameter(defaultValue = "${project}", readonly = true, required = true)
private MavenProject project;
/**
* The properties files that will be used when reading properties.
+ *
+ * @since 1.0.0
*/
@Parameter
private File[] files = new File[0];
- /**
- * @param files The files to set for tests.
- */
- public void setFiles(File[] files) {
- if (files == null) {
- this.files = new File[0];
- } else {
- this.files = new File[files.length];
- System.arraycopy(files, 0, this.files, 0, files.length);
- }
- }
-
/**
* The URLs that will be used when reading properties. These may be non-standard URLs of the form
* classpath:com/company/resource.properties
. Note that the type is not URL
for this
* reason and therefore will be explicitly checked by this Mojo.
+ *
+ * @since 1.0.0
*/
@Parameter
private String[] urls = new String[0];
- /**
- * Default scope for test access.
- *
- * @param urls The URLs to set for tests.
- */
- public void setUrls(String[] urls) {
- if (urls == null) {
- this.urls = null;
- } else {
- this.urls = new String[urls.length];
- System.arraycopy(urls, 0, this.urls, 0, urls.length);
- }
- }
-
/**
* If the plugin should be quiet if any of the files was not found
+ *
+ * @since 1.0.0
*/
@Parameter(defaultValue = "false")
private boolean quiet;
@@ -103,21 +90,24 @@ public void setUrls(String[] urls) {
/**
* Prefix that will be added before name of each property.
* Can be useful for separating properties with same name from different files.
+ *
+ * @since 1.1.0
*/
@Parameter
private String keyPrefix = null;
- public void setKeyPrefix(String keyPrefix) {
- this.keyPrefix = keyPrefix;
- }
-
+ /**
+ * Skip plugin execution.
+ *
+ * @since 1.2.0
+ */
@Parameter(defaultValue = "false", property = "prop.skipLoadProperties")
private boolean skipLoadProperties;
/**
* If the plugin should process default values within property placeholders
*
- * @parameter default-value="false"
+ * @since 1.2.0
*/
@Parameter(defaultValue = "false")
private boolean useDefaultValues;
@@ -130,15 +120,47 @@ public void setKeyPrefix(String keyPrefix) {
@Parameter(defaultValue = "true")
private boolean override = true;
- public void setOverride(boolean override) {
- this.override = override;
- }
-
/**
* Used for resolving property placeholders.
*/
private final PropertyResolver resolver = new PropertyResolver();
+ /**
+ * Default constructor
+ *
+ * @param propertiesManagers list of properties managers
+ */
+ @Inject
+ public ReadPropertiesMojo(List propertiesManagers) {
+ super(propertiesManagers);
+ }
+
+ /**
+ * @param files The files to set for tests.
+ */
+ public void setFiles(File[] files) {
+ if (files == null) {
+ this.files = new File[0];
+ } else {
+ this.files = new File[files.length];
+ System.arraycopy(files, 0, this.files, 0, files.length);
+ }
+ }
+
+ /**
+ * Default scope for test access.
+ *
+ * @param urls The URLs to set for tests.
+ */
+ public void setUrls(String[] urls) {
+ if (urls == null) {
+ this.urls = null;
+ } else {
+ this.urls = new String[urls.length];
+ System.arraycopy(urls, 0, this.urls, 0, urls.length);
+ }
+ }
+
/** {@inheritDoc} */
public void execute() throws MojoExecutionException, MojoFailureException {
if (!skipLoadProperties) {
@@ -188,8 +210,9 @@ private void loadProperties(Resource resource) throws MojoExecutionException {
effectivePrefix = keyPrefix;
}
- Properties properties = new Properties();
- properties.load(stream);
+ PropertiesManager manager = getPropertiesManager(resource.getResourceExtension());
+ Properties properties = manager.load(stream);
+
Properties projectProperties = project.getProperties();
Map newProperties = new HashMap<>();
@@ -283,27 +306,18 @@ Properties getSystemEnvVars() throws IOException {
}
/**
- * Default scope for test access.
- *
- * @param quiet Set to true
if missing files can be skipped.
+ * @param useDefaultValues set to true
if default values need to be processed within property placeholders
*/
- void setQuiet(boolean quiet) {
- this.quiet = quiet;
+ public void setUseDefaultValues(boolean useDefaultValues) {
+ this.useDefaultValues = useDefaultValues;
}
- /**
- *
- * @param skipLoadProperties Set to true
if you don't want to load properties.
- */
- void setSkipLoadProperties(boolean skipLoadProperties) {
- this.skipLoadProperties = skipLoadProperties;
+ void setKeyPrefix(String keyPrefix) {
+ this.keyPrefix = keyPrefix;
}
- /**
- * @param useDefaultValues set to true
if default values need to be processed within property placeholders
- */
- public void setUseDefaultValues(boolean useDefaultValues) {
- this.useDefaultValues = useDefaultValues;
+ void setOverride(boolean override) {
+ this.override = override;
}
/**
@@ -326,6 +340,8 @@ public MavenProject getProject() {
private abstract static class Resource {
private InputStream stream;
+ public abstract String getResourceExtension();
+
public abstract boolean canBeOpened();
protected abstract InputStream openStream() throws IOException;
@@ -345,14 +361,22 @@ private static class FileResource extends Resource {
this.file = file;
}
+ @Override
+ public String getResourceExtension() {
+ return FileUtils.extension(file.getName());
+ }
+
+ @Override
public boolean canBeOpened() {
return file.exists();
}
+ @Override
protected InputStream openStream() throws IOException {
- return new BufferedInputStream(new FileInputStream(file));
+ return new BufferedInputStream(Files.newInputStream(file.toPath()));
}
+ @Override
public String toString() {
return "File: " + file;
}
@@ -389,6 +413,12 @@ private static class UrlResource extends Resource {
}
}
+ @Override
+ public String getResourceExtension() {
+ return FileUtils.extension(url.getFile());
+ }
+
+ @Override
public boolean canBeOpened() {
if (isMissingClasspathResouce) {
return false;
@@ -401,10 +431,12 @@ public boolean canBeOpened() {
return true;
}
+ @Override
protected InputStream openStream() throws IOException {
return new BufferedInputStream(url.openStream());
}
+ @Override
public String toString() {
if (!isMissingClasspathResouce) {
return "URL " + url.toString();
diff --git a/src/main/java/org/codehaus/mojo/properties/SetSystemPropertiesMojo.java b/src/main/java/org/codehaus/mojo/properties/SetSystemPropertiesMojo.java
index 9d6b945..ee668ee 100644
--- a/src/main/java/org/codehaus/mojo/properties/SetSystemPropertiesMojo.java
+++ b/src/main/java/org/codehaus/mojo/properties/SetSystemPropertiesMojo.java
@@ -31,6 +31,8 @@
* Sets system properties.
*
* @author Mark Hobson
+ *
+ * @since 1.0.0
*/
@Mojo(name = "set-system-properties", defaultPhase = LifecyclePhase.INITIALIZE, threadSafe = true)
public class SetSystemPropertiesMojo extends AbstractMojo {
@@ -38,15 +40,15 @@ public class SetSystemPropertiesMojo extends AbstractMojo {
/**
* The system properties to set.
+ *
+ * @since 1.0.0
*/
@Parameter(required = true)
private Properties properties;
// Mojo methods -----------------------------------------------------------
- /**
- * {@inheritDoc}
- */
+ @Override
public void execute() {
if (properties.isEmpty()) {
getLog().debug("No system properties found");
diff --git a/src/main/java/org/codehaus/mojo/properties/WriteActiveProfileProperties.java b/src/main/java/org/codehaus/mojo/properties/WriteActiveProfileProperties.java
index 812194b..e2c744a 100644
--- a/src/main/java/org/codehaus/mojo/properties/WriteActiveProfileProperties.java
+++ b/src/main/java/org/codehaus/mojo/properties/WriteActiveProfileProperties.java
@@ -19,6 +19,8 @@
* under the License.
*/
+import javax.inject.Inject;
+
import java.util.List;
import java.util.Properties;
@@ -26,15 +28,29 @@
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugins.annotations.LifecyclePhase;
import org.apache.maven.plugins.annotations.Mojo;
+import org.codehaus.mojo.properties.managers.PropertiesManager;
/**
* Writes properties of all active profiles to a file.
*
* @author Zarar Siddiqi
+ *
+ * @since 1.0.0
*/
@Mojo(name = "write-active-profile-properties", defaultPhase = LifecyclePhase.NONE, threadSafe = true)
public class WriteActiveProfileProperties extends AbstractWritePropertiesMojo {
- /** {@inheritDoc} */
+
+ /**
+ * Default constructor
+ *
+ * @param propertiesManagers list of properties managers
+ */
+ @Inject
+ protected WriteActiveProfileProperties(List propertiesManagers) {
+ super(propertiesManagers);
+ }
+
+ @Override
public void execute() throws MojoExecutionException {
validateOutputFile();
List list = getProject().getActiveProfiles();
@@ -48,6 +64,6 @@ public void execute() throws MojoExecutionException {
}
}
- writeProperties(properties, getOutputFile());
+ writeProperties(properties);
}
}
diff --git a/src/main/java/org/codehaus/mojo/properties/WriteProjectProperties.java b/src/main/java/org/codehaus/mojo/properties/WriteProjectProperties.java
index 9f093dc..2fa37e5 100644
--- a/src/main/java/org/codehaus/mojo/properties/WriteProjectProperties.java
+++ b/src/main/java/org/codehaus/mojo/properties/WriteProjectProperties.java
@@ -19,21 +19,38 @@
* under the License.
*/
+import javax.inject.Inject;
+
import java.util.Enumeration;
+import java.util.List;
import java.util.Properties;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugins.annotations.LifecyclePhase;
import org.apache.maven.plugins.annotations.Mojo;
+import org.codehaus.mojo.properties.managers.PropertiesManager;
/**
* Writes project properties to a file.
*
* @author Zarar Siddiqi
+ *
+ * @since 1.0.0
*/
@Mojo(name = "write-project-properties", defaultPhase = LifecyclePhase.NONE, threadSafe = true)
public class WriteProjectProperties extends AbstractWritePropertiesMojo {
- /** {@inheritDoc} */
+
+ /**
+ * Default constructor
+ *
+ * @param propertiesManagers list of properties managers
+ */
+ @Inject
+ protected WriteProjectProperties(List propertiesManagers) {
+ super(propertiesManagers);
+ }
+
+ @Override
public void execute() throws MojoExecutionException {
validateOutputFile();
Properties projProperties = new Properties();
@@ -51,6 +68,6 @@ public void execute() throws MojoExecutionException {
}
}
- writeProperties(projProperties, getOutputFile());
+ writeProperties(projProperties);
}
}
diff --git a/src/main/java/org/codehaus/mojo/properties/managers/JdkPropertiesManager.java b/src/main/java/org/codehaus/mojo/properties/managers/JdkPropertiesManager.java
new file mode 100644
index 0000000..fc81293
--- /dev/null
+++ b/src/main/java/org/codehaus/mojo/properties/managers/JdkPropertiesManager.java
@@ -0,0 +1,72 @@
+package org.codehaus.mojo.properties.managers;
+
+import javax.inject.Named;
+import javax.inject.Singleton;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.io.PrintWriter;
+import java.io.StringReader;
+import java.io.StringWriter;
+import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Properties;
+
+/**
+ * Properties manager using JDK properties as backand.
+ */
+@Named
+@Singleton
+public class JdkPropertiesManager implements PropertiesManager {
+
+ private static final String SUPPORTED_EXTENSION = "properties";
+
+ @Override
+ public boolean isExtensionSupport(String extension) {
+ return SUPPORTED_EXTENSION.equals(extension);
+ }
+
+ @Override
+ public Properties load(InputStream in) throws IOException {
+ Properties properties = new Properties();
+ properties.load(in);
+ return properties;
+ }
+
+ @Override
+ public void save(Properties properties, OutputStream out, String comments) throws IOException {
+
+ OutputStreamWriter outputStreamWriter = new OutputStreamWriter(out, StandardCharsets.ISO_8859_1);
+
+ try (PrintWriter pw = new PrintWriter(outputStreamWriter);
+ StringWriter sw = new StringWriter()) {
+ properties.store(sw, comments);
+ comments = '#' + comments;
+
+ List lines = new ArrayList<>();
+ try (BufferedReader r = new BufferedReader(new StringReader(sw.toString()))) {
+ String line;
+ while ((line = r.readLine()) != null) {
+ if (!line.startsWith("#") || line.equals(comments)) {
+ lines.add(line);
+ }
+ }
+ }
+
+ Collections.sort(lines);
+ for (String l : lines) {
+ pw.println(l);
+ }
+ }
+ }
+
+ @Override
+ public String toString() {
+ return String.format("%s [extension=%s]", getClass().getSimpleName(), SUPPORTED_EXTENSION);
+ }
+}
diff --git a/src/main/java/org/codehaus/mojo/properties/managers/PropertiesManager.java b/src/main/java/org/codehaus/mojo/properties/managers/PropertiesManager.java
new file mode 100644
index 0000000..df8d07c
--- /dev/null
+++ b/src/main/java/org/codehaus/mojo/properties/managers/PropertiesManager.java
@@ -0,0 +1,40 @@
+package org.codehaus.mojo.properties.managers;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.Properties;
+
+/**
+ * Interface for properties managers implementations.
+ */
+public interface PropertiesManager {
+
+ String DEFAULT_MANAGER_EXTENSION = "properties";
+
+ /**
+ * Determinate if manager support resource by file extension.
+ *
+ * @param extension file extension
+ * @return true if extension is supported
+ */
+ boolean isExtensionSupport(String extension);
+ /**
+ * Load properties.
+ *
+ * @param in input stream of properties resource
+ * @return a properties
+ * @throws IOException in case of IO problems
+ */
+ Properties load(InputStream in) throws IOException;
+
+ /**
+ * Store properties
+ *
+ * @param properties properties to store
+ * @param out output stream of properties resource
+ * @param comments a comments added to output resource
+ * @throws IOException in case of IO problems
+ */
+ void save(Properties properties, OutputStream out, String comments) throws IOException;
+}
diff --git a/src/test/java/org/codehaus/mojo/properties/ReadPropertiesMojoTest.java b/src/test/java/org/codehaus/mojo/properties/ReadPropertiesMojoTest.java
index cb22eff..4b2d117 100644
--- a/src/test/java/org/codehaus/mojo/properties/ReadPropertiesMojoTest.java
+++ b/src/test/java/org/codehaus/mojo/properties/ReadPropertiesMojoTest.java
@@ -4,12 +4,14 @@
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
+import java.util.Collections;
import java.util.Properties;
import org.apache.maven.model.Model;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.project.MavenProject;
+import org.codehaus.mojo.properties.managers.JdkPropertiesManager;
import org.junit.Before;
import org.junit.Test;
@@ -26,7 +28,7 @@ public class ReadPropertiesMojoTest {
@Before
public void setUp() {
projectStub = new MavenProject();
- readPropertiesMojo = new ReadPropertiesMojo();
+ readPropertiesMojo = new ReadPropertiesMojo(Collections.singletonList(new JdkPropertiesManager()));
readPropertiesMojo.setProject(projectStub);
}
diff --git a/src/test/java/org/codehaus/mojo/properties/managers/JdkPropertiesManagerTest.java b/src/test/java/org/codehaus/mojo/properties/managers/JdkPropertiesManagerTest.java
new file mode 100644
index 0000000..41f1081
--- /dev/null
+++ b/src/test/java/org/codehaus/mojo/properties/managers/JdkPropertiesManagerTest.java
@@ -0,0 +1,54 @@
+package org.codehaus.mojo.properties.managers;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.util.Properties;
+
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+
+public class JdkPropertiesManagerTest {
+
+ private static final String NL = System.lineSeparator();
+ ;
+
+ private final JdkPropertiesManager manager = new JdkPropertiesManager();
+
+ @Test
+ public void testLoad() throws IOException {
+
+ // given
+ String props = "# comments" + NL + NL + "key1=value1" + NL + "key2 = value2";
+
+ ByteArrayInputStream inputStream = new ByteArrayInputStream(props.getBytes());
+
+ // when
+ Properties properties = manager.load(inputStream);
+
+ // then
+ assertEquals(2, properties.size());
+ assertEquals("value1", properties.getProperty("key1"));
+ assertEquals("value2", properties.getProperty("key2"));
+ }
+
+ @Test
+ public void testSave() throws IOException {
+
+ // given
+ Properties properties = new Properties();
+ properties.setProperty("key1", "value1");
+ properties.setProperty("key2", "value2");
+
+ ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+
+ // when
+ manager.save(properties, outputStream, "Test comments");
+
+ // then
+ String expected = "#Test comments" + NL + "key1=value1" + NL + "key2=value2" + NL;
+
+ assertEquals(expected, outputStream.toString());
+ }
+}