You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@karaf.apache.org by gg...@apache.org on 2017/06/21 13:32:29 UTC

[6/6] karaf git commit: [KARAF-5008] maven:password command

[KARAF-5008] maven:password command


Project: http://git-wip-us.apache.org/repos/asf/karaf/repo
Commit: http://git-wip-us.apache.org/repos/asf/karaf/commit/ecc21a3c
Tree: http://git-wip-us.apache.org/repos/asf/karaf/tree/ecc21a3c
Diff: http://git-wip-us.apache.org/repos/asf/karaf/diff/ecc21a3c

Branch: refs/heads/master-maven-commands
Commit: ecc21a3c45063ce1c88f7306f4e62865d24260d2
Parents: 750fd14
Author: Grzegorz Grzybek <gr...@gmail.com>
Authored: Tue Jun 20 12:17:46 2017 +0200
Committer: Grzegorz Grzybek <gr...@gmail.com>
Committed: Wed Jun 21 15:31:54 2017 +0200

----------------------------------------------------------------------
 maven/core/pom.xml                              |   6 ++
 .../karaf/maven/command/HttpProxyCommand.java   |   2 +-
 .../command/MavenConfigurationSupport.java      |  60 ++++++++++-
 .../maven/command/MavenSecuritySupport.java     |  31 ++++++
 .../karaf/maven/command/PasswordCommand.java    | 103 +++++++++++++++++++
 .../command/RepositoryEditCommandSupport.java   |   2 +-
 .../maven/command/RepositoryListCommand.java    |   2 +-
 .../karaf/maven/command/SummaryCommand.java     |   2 +-
 .../org/apache/karaf/maven/SettingsTest.java    |   2 +
 .../command/MavenConfigurationSupportTest.java  |  60 +++++++++++
 maven/core/src/test/resources/log4j.properties  |  34 ++++++
 11 files changed, 295 insertions(+), 9 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/karaf/blob/ecc21a3c/maven/core/pom.xml
----------------------------------------------------------------------
diff --git a/maven/core/pom.xml b/maven/core/pom.xml
index db2f2a7..a2a724f 100644
--- a/maven/core/pom.xml
+++ b/maven/core/pom.xml
@@ -66,6 +66,12 @@
             <artifactId>maven-embedder</artifactId>
             <version>3.0.3</version>
         </dependency>
+
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-log4j12</artifactId>
+            <scope>test</scope>
+        </dependency>
     </dependencies>
 
     <build>

http://git-wip-us.apache.org/repos/asf/karaf/blob/ecc21a3c/maven/core/src/main/java/org/apache/karaf/maven/command/HttpProxyCommand.java
----------------------------------------------------------------------
diff --git a/maven/core/src/main/java/org/apache/karaf/maven/command/HttpProxyCommand.java b/maven/core/src/main/java/org/apache/karaf/maven/command/HttpProxyCommand.java
index 6f8b794..129aca5 100644
--- a/maven/core/src/main/java/org/apache/karaf/maven/command/HttpProxyCommand.java
+++ b/maven/core/src/main/java/org/apache/karaf/maven/command/HttpProxyCommand.java
@@ -27,7 +27,7 @@ import org.apache.maven.settings.Proxy;
 
 @Command(scope = "maven", name = "http-proxy", description = "Manage HTTP proxy configuration for Maven remote repositories")
 @Service
-public class HttpProxyCommand extends MavenConfigurationSupport {
+public class HttpProxyCommand extends MavenSecuritySupport {
 
     @Option(name = "--add", description = "Adds HTTP proxy configuration to Maven settings", required = false, multiValued = false)
     boolean add;

http://git-wip-us.apache.org/repos/asf/karaf/blob/ecc21a3c/maven/core/src/main/java/org/apache/karaf/maven/command/MavenConfigurationSupport.java
----------------------------------------------------------------------
diff --git a/maven/core/src/main/java/org/apache/karaf/maven/command/MavenConfigurationSupport.java b/maven/core/src/main/java/org/apache/karaf/maven/command/MavenConfigurationSupport.java
index 4c3416a..0588afd 100644
--- a/maven/core/src/main/java/org/apache/karaf/maven/command/MavenConfigurationSupport.java
+++ b/maven/core/src/main/java/org/apache/karaf/maven/command/MavenConfigurationSupport.java
@@ -17,10 +17,13 @@
 package org.apache.karaf.maven.command;
 
 import java.io.File;
+import java.io.IOException;
 import java.lang.reflect.Field;
 import java.net.MalformedURLException;
 import java.net.URL;
+import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Date;
 import java.util.Dictionary;
 import java.util.HashMap;
 import java.util.LinkedHashSet;
@@ -28,10 +31,11 @@ import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import java.util.TreeSet;
+import java.util.regex.Pattern;
 
 import org.apache.karaf.maven.core.MavenRepositoryURL;
 import org.apache.karaf.shell.api.action.Action;
-import org.apache.karaf.shell.api.action.Option;
 import org.apache.karaf.shell.api.action.lifecycle.Reference;
 import org.apache.karaf.shell.api.console.Session;
 import org.apache.karaf.shell.support.table.Row;
@@ -72,6 +76,12 @@ public abstract class MavenConfigurationSupport implements Action {
 
     protected static final String PATTERN_PID_PROPERTY = "Explicit %s PID configuration (%s)";
 
+    protected static final String PATTERN_SECURITY_SETTINGS = "maven-security-settings-%d.xml";
+    protected static final Pattern RE_SECURITY_SETTINGS = Pattern.compile("maven-security-settings-(\\d+)\\.xml");
+    protected static final String PATTERN_SETTINGS = "maven-settings-%d.xml";
+    protected static final Pattern RE_SETTINGS = Pattern.compile("maven-settings-(\\d+)\\.xml");
+    private static final int MAX_SEQUENCE_SIZE = 10;
+
     protected static final String PROPERTY_LOCAL_REPOSITORY = "localRepository";
     protected static final String PROPERTY_DEFAULT_REPOSITORIES = "defaultRepositories";
     protected static final String PROPERTY_REPOSITORIES = "repositories";
@@ -122,9 +132,6 @@ public abstract class MavenConfigurationSupport implements Action {
     @Reference
     protected Session session;
 
-    @Option(name = "-x", aliases = { "--show-passwords" }, description = "Do not hide passwords related to Maven encryption", required = false, multiValued = false)
-    boolean showPasswords;
-
     @Override
     final public Object execute() throws Exception {
         Configuration c = cm.getConfiguration(PID);
@@ -144,7 +151,7 @@ public abstract class MavenConfigurationSupport implements Action {
 
                 localRepository = localRepository((String) c.getProperties().get(PID + "." + PROPERTY_LOCAL_REPOSITORY));
 
-                if (showPasswords) {
+                if (showPasswords()) {
                     decryptSettings();
                 }
 
@@ -558,6 +565,49 @@ public abstract class MavenConfigurationSupport implements Action {
         }
     }
 
+    /**
+     * Asks for confirmation (user has to press <code>y</code>) after presenting a prompt
+     * @param prompt
+     * @return
+     */
+    protected boolean confirm(String prompt) throws IOException {
+        String response = session.readLine(prompt, null);
+        return "y".equals(response);
+    }
+
+    /**
+     * Returns new {@link File} that's part of fixed-size sequence. Keeps the sequence bounded.
+     * @param dataDir
+     * @param pattern
+     * @param fileNameFormat
+     * @return
+     */
+    protected File nextSequenceFile(File dataDir, Pattern pattern, String fileNameFormat) {
+        File[] files = dataDir.listFiles((dir, name) -> pattern.matcher(name).matches());
+        File result = null;
+        if (files != null && files.length > 0) {
+            List<String> names = new ArrayList<>(Arrays.stream(files).map(File::getName)
+                    .collect(TreeSet<String>::new, TreeSet::add, TreeSet::addAll));
+
+            names.add(String.format(fileNameFormat, new Date().getTime()));
+
+            while (names.size() > MAX_SEQUENCE_SIZE) {
+                String name = names.remove(0);
+                new File(dataDir, name).delete();
+            }
+            result = new File(dataDir, names.get(names.size() - 1));
+        }
+        if (result == null) {
+            result = new File(dataDir, String.format(fileNameFormat, new Date().getTime()));
+        }
+
+        return result;
+    }
+
+    protected boolean showPasswords() {
+        return false;
+    }
+
     protected static class SourceAnd<T> {
         String source;
         T value;

http://git-wip-us.apache.org/repos/asf/karaf/blob/ecc21a3c/maven/core/src/main/java/org/apache/karaf/maven/command/MavenSecuritySupport.java
----------------------------------------------------------------------
diff --git a/maven/core/src/main/java/org/apache/karaf/maven/command/MavenSecuritySupport.java b/maven/core/src/main/java/org/apache/karaf/maven/command/MavenSecuritySupport.java
new file mode 100644
index 0000000..6c46c9d
--- /dev/null
+++ b/maven/core/src/main/java/org/apache/karaf/maven/command/MavenSecuritySupport.java
@@ -0,0 +1,31 @@
+/*
+ * 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.
+ */
+package org.apache.karaf.maven.command;
+
+import org.apache.karaf.shell.api.action.Option;
+
+public abstract class MavenSecuritySupport extends MavenConfigurationSupport {
+
+    @Option(name = "-x", aliases = { "--show-passwords" }, description = "Do not hide passwords related to Maven encryption", required = false, multiValued = false)
+    boolean showPasswords;
+
+    @Override
+    protected boolean showPasswords() {
+        return showPasswords;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/ecc21a3c/maven/core/src/main/java/org/apache/karaf/maven/command/PasswordCommand.java
----------------------------------------------------------------------
diff --git a/maven/core/src/main/java/org/apache/karaf/maven/command/PasswordCommand.java b/maven/core/src/main/java/org/apache/karaf/maven/command/PasswordCommand.java
new file mode 100644
index 0000000..ed44b35
--- /dev/null
+++ b/maven/core/src/main/java/org/apache/karaf/maven/command/PasswordCommand.java
@@ -0,0 +1,103 @@
+/*
+ * 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.
+ */
+package org.apache.karaf.maven.command;
+
+import java.io.File;
+import java.io.FileWriter;
+import java.util.Dictionary;
+
+import org.apache.karaf.shell.api.action.Command;
+import org.apache.karaf.shell.api.action.Option;
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+import org.osgi.service.cm.Configuration;
+import org.sonatype.plexus.components.sec.dispatcher.DefaultSecDispatcher;
+import org.sonatype.plexus.components.sec.dispatcher.model.SettingsSecurity;
+import org.sonatype.plexus.components.sec.dispatcher.model.io.xpp3.SecurityConfigurationXpp3Writer;
+
+@Command(scope = "maven", name = "password", description = "Manage passwords for remote repositories and proxies")
+@Service
+public class PasswordCommand extends MavenConfigurationSupport {
+
+    @Option(name = "-ep", aliases = { "--encrypt-password" }, description = "Encrypts passwords to use for remote repositories and proxies, see \"mvn -ep\"", required = false, multiValued = false)
+    boolean ep;
+
+    @Option(name = "-emp", aliases = { "--encrypt-master-password" }, description = "Encrypts master password used to encrypt/decrypt other passwords, see \"mvn -emp\"", required = false, multiValued = false)
+    boolean emp;
+
+    @Option(name = "-p", aliases = { "--persist" }, description = "", required = false, multiValued = false)
+    boolean persist;
+
+    @Override
+    public void doAction(String prefix, Dictionary<String, Object> config) throws Exception {
+        if (ep && emp) {
+            System.err.println("Please specify only one of --encrypt-password and --encrypt-master-password");
+            return;
+        }
+
+        if (ep && persist) {
+            System.err.println("Ordinary passwords are not persisted - use the encrypted password in either <proxy> or <server>");
+            return;
+        }
+
+        if (ep) {
+            // encrypt password using master password
+            if (masterPassword == null) {
+                System.err.println("Master password is not available");
+                return;
+            }
+            String password = session.readLine("Password to encrypt: ", '*');
+            System.out.println("Encrypted password: " + cipher.encryptAndDecorate(password, masterPassword));
+            return;
+        }
+
+        if (emp) {
+            if (persist && !confirm("Maven security settings will be stored in new file. This file will be used in org.ops4j.pax.url.mvn.security property. Continue? (y/N) ")) {
+                return;
+            }
+
+            // encrypt master password using DefaultSecDispatcher.SYSTEM_PROPERTY_SEC_LOCATION
+            String password = session.readLine("Master password to encrypt: ", '*');
+            String encryptedPassword = cipher.encryptAndDecorate(password, DefaultSecDispatcher.SYSTEM_PROPERTY_SEC_LOCATION);
+            System.out.println("Encrypted master password: " + encryptedPassword);
+            if (persist) {
+                SettingsSecurity settingsSecurity = new SettingsSecurity();
+                settingsSecurity.setMaster(encryptedPassword);
+                File dataDir = context.getDataFile(".");
+                if (!dataDir.isDirectory()) {
+                    System.err.println("Can't access data directory for " + context.getBundle().getSymbolicName() + " bundle");
+                }
+                File newSecuritySettingsFile = nextSequenceFile(dataDir, RE_SECURITY_SETTINGS, PATTERN_SECURITY_SETTINGS);
+                try (FileWriter fw = new FileWriter(newSecuritySettingsFile)) {
+                    new SecurityConfigurationXpp3Writer().write(fw, settingsSecurity);
+                }
+
+                System.out.println("New security settings stored in \"" + newSecuritySettingsFile.getCanonicalPath() + "\"");
+
+                Configuration cmConfig = cm.getConfiguration(PID);
+                config.put(prefix + PROPERTY_SECURITY_FILE, newSecuritySettingsFile.getCanonicalPath());
+                cmConfig.update(config);
+            }
+            return;
+        }
+    }
+
+    @Override
+    protected boolean showPasswords() {
+        return true;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/ecc21a3c/maven/core/src/main/java/org/apache/karaf/maven/command/RepositoryEditCommandSupport.java
----------------------------------------------------------------------
diff --git a/maven/core/src/main/java/org/apache/karaf/maven/command/RepositoryEditCommandSupport.java b/maven/core/src/main/java/org/apache/karaf/maven/command/RepositoryEditCommandSupport.java
index 0179b02..12700d0 100644
--- a/maven/core/src/main/java/org/apache/karaf/maven/command/RepositoryEditCommandSupport.java
+++ b/maven/core/src/main/java/org/apache/karaf/maven/command/RepositoryEditCommandSupport.java
@@ -21,7 +21,7 @@ import java.util.Dictionary;
 import org.apache.karaf.maven.core.MavenRepositoryURL;
 import org.apache.karaf.shell.api.action.Option;
 
-public abstract class RepositoryEditCommandSupport extends MavenConfigurationSupport {
+public abstract class RepositoryEditCommandSupport extends MavenSecuritySupport {
 
     @Override
     public void doAction(String prefix, Dictionary<String, Object> config) throws Exception {

http://git-wip-us.apache.org/repos/asf/karaf/blob/ecc21a3c/maven/core/src/main/java/org/apache/karaf/maven/command/RepositoryListCommand.java
----------------------------------------------------------------------
diff --git a/maven/core/src/main/java/org/apache/karaf/maven/command/RepositoryListCommand.java b/maven/core/src/main/java/org/apache/karaf/maven/command/RepositoryListCommand.java
index 90c7c26..ddc2ea5 100644
--- a/maven/core/src/main/java/org/apache/karaf/maven/command/RepositoryListCommand.java
+++ b/maven/core/src/main/java/org/apache/karaf/maven/command/RepositoryListCommand.java
@@ -28,7 +28,7 @@ import org.apache.maven.settings.Server;
 
 @Command(scope = "maven", name = "repository-list", description = "Maven repository summary.")
 @Service
-public class RepositoryListCommand extends MavenConfigurationSupport {
+public class RepositoryListCommand extends MavenSecuritySupport {
 
     @Option(name = "-v", aliases = { "--verbose" }, description = "Show additional information (policies, source)", required = false, multiValued = false)
     boolean verbose;

http://git-wip-us.apache.org/repos/asf/karaf/blob/ecc21a3c/maven/core/src/main/java/org/apache/karaf/maven/command/SummaryCommand.java
----------------------------------------------------------------------
diff --git a/maven/core/src/main/java/org/apache/karaf/maven/command/SummaryCommand.java b/maven/core/src/main/java/org/apache/karaf/maven/command/SummaryCommand.java
index 1678239..3f7e91a 100644
--- a/maven/core/src/main/java/org/apache/karaf/maven/command/SummaryCommand.java
+++ b/maven/core/src/main/java/org/apache/karaf/maven/command/SummaryCommand.java
@@ -28,7 +28,7 @@ import org.apache.maven.settings.Proxy;
 
 @Command(scope = "maven", name = "summary", description = "Maven configuration summary.")
 @Service
-public class SummaryCommand extends MavenConfigurationSupport {
+public class SummaryCommand extends MavenSecuritySupport {
 
     @Option(name = "-p", aliases = { "--property-ids" }, description = "Use PID property identifiers instead of their names", required = false, multiValued = false)
     boolean propertyIds;

http://git-wip-us.apache.org/repos/asf/karaf/blob/ecc21a3c/maven/core/src/test/java/org/apache/karaf/maven/SettingsTest.java
----------------------------------------------------------------------
diff --git a/maven/core/src/test/java/org/apache/karaf/maven/SettingsTest.java b/maven/core/src/test/java/org/apache/karaf/maven/SettingsTest.java
index b0d9110..3ecaf30 100644
--- a/maven/core/src/test/java/org/apache/karaf/maven/SettingsTest.java
+++ b/maven/core/src/test/java/org/apache/karaf/maven/SettingsTest.java
@@ -53,9 +53,11 @@ public class SettingsTest {
         // non-master password ('mvn -ep admin')
         DefaultPlexusCipher plexusCipher = new DefaultPlexusCipher();
         System.out.println(plexusCipher.decrypt("{EhjazkVpkMoHjAgaUKX+UxeXn9lsJGHst2uFKmhNZ8U=}", "admin"));
+        System.out.println(plexusCipher.decrypt("{oWE12FbirwYHNit93TAMA+OC/GJge2r9FuzI8kOuHlA=}", "settings.security"));
 
         // master password (`mvn -emp admin`)
         PBECipher cipher = new PBECipher();
+        System.out.println(cipher.decrypt64("EhjazkVpkMoHjAgaUKX+UxeXn9lsJGHst2uFKmhNZ8U=","admin"));
         System.out.println(cipher.decrypt64("oWE12FbirwYHNit93TAMA+OC/GJge2r9FuzI8kOuHlA=","settings.security"));
     }
 

http://git-wip-us.apache.org/repos/asf/karaf/blob/ecc21a3c/maven/core/src/test/java/org/apache/karaf/maven/command/MavenConfigurationSupportTest.java
----------------------------------------------------------------------
diff --git a/maven/core/src/test/java/org/apache/karaf/maven/command/MavenConfigurationSupportTest.java b/maven/core/src/test/java/org/apache/karaf/maven/command/MavenConfigurationSupportTest.java
new file mode 100644
index 0000000..16ffc3f
--- /dev/null
+++ b/maven/core/src/test/java/org/apache/karaf/maven/command/MavenConfigurationSupportTest.java
@@ -0,0 +1,60 @@
+/*
+ * 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.
+ */
+package org.apache.karaf.maven.command;
+
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.util.Dictionary;
+import java.util.regex.Pattern;
+
+import org.junit.Test;
+import shaded.org.apache.commons.io.FileUtils;
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.MatcherAssert.assertThat;
+
+public class MavenConfigurationSupportTest {
+
+    @Test
+    public void sequenceFiles() throws IOException {
+        File dataDir = new File("target/data");
+        FileUtils.deleteDirectory(dataDir);
+        dataDir.mkdirs();
+
+        MavenConfigurationSupport support = new MavenConfigurationSupport() {
+            @Override
+            protected void doAction(String prefix, Dictionary<String, Object> config) throws Exception { }
+        };
+
+        File newFile = support.nextSequenceFile(dataDir, Pattern.compile("file-(\\d+).txt"), "file-%04d.txt");
+        assertThat(newFile.getName(), equalTo("file-0001.txt"));
+
+        try (FileWriter fw = new FileWriter(new File(dataDir, "file-abcd.txt"))) {
+            fw.write("~");
+        }
+        newFile = support.nextSequenceFile(dataDir, Pattern.compile("file-(\\d+).txt"), "file-%04d.txt");
+        assertThat(newFile.getName(), equalTo("file-0001.txt"));
+
+        try (FileWriter fw = new FileWriter(new File(dataDir, "file-0004.txt"))) {
+            fw.write("~");
+        }
+        newFile = support.nextSequenceFile(dataDir, Pattern.compile("file-(\\d+).txt"), "file-%04d.txt");
+        assertThat(newFile.getName(), equalTo("file-0005.txt"));
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/ecc21a3c/maven/core/src/test/resources/log4j.properties
----------------------------------------------------------------------
diff --git a/maven/core/src/test/resources/log4j.properties b/maven/core/src/test/resources/log4j.properties
new file mode 100644
index 0000000..e1cbdd1
--- /dev/null
+++ b/maven/core/src/test/resources/log4j.properties
@@ -0,0 +1,34 @@
+## ---------------------------------------------------------------------------
+## 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.
+## ---------------------------------------------------------------------------
+
+#
+# The logging properties used during tests..
+#
+log4j.rootLogger=DEBUG, console, file
+
+# Console will only display warnnings
+log4j.appender.console=org.apache.log4j.ConsoleAppender
+log4j.appender.console.layout=org.apache.log4j.PatternLayout
+log4j.appender.console.layout.ConversionPattern=%d{ISO8601} | %-5.5p | %-16.16t | %-32.32c{1} | %-32.32C %4L | %m%n
+#log4j.appender.console.threshold=WARN
+
+# File appender will contain all info messages
+log4j.appender.file=org.apache.log4j.FileAppender
+log4j.appender.file.layout=org.apache.log4j.PatternLayout
+log4j.appender.file.layout.ConversionPattern=%d | %-5p | %m | %c | %t%n
+log4j.appender.file.file=target/test.log
+log4j.appender.file.append=true