This is an automated email from the ASF dual-hosted git repository.

rmaucher pushed a commit to branch trunk
in repository https://gitbox.apache.org/repos/asf/tomcat-maven-plugin.git


The following commit(s) were added to refs/heads/trunk by this push:
     new 0fc959f  Fix issues from code review
0fc959f is described below

commit 0fc959fb635607b9a9751293dccb0459c069ff82
Author: remm <remm@meteor>
AuthorDate: Thu Jun 4 14:55:03 2026 +0200

    Fix issues from code review
---
 .../maven/common/deployer/TomcatManager.java       | 100 +++---
 .../common/deployer/TomcatManagerResponse.java     |  46 +--
 .../common/messages/DefaultMessagesProvider.java   |  36 +--
 .../maven/common/messages/MessagesProvider.java    |   4 +-
 .../run/ClassLoaderEntriesCalculatorResult.java    |   3 +-
 .../run/DefaultClassLoaderEntriesCalculator.java   |   1 +
 .../tomcat/maven/common/run/EmbeddedRegistry.java  |  32 +-
 .../maven/plugin/tomcat/AbstractCatalinaMojo.java  |  11 +-
 .../maven/plugin/tomcat/AbstractTomcatMojo.java    |   1 +
 .../plugin/tomcat/deploy/AbstractDeployMojo.java   |   2 +-
 .../tomcat/deploy/AbstractDeployWarMojo.java       |   2 +-
 .../maven/plugin/tomcat/deploy/RedeployMojo.java   |   3 +-
 .../plugin/tomcat/deploy/RedeployOnlyMojo.java     |   4 +-
 .../maven/plugin/tomcat/deploy/SessionsMojo.java   |   7 +-
 .../maven/plugin/tomcat/deploy/WaitMojo.java       |   6 +-
 .../plugin/tomcat/run/AbstractExecWarMojo.java     |  74 +++--
 .../maven/plugin/tomcat/run/AbstractRunMojo.java   | 355 ++++++++++-----------
 .../tomcat/run/AbstractStandaloneWarMojo.java      |  12 +-
 .../maven/plugin/tomcat/run/ExtendedTomcat.java    |   3 +
 .../tomcat/maven/plugin/tomcat/run/RunMojo.java    |  10 +-
 .../maven/plugin/tomcat/run/ShutdownMojo.java      |   2 +-
 .../tomcat/maven/plugin/tomcat/run/Webapp.java     |  47 +--
 .../apache/tomcat/maven/runner/PasswordUtil.java   |  35 +-
 .../apache/tomcat/maven/runner/TomcatRunner.java   |  25 +-
 .../tomcat/maven/runner/TomcatRunnerCli.java       |  55 +++-
 25 files changed, 447 insertions(+), 429 deletions(-)

diff --git 
a/src/main/java/org/apache/tomcat/maven/common/deployer/TomcatManager.java 
b/src/main/java/org/apache/tomcat/maven/common/deployer/TomcatManager.java
index 315bc17..61702c3 100644
--- a/src/main/java/org/apache/tomcat/maven/common/deployer/TomcatManager.java
+++ b/src/main/java/org/apache/tomcat/maven/common/deployer/TomcatManager.java
@@ -37,6 +37,7 @@ import java.util.Locale;
 
 import org.apache.commons.codec.binary.Base64;
 import org.apache.commons.io.IOUtils;
+import org.apache.maven.plugin.logging.Log;
 import org.apache.maven.settings.Proxy;
 import org.apache.maven.wagon.proxy.ProxyInfo;
 import org.apache.maven.wagon.proxy.ProxyUtils;
@@ -47,19 +48,13 @@ import org.apache.maven.wagon.proxy.ProxyUtils;
  * @author Mark Hobson ([email protected])
  */
 public class TomcatManager {
+
     // ----------------------------------------------------------------------
     // Constants
     // ----------------------------------------------------------------------
 
     private static final int BUFFER_SIZE = 2048;
 
-    private static final int SC_OK = 200;
-    private static final int SC_CREATED = 201;
-    private static final int SC_ACCEPTED = 202;
-    private static final int SC_MOVED_PERMANENTLY = 301;
-    private static final int SC_MOVED_TEMPORARILY = 302;
-    private static final int SC_SEE_OTHER = 303;
-
     // ----------------------------------------------------------------------
     // Fields
     // ----------------------------------------------------------------------
@@ -67,7 +62,7 @@ public class TomcatManager {
     /**
      * The full URL of the Tomcat manager instance to use.
      */
-    private URL url;
+    private final URL url;
 
     /**
      * The username to use when authenticating with Tomcat manager.
@@ -101,6 +96,13 @@ public class TomcatManager {
 
     private Proxy proxySettings;
 
+    /**
+     * The Maven log instance for output.
+     *
+     * @since 2.2
+     */
+    private Log log;
+
     // ----------------------------------------------------------------------
     // Constructors
     // ----------------------------------------------------------------------
@@ -183,6 +185,16 @@ public class TomcatManager {
         return url;
     }
 
+    /**
+     * Sets the Maven log instance for output.
+     *
+     * @param log the Maven log instance
+     * @since 2.2
+     */
+    public void setLog(Log log) {
+        this.log = log;
+    }
+
     /**
      * Gets the username to use when authenticating with Tomcat manager.
      *
@@ -717,14 +729,13 @@ public class TomcatManager {
                     long remaining = length;
                     while (remaining > 0) {
                         int transferSize = (int) Math.min(BUFFER_SIZE, 
remaining);
-                        completed += transferSize;
-                        int l = stream.read(buffer, 0, transferSize);
-                        if (l == -1) {
+                        int nRead = stream.read(buffer, 0, transferSize);
+                        if (nRead < 0) {
                             break;
                         }
-
-                        os.write(buffer, 0, l);
-                        remaining -= l;
+                        completed += nRead;
+                        os.write(buffer, 0, nRead);
+                        remaining -= nRead;
                         transferProgressed(completed, length);
                     }
                 }
@@ -735,36 +746,18 @@ public class TomcatManager {
         }
 
         int statusCode = connection.getResponseCode();
-
-        String relocateUrl = null;
-        switch (statusCode) {
-            // Success Codes
-            case SC_OK: // 200
-            case SC_CREATED: // 201
-            case SC_ACCEPTED: // 202
-                break;
-            // handle all redirect even if http specs says " the user agent 
MUST NOT automatically redirect the request
-            // unless it can be confirmed by the user"
-            case SC_MOVED_PERMANENTLY: // 301
-            case SC_MOVED_TEMPORARILY: // 302
-            case SC_SEE_OTHER: // 303
-                relocateUrl = calculateRelocatedUrl(connection);
-                try {
-                    this.url = new URI(relocateUrl).toURL();
-                } catch (URISyntaxException e) {
-                    throw new MalformedURLException(e.getMessage());
-                }
-                return invoke(path, data, length);
-        }
-
-        String responseBody;
-        try (InputStream is = connection.getInputStream() != null ? 
connection.getInputStream()
-                : connection.getErrorStream()) {
-            responseBody = IOUtils.toString(is, StandardCharsets.UTF_8);
+        try {
+            InputStream is;
+            try {
+                is = connection.getInputStream();
+            } catch (IOException e) {
+                is = connection.getErrorStream();
+            }
+            return new TomcatManagerResponse(statusCode, 
connection.getResponseMessage(),
+                    is != null ? IOUtils.toString(is, StandardCharsets.UTF_8) 
: "");
+        } finally {
+            connection.disconnect();
         }
-
-        return new 
TomcatManagerResponse().setStatusCode(statusCode).setReasonPhrase(connection.getResponseMessage())
-                .setHttpResponseBody(responseBody);
     }
 
     /**
@@ -835,30 +828,25 @@ public class TomcatManager {
         if (password != null) {
             buffer.append(password);
         }
-        return "Basic " + new 
String(Base64.encodeBase64(buffer.toString().getBytes()));
+        return "Basic " + new 
String(Base64.encodeBase64(buffer.toString().getBytes(StandardCharsets.UTF_8), 
false));
     }
 
     private void transferInitiated(String targetUrl) {
-        String message = "Uploading";
-
-        System.out.println(message + ": " + targetUrl);
+        if (log != null) {
+            log.info("Uploading: " + targetUrl);
+        }
     }
 
     private void transferProgressed(long completedSize, long totalSize) {
-        if (!verbose) {
+        if (!verbose || log == null) {
             return;
         }
 
-        StringBuilder buffer = new StringBuilder(64);
-
-        buffer.append(getStatus(completedSize, totalSize)).append("  ");
-        buffer.append('\r');
-
-        System.out.print(buffer);
+        log.info(getStatus(completedSize, totalSize));
     }
 
     private void transferSucceeded(long contentLength, long startTime) {
-        if (contentLength >= 0) {
+        if (contentLength >= 0 && log != null) {
             String type = "Uploaded";
             String len = contentLength >= 1024 ? toKB(contentLength) + " KB" : 
contentLength + " B";
 
@@ -870,7 +858,7 @@ public class TomcatManager {
                 throughput = " at " + format.format(kbPerSec) + " KB/sec";
             }
 
-            System.out.println(type + ": " + url + " (" + len + throughput + 
")");
+            log.info(type + ": " + url + " (" + len + throughput + ")");
         }
     }
 
diff --git 
a/src/main/java/org/apache/tomcat/maven/common/deployer/TomcatManagerResponse.java
 
b/src/main/java/org/apache/tomcat/maven/common/deployer/TomcatManagerResponse.java
index 14c7e67..314d1b3 100644
--- 
a/src/main/java/org/apache/tomcat/maven/common/deployer/TomcatManagerResponse.java
+++ 
b/src/main/java/org/apache/tomcat/maven/common/deployer/TomcatManagerResponse.java
@@ -25,17 +25,24 @@ package org.apache.tomcat.maven.common.deployer;
  * @since 2.0
  */
 public class TomcatManagerResponse {
-    private int statusCode;
 
-    private String reasonPhrase;
+    private final int statusCode;
 
-    private String httpResponseBody;
+    private final String reasonPhrase;
+
+    private final String httpResponseBody;
 
     /**
      * Creates an instance of TomcatManagerResponse.
+     *
+     * @param statusCode the HTTP status code
+     * @param reasonPhrase the HTTP reason phrase
+     * @param httpResponseBody the HTTP response body
      */
-    public TomcatManagerResponse() {
-        // no op
+    public TomcatManagerResponse(int statusCode, String reasonPhrase, String 
httpResponseBody) {
+        this.statusCode = statusCode;
+        this.reasonPhrase = reasonPhrase;
+        this.httpResponseBody = httpResponseBody;
     }
 
     /**
@@ -46,16 +53,6 @@ public class TomcatManagerResponse {
         return statusCode;
     }
 
-    /**
-     * Sets the HTTP status code.
-     * @param statusCode the status code
-     * @return this response for chaining
-     */
-    public TomcatManagerResponse setStatusCode(int statusCode) {
-        this.statusCode = statusCode;
-        return this;
-    }
-
     /**
      * Returns the HTTP reason phrase.
      * @return the reason phrase
@@ -64,16 +61,6 @@ public class TomcatManagerResponse {
         return reasonPhrase;
     }
 
-    /**
-     * Sets the HTTP reason phrase.
-     * @param reasonPhrase the reason phrase
-     * @return this response for chaining
-     */
-    public TomcatManagerResponse setReasonPhrase(String reasonPhrase) {
-        this.reasonPhrase = reasonPhrase;
-        return this;
-    }
-
     /**
      * Returns the HTTP response body.
      * @return the response body
@@ -82,13 +69,4 @@ public class TomcatManagerResponse {
         return httpResponseBody;
     }
 
-    /**
-     * Sets the HTTP response body.
-     * @param httpResponseBody the response body
-     * @return this response for chaining
-     */
-    public TomcatManagerResponse setHttpResponseBody(String httpResponseBody) {
-        this.httpResponseBody = httpResponseBody;
-        return this;
-    }
 }
diff --git 
a/src/main/java/org/apache/tomcat/maven/common/messages/DefaultMessagesProvider.java
 
b/src/main/java/org/apache/tomcat/maven/common/messages/DefaultMessagesProvider.java
index 7f32866..104f264 100644
--- 
a/src/main/java/org/apache/tomcat/maven/common/messages/DefaultMessagesProvider.java
+++ 
b/src/main/java/org/apache/tomcat/maven/common/messages/DefaultMessagesProvider.java
@@ -34,7 +34,7 @@ import java.util.ResourceBundle;
 public class DefaultMessagesProvider implements MessagesProvider {
 
     /**
-     * plugin messages
+     * Plugin messages
      */
     private final ResourceBundle messages;
 
@@ -43,9 +43,11 @@ public class DefaultMessagesProvider implements 
MessagesProvider {
      * Creates a new instance and loads the message bundle.
      */
     public DefaultMessagesProvider() {
-        String packageName = getClass().getPackage().getName();
-
-        messages = ResourceBundle.getBundle(packageName + ".messages");
+        try {
+            messages = 
ResourceBundle.getBundle(getClass().getPackage().getName() + ".messages");
+        } catch (MissingResourceException e) {
+            throw new IllegalStateException("Required message bundle 
'messages' not found on classpath", e);
+        }
     }
 
     /**
@@ -56,13 +58,6 @@ public class DefaultMessagesProvider implements 
MessagesProvider {
         return this.messages;
     }
 
-    /**
-     * Gets the message for the given key from this packages resource bundle.
-     *
-     * @param key the key for the required message
-     * 
-     * @return the message
-     */
     @Override
     public String getMessage(String key) {
         try {
@@ -72,17 +67,16 @@ public class DefaultMessagesProvider implements 
MessagesProvider {
         }
     }
 
-    /**
-     * Gets the message for the given key from this packages resource bundle 
and formats it with the given parameter.
-     *
-     * @param key    the key for the required message
-     * @param params the parameters to be used to format the message with
-     * 
-     * @return the formatted message
-     */
     @Override
     public String getMessage(String key, Object... params) {
-        return MessageFormat.format(getMessage(key), params);
+        String template = getMessage(key);
+        if (params == null || params.length == 0) {
+            return template;
+        }
+        try {
+            return MessageFormat.format(template, params);
+        } catch (IllegalArgumentException e) {
+            return template + " [formatting error: " + e.getMessage() + "]";
+        }
     }
-
 }
diff --git 
a/src/main/java/org/apache/tomcat/maven/common/messages/MessagesProvider.java 
b/src/main/java/org/apache/tomcat/maven/common/messages/MessagesProvider.java
index 111ed2d..6af72b7 100644
--- 
a/src/main/java/org/apache/tomcat/maven/common/messages/MessagesProvider.java
+++ 
b/src/main/java/org/apache/tomcat/maven/common/messages/MessagesProvider.java
@@ -36,9 +36,9 @@ public interface MessagesProvider {
     /**
      * Returns the formatted message for the given key with the specified 
parameters.
      * @param key the message key
-     * @param param1 the formatting parameters
+     * @param params the formatting parameters
      * @return the formatted message string
      */
-    String getMessage(String key, Object... param1);
+    String getMessage(String key, Object... params);
 
 }
diff --git 
a/src/main/java/org/apache/tomcat/maven/common/run/ClassLoaderEntriesCalculatorResult.java
 
b/src/main/java/org/apache/tomcat/maven/common/run/ClassLoaderEntriesCalculatorResult.java
index 0c9ea2d..5b7ca7d 100644
--- 
a/src/main/java/org/apache/tomcat/maven/common/run/ClassLoaderEntriesCalculatorResult.java
+++ 
b/src/main/java/org/apache/tomcat/maven/common/run/ClassLoaderEntriesCalculatorResult.java
@@ -19,6 +19,7 @@
 package org.apache.tomcat.maven.common.run;
 
 import java.io.File;
+import java.util.Collections;
 import java.util.List;
 
 /**
@@ -54,7 +55,7 @@ public class ClassLoaderEntriesCalculatorResult {
             List<String> buildDirectories) {
         this.classPathEntries = classPathEntries;
         this.tmpDirectories = tmpDirectories;
-        this.buildDirectories = buildDirectories;
+        this.buildDirectories = Collections.unmodifiableList(buildDirectories);
     }
 
     /**
diff --git 
a/src/main/java/org/apache/tomcat/maven/common/run/DefaultClassLoaderEntriesCalculator.java
 
b/src/main/java/org/apache/tomcat/maven/common/run/DefaultClassLoaderEntriesCalculator.java
index 494b1b3..5b8f974 100644
--- 
a/src/main/java/org/apache/tomcat/maven/common/run/DefaultClassLoaderEntriesCalculator.java
+++ 
b/src/main/java/org/apache/tomcat/maven/common/run/DefaultClassLoaderEntriesCalculator.java
@@ -149,6 +149,7 @@ public class DefaultClassLoaderEntriesCalculator implements 
ClassLoaderEntriesCa
                         }
                     }
 
+                    // All directories must be added, this is not for cleanup
                     tmpDirectories.add(tmpDir);
 
                     try {
diff --git 
a/src/main/java/org/apache/tomcat/maven/common/run/EmbeddedRegistry.java 
b/src/main/java/org/apache/tomcat/maven/common/run/EmbeddedRegistry.java
index 78902e7..eb42212 100644
--- a/src/main/java/org/apache/tomcat/maven/common/run/EmbeddedRegistry.java
+++ b/src/main/java/org/apache/tomcat/maven/common/run/EmbeddedRegistry.java
@@ -22,9 +22,9 @@ import org.apache.maven.plugin.logging.Log;
 
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
-import java.util.HashSet;
 import java.util.Iterator;
 import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
 
 /**
  * Registry which collects all embedded Tomcat Servers so that they will be 
shutdown through a shutdown hook when the
@@ -35,15 +35,24 @@ import java.util.Set;
  * @since 1.1
  */
 public final class EmbeddedRegistry {
-    private static EmbeddedRegistry instance;
 
-    private final Set<Object> containers = new HashSet<>(1);
+    private static class Holder {
+        static final EmbeddedRegistry INSTANCE = new EmbeddedRegistry();
+    }
+
+    private final Set<Object> containers = ConcurrentHashMap.newKeySet(1);
 
     /**
      * Don't instantiate - use the instance through {@link #getInstance()}.
      */
     private EmbeddedRegistry() {
-        // no op
+        Runtime.getRuntime().addShutdownHook(new Thread(() -> {
+            try {
+                getInstance().shutdownAll(null);
+            } catch (Exception e) {
+                // ignore, the exception should already have been reported
+            }
+        }));
     }
 
     /**
@@ -52,17 +61,7 @@ public final class EmbeddedRegistry {
      * @return singleton instance of the registry
      */
     public static EmbeddedRegistry getInstance() {
-        if (instance == null) {
-            instance = new EmbeddedRegistry();
-            Runtime.getRuntime().addShutdownHook(new Thread(() -> {
-                try {
-                    getInstance().shutdownAll(null);
-                } catch (Exception e) {
-                    // ignore, the exception should already have been reported
-                }
-            }));
-        }
-        return instance;
+        return Holder.INSTANCE;
     }
 
     /**
@@ -108,11 +107,10 @@ public final class EmbeddedRegistry {
                     error(log, e, "Error while shutting down embedded 
Tomcat.");
                 }
             } catch (InvocationTargetException e) {
-
                 if (firstException == null) {
                     firstException = e;
                     error(log, e,
-                            "IllegalAccessException for stop/destroy method in 
class " + embedded.getClass().getName());
+                            "InvocationTargetException for stop/destroy method 
in class " + embedded.getClass().getName());
                 } else {
                     error(log, e, "Error while shutting down embedded 
Tomcat.");
                 }
diff --git 
a/src/main/java/org/apache/tomcat/maven/plugin/tomcat/AbstractCatalinaMojo.java 
b/src/main/java/org/apache/tomcat/maven/plugin/tomcat/AbstractCatalinaMojo.java
index 134fb6e..fcb4800 100644
--- 
a/src/main/java/org/apache/tomcat/maven/plugin/tomcat/AbstractCatalinaMojo.java
+++ 
b/src/main/java/org/apache/tomcat/maven/plugin/tomcat/AbstractCatalinaMojo.java
@@ -111,7 +111,7 @@ public abstract class AbstractCatalinaMojo extends 
AbstractTomcatMojo {
     /**
      * The Tomcat manager wrapper object.
      */
-    private TomcatManager manager;
+    private volatile TomcatManager manager;
 
     // ----------------------------------------------------------------------
     // Mojo Implementation
@@ -155,6 +155,14 @@ public abstract class AbstractCatalinaMojo extends 
AbstractTomcatMojo {
      *                                                            details
      */
     protected TomcatManager getManager() throws MojoExecutionException {
+        TomcatManager manager = this.manager;
+        if (manager == null) {
+            manager = getManagerInternal();
+        }
+        return manager;
+    }
+
+    protected synchronized TomcatManager getManagerInternal() throws 
MojoExecutionException {
         // lazily instantiate when config values have been injected
         if (manager == null) {
             String userName;
@@ -195,6 +203,7 @@ public abstract class AbstractCatalinaMojo extends 
AbstractTomcatMojo {
             }
 
             manager = new TomcatManager(url, userName, password, charset, 
settings.isInteractiveMode());
+            manager.setLog(getLog());
             manager.setUserAgent(name + "/" + version);
         }
 
diff --git 
a/src/main/java/org/apache/tomcat/maven/plugin/tomcat/AbstractTomcatMojo.java 
b/src/main/java/org/apache/tomcat/maven/plugin/tomcat/AbstractTomcatMojo.java
index 8a56f7e..252d7c6 100644
--- 
a/src/main/java/org/apache/tomcat/maven/plugin/tomcat/AbstractTomcatMojo.java
+++ 
b/src/main/java/org/apache/tomcat/maven/plugin/tomcat/AbstractTomcatMojo.java
@@ -88,6 +88,7 @@ public abstract class AbstractTomcatMojo extends AbstractMojo 
{
                     messagesProvider.getMessage("tomcatHttpStatusError", 
statusCode, tomcatResponse.getReasonPhrase()) +
                             ": " + tomcatResponse.getHttpResponseBody());
         } else if (!tomcatResponse.getHttpResponseBody().startsWith("OK -")) {
+            // Tomcat Manager and Host Manager will always use "OK -" and 
"FAIL -" prefixes for their text endpoints
             getLog().error(messagesProvider.getMessage("tomcatHttpBodyError", 
tomcatResponse.getHttpResponseBody()));
             throw new MojoExecutionException(
                     messagesProvider.getMessage("tomcatHttpBodyError", 
tomcatResponse.getHttpResponseBody()));
diff --git 
a/src/main/java/org/apache/tomcat/maven/plugin/tomcat/deploy/AbstractDeployMojo.java
 
b/src/main/java/org/apache/tomcat/maven/plugin/tomcat/deploy/AbstractDeployMojo.java
index d70972f..9ed3522 100644
--- 
a/src/main/java/org/apache/tomcat/maven/plugin/tomcat/deploy/AbstractDeployMojo.java
+++ 
b/src/main/java/org/apache/tomcat/maven/plugin/tomcat/deploy/AbstractDeployMojo.java
@@ -77,7 +77,7 @@ public abstract class AbstractDeployMojo extends 
AbstractWarCatalinaMojo {
      * {@inheritDoc}
      */
     @Override
-    public void invokeManager() throws MojoExecutionException, 
TomcatManagerException, IOException {
+    protected void invokeManager() throws MojoExecutionException, 
TomcatManagerException, IOException {
         if ("war".equals(mode)) {
             deployWar();
         } else if ("context".equals(mode)) {
diff --git 
a/src/main/java/org/apache/tomcat/maven/plugin/tomcat/deploy/AbstractDeployWarMojo.java
 
b/src/main/java/org/apache/tomcat/maven/plugin/tomcat/deploy/AbstractDeployWarMojo.java
index 61c00b2..92c8c42 100644
--- 
a/src/main/java/org/apache/tomcat/maven/plugin/tomcat/deploy/AbstractDeployWarMojo.java
+++ 
b/src/main/java/org/apache/tomcat/maven/plugin/tomcat/deploy/AbstractDeployWarMojo.java
@@ -66,7 +66,7 @@ public class AbstractDeployWarMojo extends AbstractDeployMojo 
{
      */
     @Override
     protected void validateWarFile() throws MojoExecutionException {
-        if (!warFile.exists() || !warFile.isFile()) {
+        if (!warFile.exists() || !warFile.isFile() || !warFile.canRead()) {
             throw new 
MojoExecutionException(messagesProvider.getMessage("DeployMojo.missingWar", 
warFile.getPath()));
         }
     }
diff --git 
a/src/main/java/org/apache/tomcat/maven/plugin/tomcat/deploy/RedeployMojo.java 
b/src/main/java/org/apache/tomcat/maven/plugin/tomcat/deploy/RedeployMojo.java
index 7207a71..0e6dc6a 100644
--- 
a/src/main/java/org/apache/tomcat/maven/plugin/tomcat/deploy/RedeployMojo.java
+++ 
b/src/main/java/org/apache/tomcat/maven/plugin/tomcat/deploy/RedeployMojo.java
@@ -23,7 +23,8 @@ import org.apache.maven.plugins.annotations.LifecyclePhase;
 import org.apache.maven.plugins.annotations.Mojo;
 
 /**
- * Redeploy a WAR in Tomcat. (Alias for the deploy goal with its update 
parameter set to true.)
+ * Redeploy a WAR in Tomcat. Alias for the deploy goal with its update 
parameter set to true, so
+ * this goal always undeploys any existing web application.
  *
  * @author Olivier Lamy
  *
diff --git 
a/src/main/java/org/apache/tomcat/maven/plugin/tomcat/deploy/RedeployOnlyMojo.java
 
b/src/main/java/org/apache/tomcat/maven/plugin/tomcat/deploy/RedeployOnlyMojo.java
index 9376767..177cd62 100644
--- 
a/src/main/java/org/apache/tomcat/maven/plugin/tomcat/deploy/RedeployOnlyMojo.java
+++ 
b/src/main/java/org/apache/tomcat/maven/plugin/tomcat/deploy/RedeployOnlyMojo.java
@@ -21,8 +21,8 @@ package org.apache.tomcat.maven.plugin.tomcat.deploy;
 import org.apache.maven.plugins.annotations.Mojo;
 
 /**
- * Redeploy a WAR in Tomcat without forking the package lifecycle. (Alias for 
the deploy-only goal with its update
- * parameter set to true.)
+ * Redeploy a WAR in Tomcat without forking the package lifecycle. Alias for 
the deploy-only
+ * goal with its update parameter set to true, so this goal always undeploys 
any existing web application.
  *
  * @since 2.1
  */
diff --git 
a/src/main/java/org/apache/tomcat/maven/plugin/tomcat/deploy/SessionsMojo.java 
b/src/main/java/org/apache/tomcat/maven/plugin/tomcat/deploy/SessionsMojo.java
index 576cc05..537018a 100644
--- 
a/src/main/java/org/apache/tomcat/maven/plugin/tomcat/deploy/SessionsMojo.java
+++ 
b/src/main/java/org/apache/tomcat/maven/plugin/tomcat/deploy/SessionsMojo.java
@@ -26,7 +26,8 @@ import 
org.apache.tomcat.maven.plugin.tomcat.AbstractCatalinaMojo;
 import java.io.IOException;
 
 /**
- * List session information for a web application.
+ * List session information for a web application. Session information
+ * can be sensitive material, so exercise caution when using this goal.
  *
  * @since 3.0
  */
@@ -38,13 +39,11 @@ public class SessionsMojo extends AbstractCatalinaMojo {
     public SessionsMojo() {
         // default constructor
     }
+
     // ----------------------------------------------------------------------
     // Protected Methods
     // ----------------------------------------------------------------------
 
-    /**
-     * {@inheritDoc}
-     */
     @Override
     protected void invokeManager() throws MojoExecutionException, 
TomcatManagerException, IOException {
         getLog().info(messagesProvider.getMessage("SessionsMojo.listSessions", 
getURL()));
diff --git 
a/src/main/java/org/apache/tomcat/maven/plugin/tomcat/deploy/WaitMojo.java 
b/src/main/java/org/apache/tomcat/maven/plugin/tomcat/deploy/WaitMojo.java
index aef0454..197633e 100644
--- a/src/main/java/org/apache/tomcat/maven/plugin/tomcat/deploy/WaitMojo.java
+++ b/src/main/java/org/apache/tomcat/maven/plugin/tomcat/deploy/WaitMojo.java
@@ -56,7 +56,7 @@ public class WaitMojo extends AbstractCatalinaMojo {
      * The interval between checks, in milliseconds.
      */
     @Parameter(property = "maven.tomcat.wait.interval", defaultValue = "1000")
-    private long interval = 1000;
+    private int interval = 1000;
 
     /**
      * The HTTP status code to wait for.
@@ -113,8 +113,8 @@ public class WaitMojo extends AbstractCatalinaMojo {
      */
     private boolean isServerResponsive(URL url) throws IOException {
         HttpURLConnection connection = (HttpURLConnection) 
url.openConnection();
-        connection.setConnectTimeout((int) interval);
-        connection.setReadTimeout((int) interval);
+        connection.setConnectTimeout(interval);
+        connection.setReadTimeout(interval);
         connection.setRequestMethod("HEAD");
 
         try {
diff --git 
a/src/main/java/org/apache/tomcat/maven/plugin/tomcat/run/AbstractExecWarMojo.java
 
b/src/main/java/org/apache/tomcat/maven/plugin/tomcat/run/AbstractExecWarMojo.java
index 2c7cd8d..adbf048 100644
--- 
a/src/main/java/org/apache/tomcat/maven/plugin/tomcat/run/AbstractExecWarMojo.java
+++ 
b/src/main/java/org/apache/tomcat/maven/plugin/tomcat/run/AbstractExecWarMojo.java
@@ -22,6 +22,7 @@ import java.io.File;
 import java.io.FileInputStream;
 import java.io.FileOutputStream;
 import java.io.IOException;
+import java.io.InputStream;
 import java.io.OutputStream;
 import java.io.PrintWriter;
 import java.nio.file.Files;
@@ -292,10 +293,10 @@ public abstract class AbstractExecWarMojo extends 
AbstractTomcatMojo {
             // * file tomcat.standalone.properties with possible values :
             // * useServerXml=true/false to use directly the one provided
             // * enableNaming=true/false
-            // * wars=foo.war|contextpath;bar.war ( |contextpath is optionnal 
if empty use the war name )
+            // * wars=foo.war|contextpath;bar.war ( |contextpath is optional 
if empty use the war name )
             // * accessLogValveFormat=
             // * connectorhttpProtocol: HTTP/1.1 or 
org.apache.coyote.http11.Http11NioProtocol
-            // * optionnal: conf/ with usual tomcat configuration files
+            // * optional: conf/ with usual tomcat configuration files
             // * MANIFEST with Main-Class
 
             Properties properties = new Properties();
@@ -313,12 +314,17 @@ public abstract class AbstractExecWarMojo extends 
AbstractTomcatMojo {
 
             if ("war".equals(project.getPackaging())) {
 
-                String pathWithoutSlash = path.startsWith("/") ? 
path.substring(1) : path;
-                os.putArchiveEntry(new JarArchiveEntry(pathWithoutSlash + 
".war"));
-                IOUtils.copy(new FileInputStream(projectArtifact.getFile()), 
os);
-                os.closeArchiveEntry();
+                if (projectArtifact.getFile() != null) {
+                    String pathWithoutSlash = path.startsWith("/") ? 
path.substring(1) : path;
+                    os.putArchiveEntry(new JarArchiveEntry(pathWithoutSlash + 
".war"));
+                    IOUtils.copy(new 
FileInputStream(projectArtifact.getFile()), os);
+                    os.closeArchiveEntry();
+
+                    properties.put(TomcatRunner.WARS_KEY, pathWithoutSlash + 
".war|" + path);
+                } else {
+                    throw new MojoExecutionException("No project artifact 
found");
+                }
 
-                properties.put(TomcatRunner.WARS_KEY, pathWithoutSlash + 
".war|" + path);
             } else if (warRunDependencies != null && 
!warRunDependencies.isEmpty()) {
                 for (WarRunDependency warRunDependency : warRunDependencies) {
                     if (warRunDependency.dependency != null) {
@@ -335,6 +341,10 @@ public abstract class AbstractExecWarMojo extends 
AbstractTomcatMojo {
                         Artifact artifact = 
toMavenArtifact(dependency.getGroupId(), dependency.getArtifactId(),
                                 version, dependency.getType(), 
dependency.getClassifier());
 
+                        if (artifact.getFile() == null) {
+                            throw new MojoExecutionException("Dependency '" + 
dependency.getGroupId() + "':'" +
+                                    dependency.getArtifactId() + "' not 
found");
+                        }
                         File warFileToBundle = new 
File(resolvePluginWorkDir(), artifact.getFile().getName());
                         FileUtils.copyFile(artifact.getFile(), 
warFileToBundle);
 
@@ -603,7 +613,7 @@ public abstract class AbstractExecWarMojo extends 
AbstractTomcatMojo {
     }
 
     /**
-     * Copy the contents of a jar file to another archive
+     * Copy the contents of a jar file to another archive, then close it.
      *
      * @param file The input jar file
      * @param os   The output archive
@@ -612,30 +622,42 @@ public abstract class AbstractExecWarMojo extends 
AbstractTomcatMojo {
      */
     protected void extractJarToArchive(JarFile file, 
ArchiveOutputStream<JarArchiveEntry> os, String[] excludes)
             throws IOException {
-        Enumeration<? extends JarEntry> entries = file.entries();
-        while (entries.hasMoreElements()) {
-            JarEntry j = entries.nextElement();
-
-            if (excludes != null) {
-                for (String exclude : excludes) {
-                    if (SelectorUtils.match(exclude, j.getName())) {
+        try {
+            Enumeration<? extends JarEntry> entries = file.entries();
+            while (entries.hasMoreElements()) {
+                JarEntry j = entries.nextElement();
+
+                if (excludes != null) {
+                    boolean excluded = false;
+                    for (String exclude : excludes) {
+                        if (SelectorUtils.match(exclude, j.getName())) {
+                            excluded = true;
+                            break;
+                        }
+                    }
+                    if (excluded) {
                         continue;
                     }
                 }
-            }
 
-            if ("META-INF/MANIFEST.MF".equalsIgnoreCase(j.getName())) {
-                continue;
-            }
-            if (j.getName().startsWith("META-INF/") &&
-                    (j.getName().endsWith(".SF") || 
j.getName().endsWith(".DSA") || j.getName().endsWith(".RSA"))) {
-                continue;
+                if ("META-INF/MANIFEST.MF".equalsIgnoreCase(j.getName())) {
+                    continue;
+                }
+                if (j.getName().startsWith("META-INF/") &&
+                        (j.getName().endsWith(".SF") || 
j.getName().endsWith(".DSA") || j.getName().endsWith(".RSA"))) {
+                    continue;
+                }
+                os.putArchiveEntry(new JarArchiveEntry(j.getName()));
+                if (!j.isDirectory()) {
+                    try (InputStream is = file.getInputStream(j)) {
+                        IOUtils.copy(is, os);
+                    }
+                }
+                os.closeArchiveEntry();
             }
-            os.putArchiveEntry(new JarArchiveEntry(j.getName()));
-            IOUtils.copy(file.getInputStream(j), os);
-            os.closeArchiveEntry();
+        } finally {
+            file.close();
         }
-        file.close();
     }
 
     private Artifact toMavenArtifact(String groupId, String artifactId, String 
version, String type, String classifier)
diff --git 
a/src/main/java/org/apache/tomcat/maven/plugin/tomcat/run/AbstractRunMojo.java 
b/src/main/java/org/apache/tomcat/maven/plugin/tomcat/run/AbstractRunMojo.java
index f9ccbf6..d584108 100644
--- 
a/src/main/java/org/apache/tomcat/maven/plugin/tomcat/run/AbstractRunMojo.java
+++ 
b/src/main/java/org/apache/tomcat/maven/plugin/tomcat/run/AbstractRunMojo.java
@@ -732,9 +732,9 @@ public abstract class AbstractRunMojo extends 
AbstractTomcatMojo {
      * @throws MojoExecutionException if parsing fails
      */
     protected StandardContext parseContextFile(File file) throws 
MojoExecutionException {
-        try {
+        try (FileInputStream fis = new FileInputStream(file)) {
             StandardContext standardContext = new StandardContext();
-            XMLStreamReader reader = 
XMLInputFactory.newFactory().createXMLStreamReader(new FileInputStream(file));
+            XMLStreamReader reader = 
XMLInputFactory.newFactory().createXMLStreamReader(fis);
 
             int tag = reader.next();
 
@@ -757,7 +757,7 @@ public abstract class AbstractRunMojo extends 
AbstractTomcatMojo {
             }
 
             return standardContext;
-        } catch (XMLStreamException | FileNotFoundException e) {
+        } catch (XMLStreamException | IOException e) {
             throw new MojoExecutionException(e.getMessage(), e);
         }
     }
@@ -775,11 +775,6 @@ public abstract class AbstractRunMojo extends 
AbstractTomcatMojo {
         return new WebappLoader();
     }
 
-    /**
-     * Determine whether the passed context.xml file declares the context as 
reloadable or not.
-     *
-     * @return false by default, true if reloadable="true" in context.xml.
-     */
     /**
      * Determine whether the passed context.xml file declares the context as 
reloadable or not.
      *
@@ -795,6 +790,9 @@ public abstract class AbstractRunMojo extends 
AbstractTomcatMojo {
         try {
             if (contextFile != null && contextFile.exists()) {
                 DocumentBuilderFactory builderFactory = 
DocumentBuilderFactory.newInstance();
+                
builderFactory.setFeature(javax.xml.XMLConstants.FEATURE_SECURE_PROCESSING, 
true);
+                
builderFactory.setFeature("http://apache.org/xml/features/disallow-doctype-decl";,
 true);
+                builderFactory.setExpandEntityReferences(false);
                 DocumentBuilder builder = builderFactory.newDocumentBuilder();
                 Document contextDoc = builder.parse(contextFile);
                 contextDoc.getDocumentElement().normalize();
@@ -816,11 +814,6 @@ public abstract class AbstractRunMojo extends 
AbstractTomcatMojo {
     }
 
 
-    /**
-     * Gets the webapp directory to run.
-     *
-     * @return the webapp directory
-     */
     /**
      * Gets the webapp directory to run.
      * @return the webapp directory
@@ -922,7 +915,7 @@ public abstract class AbstractRunMojo extends 
AbstractTomcatMojo {
                 String[] files = scanner.getIncludedFiles();
 
                 if (files != null && files.length > 0) {
-                    getLog().info("Coping additional tomcat config files");
+                    getLog().info("Copying additional tomcat config files");
 
                     for (int i = 0; i < files.length; i++) {
                         File file = new File(additionalConfigFilesDir, 
files[i]);
@@ -962,233 +955,229 @@ public abstract class AbstractRunMojo extends 
AbstractTomcatMojo {
      * @throws MojoExecutionException if the server could not be configured
      */
     private void startContainer() throws IOException, LifecycleException, 
MojoExecutionException, Exception {
-        String previousCatalinaBase = System.getProperty("catalina.base");
-
-        try {
 
-            // Set the system properties
-            setupSystemProperties();
+        // Set the system properties
+        setupSystemProperties();
 
-            System.setProperty("catalina.base", 
configurationDir.getAbsolutePath());
+        System.setProperty("catalina.base", 
configurationDir.getAbsolutePath());
 
-            if (serverXml != null) {
-                if (!serverXml.exists()) {
-                    throw new MojoExecutionException(serverXml.getPath() + " 
not exists");
-                }
+        if (serverXml != null) {
+            if (!serverXml.exists()) {
+                throw new MojoExecutionException(serverXml.getPath() + " not 
exists");
+            }
 
-                Catalina container = new Catalina();
+            Catalina container = new Catalina();
 
-                if (useSeparateTomcatClassLoader) {
-                    
Thread.currentThread().setContextClassLoader(getTomcatClassLoader());
-                    container.setParentClassLoader(getTomcatClassLoader());
-                }
+            if (useSeparateTomcatClassLoader) {
+                
Thread.currentThread().setContextClassLoader(getTomcatClassLoader());
+                container.setParentClassLoader(getTomcatClassLoader());
+            }
 
-                container.setUseNaming(this.useNaming);
-                container.setConfigFile(serverXml.getAbsolutePath());
-                container.start();
-                EmbeddedRegistry.getInstance().register(container);
-            } else {
+            container.setUseNaming(this.useNaming);
+            container.setConfigFile(serverXml.getAbsolutePath());
+            container.start();
+            EmbeddedRegistry.getInstance().register(container);
+        } else {
 
-                System.setProperty("java.util.logging.manager", 
"org.apache.juli.ClassLoaderLogManager");
-                System.setProperty("java.util.logging.config.file",
-                        new File(configurationDir, 
"conf/logging.properties").toString());
+            System.setProperty("java.util.logging.manager", 
"org.apache.juli.ClassLoaderLogManager");
+            System.setProperty("java.util.logging.config.file",
+                    new File(configurationDir, 
"conf/logging.properties").toString());
 
-                // Trigger loading of catalina.properties
-                CatalinaProperties.getProperty("foo");
+            // Trigger loading of catalina.properties
+            CatalinaProperties.getProperty("foo");
 
-                Tomcat embeddedTomcat = new ExtendedTomcat(configurationDir);
+            Tomcat embeddedTomcat = new ExtendedTomcat(configurationDir);
 
-                embeddedTomcat.setBaseDir(configurationDir.getAbsolutePath());
-                MemoryRealm memoryRealm = new MemoryRealm();
+            embeddedTomcat.setBaseDir(configurationDir.getAbsolutePath());
+            MemoryRealm memoryRealm = new MemoryRealm();
 
-                if (tomcatUsers != null) {
-                    if (!tomcatUsers.exists()) {
-                        throw new MojoExecutionException(" tomcatUsers " + 
tomcatUsers.getPath() + " not exists");
-                    }
-                    getLog().info("use tomcat-users.xml from " + 
tomcatUsers.getAbsolutePath());
-                    memoryRealm.setPathname(tomcatUsers.getAbsolutePath());
+            if (tomcatUsers != null) {
+                if (!tomcatUsers.exists()) {
+                    throw new MojoExecutionException(" tomcatUsers " + 
tomcatUsers.getPath() + " not exists");
                 }
+                getLog().info("use tomcat-users.xml from " + 
tomcatUsers.getAbsolutePath());
+                memoryRealm.setPathname(tomcatUsers.getAbsolutePath());
+            }
 
-                embeddedTomcat.getEngine().setRealm(memoryRealm);
+            embeddedTomcat.getEngine().setRealm(memoryRealm);
 
-                Context ctx = createContext(embeddedTomcat);
+            Context ctx = createContext(embeddedTomcat);
 
-                if (useNaming) {
-                    embeddedTomcat.enableNaming();
-                }
+            if (useNaming) {
+                embeddedTomcat.enableNaming();
+            }
 
-                embeddedTomcat.getHost().setAppBase(new File(configurationDir, 
"webapps").getAbsolutePath());
+            embeddedTomcat.getHost().setAppBase(new File(configurationDir, 
"webapps").getAbsolutePath());
 
-                if (hostName != null) {
-                    embeddedTomcat.getHost().setName(hostName);
+            if (hostName != null) {
+                embeddedTomcat.getHost().setName(hostName);
+            }
+            if (aliases != null) {
+                for (String alias : aliases) {
+                    embeddedTomcat.getHost().addAlias(alias);
                 }
-                if (aliases != null) {
-                    for (String alias : aliases) {
-                        embeddedTomcat.getHost().addAlias(alias);
-                    }
 
-                }
-                createStaticContext(embeddedTomcat, ctx, 
embeddedTomcat.getHost());
+            }
+            createStaticContext(embeddedTomcat, ctx, embeddedTomcat.getHost());
 
-                Connector connector = new Connector(protocol);
-                connector.setPort(port);
-                connector.setMaxPostSize(maxPostSize);
+            Connector connector = new Connector(protocol);
+            connector.setPort(port);
+            connector.setMaxPostSize(maxPostSize);
 
-                if (httpsPort > 0) {
-                    connector.setRedirectPort(httpsPort);
-                }
+            if (httpsPort > 0) {
+                connector.setRedirectPort(httpsPort);
+            }
 
-                if (address != null) {
-                    connector.setProperty("address", address);
-                }
+            if (address != null) {
+                connector.setProperty("address", address);
+            }
 
-                connector.setURIEncoding(uriEncoding);
+            connector.setURIEncoding(uriEncoding);
 
-                connector.setUseBodyEncodingForURI(this.useBodyEncodingForURI);
+            connector.setUseBodyEncodingForURI(this.useBodyEncodingForURI);
 
-                embeddedTomcat.getService().addConnector(connector);
+            embeddedTomcat.getService().addConnector(connector);
 
-                embeddedTomcat.setConnector(connector);
+            embeddedTomcat.setConnector(connector);
 
-                AccessLogValve alv = new AccessLogValve();
-                alv.setDirectory(new File(configurationDir, 
"logs").getAbsolutePath());
-                alv.setPattern("%h %l %u %t \"%r\" %s %b %I %D");
-                embeddedTomcat.getHost().getPipeline().addValve(alv);
+            AccessLogValve alv = new AccessLogValve();
+            alv.setDirectory(new File(configurationDir, 
"logs").getAbsolutePath());
+            alv.setPattern("%h %l %u %t \"%r\" %s %b %I %D");
+            embeddedTomcat.getHost().getPipeline().addValve(alv);
 
-                // create https connector
-                Connector httpsConnector = null;
-                if (httpsPort > 0) {
-                    httpsConnector = new Connector(protocol);
-                    httpsConnector.setPort(httpsPort);
-                    httpsConnector.setMaxPostSize(maxPostSize);
-                    httpsConnector.setSecure(true);
-                    httpsConnector.setProperty("SSLEnabled", "true");
-                    httpsConnector.setURIEncoding(uriEncoding);
-                    
httpsConnector.setUseBodyEncodingForURI(this.useBodyEncodingForURI);
+            // create https connector
+            Connector httpsConnector = null;
+            if (httpsPort > 0) {
+                httpsConnector = new Connector(protocol);
+                httpsConnector.setPort(httpsPort);
+                httpsConnector.setMaxPostSize(maxPostSize);
+                httpsConnector.setSecure(true);
+                httpsConnector.setProperty("SSLEnabled", "true");
+                httpsConnector.setURIEncoding(uriEncoding);
+                
httpsConnector.setUseBodyEncodingForURI(this.useBodyEncodingForURI);
 
-                    SSLHostConfig hostConfig = new SSLHostConfig();
-                    SSLHostConfigCertificate certificate = new 
SSLHostConfigCertificate(hostConfig,
-                            SSLHostConfigCertificate.DEFAULT_TYPE);
+                SSLHostConfig hostConfig = new SSLHostConfig();
+                SSLHostConfigCertificate certificate = new 
SSLHostConfigCertificate(hostConfig,
+                        SSLHostConfigCertificate.DEFAULT_TYPE);
 
-                    if (keystoreFile != null) {
-                        certificate.setCertificateKeystoreFile(keystoreFile);
-                    }
-                    if (keystorePass != null) {
-                        
certificate.setCertificateKeystorePassword(keystorePass);
-                        httpsConnector.setProperty("keystorePass", 
keystorePass);
-                    }
-                    if (keystoreType != null) {
-                        certificate.setCertificateKeystoreType(keystoreType);
-                    }
+                if (keystoreFile != null) {
+                    certificate.setCertificateKeystoreFile(keystoreFile);
+                }
+                if (keystorePass != null) {
+                    certificate.setCertificateKeystorePassword(keystorePass);
+                    httpsConnector.setProperty("keystorePass", keystorePass);
+                }
+                if (keystoreType != null) {
+                    certificate.setCertificateKeystoreType(keystoreType);
+                }
 
-                    if (trustManagerClassName != null) {
-                        
hostConfig.setTrustManagerClassName(trustManagerClassName);
-                    }
+                if (trustManagerClassName != null) {
+                    hostConfig.setTrustManagerClassName(trustManagerClassName);
+                }
 
-                    if (trustMaxCertLength != null) {
+                if (trustMaxCertLength != null) {
+                    try {
                         
hostConfig.setCertificateVerificationDepth(Integer.parseInt(trustMaxCertLength));
+                    } catch (NumberFormatException e) {
+                        throw new MojoExecutionException("Invalid value for 
trustMaxCertLength: '" +
+                                trustMaxCertLength + "'. Must be an integer.", 
e);
                     }
+                }
 
-                    if (truststoreAlgorithm != null) {
-                        hostConfig.setTruststoreAlgorithm(truststoreAlgorithm);
-                    }
+                if (truststoreAlgorithm != null) {
+                    hostConfig.setTruststoreAlgorithm(truststoreAlgorithm);
+                }
 
-                    if (truststoreFile != null) {
-                        hostConfig.setTruststoreFile(truststoreFile);
-                    }
+                if (truststoreFile != null) {
+                    hostConfig.setTruststoreFile(truststoreFile);
+                }
 
-                    if (truststorePass != null) {
-                        hostConfig.setTruststorePassword(truststorePass);
-                    }
+                if (truststorePass != null) {
+                    hostConfig.setTruststorePassword(truststorePass);
+                }
 
-                    if (truststoreProvider != null) {
-                        hostConfig.setTruststoreProvider(truststoreProvider);
-                    }
+                if (truststoreProvider != null) {
+                    hostConfig.setTruststoreProvider(truststoreProvider);
+                }
 
-                    if (truststoreType != null) {
-                        hostConfig.setTruststoreType(truststoreType);
-                    }
-                    hostConfig.setCertificateVerificationAsString(clientAuth);
+                if (truststoreType != null) {
+                    hostConfig.setTruststoreType(truststoreType);
+                }
+                hostConfig.setCertificateVerificationAsString(clientAuth);
 
-                    if (address != null) {
-                        httpsConnector.setProperty("address", address);
-                    }
-                    hostConfig.addCertificate(certificate);
-                    httpsConnector.addSslHostConfig(hostConfig);
+                if (address != null) {
+                    httpsConnector.setProperty("address", address);
+                }
+                hostConfig.addCertificate(certificate);
+                httpsConnector.addSslHostConfig(hostConfig);
 
-                    
embeddedTomcat.getEngine().getService().addConnector(httpsConnector);
+                
embeddedTomcat.getEngine().getService().addConnector(httpsConnector);
 
-                }
+            }
 
-                // create ajp connector
-                Connector ajpConnector = null;
-                if (ajpPort > 0) {
-                    ajpConnector = new Connector(ajpProtocol);
-                    ajpConnector.setPort(ajpPort);
-                    ajpConnector.setURIEncoding(uriEncoding);
-                    
ajpConnector.setUseBodyEncodingForURI(this.useBodyEncodingForURI);
-                    if (address != null) {
-                        ajpConnector.setProperty("address", address);
-                    }
-                    ajpConnector.setProperty("secretRequired", "false");
-                    
embeddedTomcat.getEngine().getService().addConnector(ajpConnector);
+            // create ajp connector
+            Connector ajpConnector = null;
+            if (ajpPort > 0) {
+                ajpConnector = new Connector(ajpProtocol);
+                ajpConnector.setPort(ajpPort);
+                ajpConnector.setURIEncoding(uriEncoding);
+                
ajpConnector.setUseBodyEncodingForURI(this.useBodyEncodingForURI);
+                if (address != null) {
+                    ajpConnector.setProperty("address", address);
                 }
+                ajpConnector.setProperty("secretRequired", "false");
+                
embeddedTomcat.getEngine().getService().addConnector(ajpConnector);
+            }
 
-                if (addContextWarDependencies || 
!getAdditionalWebapps().isEmpty()) {
-                    createDependencyContexts(embeddedTomcat);
-                }
+            if (addContextWarDependencies || 
!getAdditionalWebapps().isEmpty()) {
+                createDependencyContexts(embeddedTomcat);
+            }
 
-                if (useSeparateTomcatClassLoader) {
-                    
Thread.currentThread().setContextClassLoader(getTomcatClassLoader());
-                    
embeddedTomcat.getEngine().setParentClassLoader(getTomcatClassLoader());
-                }
+            if (useSeparateTomcatClassLoader) {
+                
Thread.currentThread().setContextClassLoader(getTomcatClassLoader());
+                
embeddedTomcat.getEngine().setParentClassLoader(getTomcatClassLoader());
+            }
 
-                embeddedTomcat.start();
+            embeddedTomcat.start();
 
-                Properties portProperties = new Properties();
+            Properties portProperties = new Properties();
 
-                portProperties.put("tomcat.maven.http.port", 
Integer.toString(connector.getLocalPort()));
+            portProperties.put("tomcat.maven.http.port", 
Integer.toString(connector.getLocalPort()));
 
-                
session.getUserProperties().setProperty("tomcat.maven.http.port",
-                        Integer.toString(connector.getLocalPort()));
-                System.setProperty("tomcat.maven.http.port", 
Integer.toString(connector.getLocalPort()));
+            session.getUserProperties().setProperty("tomcat.maven.http.port",
+                    Integer.toString(connector.getLocalPort()));
+            System.setProperty("tomcat.maven.http.port", 
Integer.toString(connector.getLocalPort()));
 
-                if (httpsConnector != null) {
-                    
session.getUserProperties().setProperty("tomcat.maven.https.port",
-                            Integer.toString(httpsConnector.getLocalPort()));
-                    portProperties.put("tomcat.maven.https.port", 
Integer.toString(httpsConnector.getLocalPort()));
-                    System.setProperty("tomcat.maven.https.port", 
Integer.toString(httpsConnector.getLocalPort()));
-                }
+            if (httpsConnector != null) {
+                
session.getUserProperties().setProperty("tomcat.maven.https.port",
+                        Integer.toString(httpsConnector.getLocalPort()));
+                portProperties.put("tomcat.maven.https.port", 
Integer.toString(httpsConnector.getLocalPort()));
+                System.setProperty("tomcat.maven.https.port", 
Integer.toString(httpsConnector.getLocalPort()));
+            }
 
-                if (ajpConnector != null) {
-                    
session.getUserProperties().setProperty("tomcat.maven.ajp.port",
-                            Integer.toString(ajpConnector.getLocalPort()));
-                    portProperties.put("tomcat.maven.ajp.port", 
Integer.toString(ajpConnector.getLocalPort()));
-                    System.setProperty("tomcat.maven.ajp.port", 
Integer.toString(ajpConnector.getLocalPort()));
+            if (ajpConnector != null) {
+                
session.getUserProperties().setProperty("tomcat.maven.ajp.port",
+                        Integer.toString(ajpConnector.getLocalPort()));
+                portProperties.put("tomcat.maven.ajp.port", 
Integer.toString(ajpConnector.getLocalPort()));
+                System.setProperty("tomcat.maven.ajp.port", 
Integer.toString(ajpConnector.getLocalPort()));
+            }
+            if (propertiesPortFilePath != null) {
+                File propertiesPortsFile = new File(propertiesPortFilePath);
+                if (propertiesPortsFile.exists()) {
+                    propertiesPortsFile.delete();
                 }
-                if (propertiesPortFilePath != null) {
-                    File propertiesPortsFile = new 
File(propertiesPortFilePath);
-                    if (propertiesPortsFile.exists()) {
-                        propertiesPortsFile.delete();
-                    }
-                    FileOutputStream fileOutputStream = new 
FileOutputStream(propertiesPortsFile);
-                    try {
-                        portProperties.store(fileOutputStream, "Apache Tomcat 
Maven plugin port used");
-                    } finally {
-                        IOUtils.closeQuietly(fileOutputStream);
-                    }
+                FileOutputStream fileOutputStream = new 
FileOutputStream(propertiesPortsFile);
+                try {
+                    portProperties.store(fileOutputStream, "Apache Tomcat 
Maven plugin port used");
+                } finally {
+                    IOUtils.closeQuietly(fileOutputStream);
                 }
-
-                EmbeddedRegistry.getInstance().register(embeddedTomcat);
-
             }
 
+            EmbeddedRegistry.getInstance().register(embeddedTomcat);
 
-        } finally {
-            if (previousCatalinaBase != null) {
-                System.setProperty("catalina.base", previousCatalinaBase);
-            }
         }
+
     }
 
     private List<Webapp> getAdditionalWebapps() {
diff --git 
a/src/main/java/org/apache/tomcat/maven/plugin/tomcat/run/AbstractStandaloneWarMojo.java
 
b/src/main/java/org/apache/tomcat/maven/plugin/tomcat/run/AbstractStandaloneWarMojo.java
index 3b74a8d..1af42f8 100644
--- 
a/src/main/java/org/apache/tomcat/maven/plugin/tomcat/run/AbstractStandaloneWarMojo.java
+++ 
b/src/main/java/org/apache/tomcat/maven/plugin/tomcat/run/AbstractStandaloneWarMojo.java
@@ -81,12 +81,12 @@ public abstract class AbstractStandaloneWarMojo extends 
AbstractExecWarMojo {
      * @since 2.2
      */
     @Parameter(property = "maven.tomcat.exec.war.attachArtifactType", 
defaultValue = "war", required = true)
-    protected String attachArtifactClassifierType;
+    protected String attachArtifactType;
 
     @Override
     public void execute() throws MojoExecutionException, MojoFailureException {
         if (!"war".equals(project.getPackaging())) {
-            throw new MojoFailureException("Pacakaging must be of type war for 
standalone-war goal.");
+            throw new MojoFailureException("Packaging must be of type war for 
standalone-war goal.");
         }
 
         File warExecFile = new File(buildDirectory, finalName);
@@ -221,7 +221,7 @@ public abstract class AbstractStandaloneWarMojo extends 
AbstractExecWarMojo {
 
             if (attachArtifact) {
                 // MavenProject project, String artifactType, String 
artifactClassifier, File artifactFile
-                projectHelper.attachArtifact(project, 
attachArtifactClassifierType, attachArtifactClassifier,
+                projectHelper.attachArtifact(project, attachArtifactType, 
attachArtifactClassifier,
                         execWarJar);
             }
 
@@ -259,6 +259,12 @@ public abstract class AbstractStandaloneWarMojo extends 
AbstractExecWarMojo {
             IOUtils.closeQuietly(tmpManifestWriter);
             IOUtils.closeQuietly(execWarJarOutputStream);
             IOUtils.closeQuietly(tmpPropertiesFileOutputStream);
+            if (tmpPropertiesFile != null) {
+                tmpPropertiesFile.delete();
+            }
+            if (tmpManifestFile != null) {
+                tmpManifestFile.delete();
+            }
         }
 
     }
diff --git 
a/src/main/java/org/apache/tomcat/maven/plugin/tomcat/run/ExtendedTomcat.java 
b/src/main/java/org/apache/tomcat/maven/plugin/tomcat/run/ExtendedTomcat.java
index 66f26d4..b5bf346 100644
--- 
a/src/main/java/org/apache/tomcat/maven/plugin/tomcat/run/ExtendedTomcat.java
+++ 
b/src/main/java/org/apache/tomcat/maven/plugin/tomcat/run/ExtendedTomcat.java
@@ -42,6 +42,9 @@ public class ExtendedTomcat extends Tomcat {
      */
     public ExtendedTomcat(File configurationDir) {
         super();
+        if (configurationDir == null || !configurationDir.exists() || 
!configurationDir.isDirectory()) {
+            throw new IllegalArgumentException("configurationDir must not be 
null and must exist");
+        }
         this.configurationDir = configurationDir;
     }
 
diff --git 
a/src/main/java/org/apache/tomcat/maven/plugin/tomcat/run/RunMojo.java 
b/src/main/java/org/apache/tomcat/maven/plugin/tomcat/run/RunMojo.java
index 071feab..0f7d5b0 100644
--- a/src/main/java/org/apache/tomcat/maven/plugin/tomcat/run/RunMojo.java
+++ b/src/main/java/org/apache/tomcat/maven/plugin/tomcat/run/RunMojo.java
@@ -187,11 +187,11 @@ public class RunMojo extends AbstractRunMojo {
         FileWriter fw = null;
         StringWriter sw = new StringWriter();
         try {
-            temporaryContextFile = File.createTempFile("tomcat-maven-plugin", 
"temp-ctx-file");
-            temporaryContextFile.deleteOnExit();
-
             // format to modify/create <Context backgroundProcessorDelay="5" 
reloadable="false">
             if (contextFile != null && contextFile.exists()) {
+                temporaryContextFile = 
File.createTempFile("tomcat-maven-plugin", "temp-ctx-file");
+                temporaryContextFile.deleteOnExit();
+
                 MavenFileFilterRequest mavenFileFilterRequest = new 
MavenFileFilterRequest();
                 mavenFileFilterRequest.setFrom(contextFile);
                 mavenFileFilterRequest.setTo(temporaryContextFile);
@@ -205,12 +205,16 @@ public class RunMojo extends AbstractRunMojo {
                 Xpp3Dom xpp3Dom = Xpp3DomBuilder.build(fr);
                 xpp3Dom.setAttribute("backgroundProcessorDelay", 
Integer.toString(backgroundProcessorDelay));
                 xpp3Dom.setAttribute("reloadable", 
Boolean.toString(isContextReloadable()));
+                IOUtil.close(fr);
                 fw = new FileWriter(temporaryContextFile);
                 Xpp3DomWriter.write(fw, xpp3Dom);
                 Xpp3DomWriter.write(sw, xpp3Dom);
                 getLog().debug(" generated context file " + sw.toString());
             } else {
                 if (contextReloadable) {
+                    temporaryContextFile = 
File.createTempFile("tomcat-maven-plugin", "temp-ctx-file");
+                    temporaryContextFile.deleteOnExit();
+
                     // don't care about using a complicated xml api to create 
one xml line :-)
                     StringBuilder sb = new StringBuilder("<Context 
").append("backgroundProcessorDelay=\"")
                             
.append(Integer.toString(backgroundProcessorDelay)).append("\"").append(" 
reloadable=\"")
diff --git 
a/src/main/java/org/apache/tomcat/maven/plugin/tomcat/run/ShutdownMojo.java 
b/src/main/java/org/apache/tomcat/maven/plugin/tomcat/run/ShutdownMojo.java
index 1aacaf7..ffd7001 100644
--- a/src/main/java/org/apache/tomcat/maven/plugin/tomcat/run/ShutdownMojo.java
+++ b/src/main/java/org/apache/tomcat/maven/plugin/tomcat/run/ShutdownMojo.java
@@ -28,7 +28,7 @@ import 
org.apache.tomcat.maven.plugin.tomcat.AbstractTomcatMojo;
 /**
  * <p>
  * Shuts down all possibly started embedded Tomcat servers. This will be 
automatically done through a shutdown hook or
- * you may call this Mojo to shut them down explictly.
+ * you may call this Mojo to shut them down explicitly.
  * </p>
  * <p>
  * By default the <code>shutdown</code> goal is not bound to any phase. For 
integration tests you might want to bind it
diff --git 
a/src/main/java/org/apache/tomcat/maven/plugin/tomcat/run/Webapp.java 
b/src/main/java/org/apache/tomcat/maven/plugin/tomcat/run/Webapp.java
index 2d39b1a..fedbf16 100644
--- a/src/main/java/org/apache/tomcat/maven/plugin/tomcat/run/Webapp.java
+++ b/src/main/java/org/apache/tomcat/maven/plugin/tomcat/run/Webapp.java
@@ -20,25 +20,6 @@ package org.apache.tomcat.maven.plugin.tomcat.run;
 
 import java.io.File;
 
-/*
- * 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.
- */
-
 import org.apache.maven.artifact.Artifact;
 
 /**
@@ -48,29 +29,12 @@ import org.apache.maven.artifact.Artifact;
  */
 public class Webapp {
 
-    /**
-     *
-     */
     private String groupId;
-    /**
-     *
-     */
     private String artifactId;
-    /**
-     *
-     */
     private String version = null;
-    /**
-     *
-     */
     private String type = "war";
-    /**
-     *
-     */
     private String classifier;
-    /**
-     * @parameter
-     */
+
     private String contextPath;
     private Artifact artifact;
     private File contextFile;
@@ -181,10 +145,13 @@ public class Webapp {
      * @return the context path
      */
     public String getContextPath() {
-        if (contextPath == null || contextPath.isEmpty()) {
-            return this.artifactId;
+        if (contextPath != null && !contextPath.isEmpty()) {
+            return contextPath;
+        }
+        if (artifactId != null && !artifactId.isEmpty()) {
+            return artifactId;
         }
-        return contextPath;
+        throw new IllegalStateException("Either contextPath or artifactId must 
be configured");
     }
 
     /**
diff --git a/src/main/java/org/apache/tomcat/maven/runner/PasswordUtil.java 
b/src/main/java/org/apache/tomcat/maven/runner/PasswordUtil.java
index 23a8c11..4951285 100644
--- a/src/main/java/org/apache/tomcat/maven/runner/PasswordUtil.java
+++ b/src/main/java/org/apache/tomcat/maven/runner/PasswordUtil.java
@@ -18,6 +18,9 @@
  */
 package org.apache.tomcat.maven.runner;
 
+import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
+import java.util.List;
 import java.util.Properties;
 
 
@@ -34,10 +37,6 @@ import java.util.Properties;
  * They are not secure, but prevent casual observation.
  * </p>
  *
- * @see <a href=
- *          
"http://grepcode.com/file_/repo1.maven.org/maven2/org.mortbay.jetty/jetty/6.1.11/org/mortbay/jetty/security/Password.java/?v=source";
- *          >Jetty Source org.mortbay.jetty.security.Password</a>
- * 
  * @since 2.0
  */
 public class PasswordUtil {
@@ -60,7 +59,7 @@ public class PasswordUtil {
      */
     public static String obfuscate(String s) {
         StringBuilder buf = new StringBuilder();
-        byte[] b = s.getBytes();
+        byte[] b = s.getBytes(StandardCharsets.UTF_8);
 
         buf.append(__OBFUSCATE);
         for (int i = 0; i < b.length; i++) {
@@ -94,7 +93,9 @@ public class PasswordUtil {
     public static String deobfuscate(String s) {
         if (s.startsWith(__OBFUSCATE)) {
             s = s.substring(__OBFUSCATE.length());
-
+            if (s.length() % 4 != 0) {
+                throw new IllegalArgumentException("Invalid obfuscated 
password: length must be a multiple of 4");
+            }
             byte[] b = new byte[s.length() / 2];
             int l = 0;
             for (int i = 0; i < s.length(); i += 4) {
@@ -104,7 +105,7 @@ public class PasswordUtil {
                 int i2 = (i0 % 256);
                 b[l++] = (byte) ((i1 + i2 - 254) / 2);
             }
-            return new String(b, 0, l);
+            return new String(b, 0, l, StandardCharsets.UTF_8);
         } else {
             return s;
         }
@@ -116,15 +117,19 @@ public class PasswordUtil {
      */
     public static void deobfuscateSystemProps() {
         Properties props = System.getProperties();
+        List<String> keysToModify = new ArrayList<>();
         for (Object obj : props.keySet()) {
             if (obj instanceof String) {
                 String key = (String) obj;
                 String value = props.getProperty(key);
                 if (value != null && value.startsWith(__OBFUSCATE)) {
-                    System.setProperty(key, deobfuscate(value));
+                    keysToModify.add(key);
                 }
             }
         }
+        for (String key : keysToModify) {
+            System.setProperty(key, deobfuscate(System.getProperty(key)));
+        }
     }
 
     /**
@@ -132,10 +137,14 @@ public class PasswordUtil {
      * @param args command-line arguments
      */
     public static void main(String[] args) {
-        if (args[0].startsWith(__OBFUSCATE)) {
-            System.out.println(PasswordUtil.deobfuscate(args[1]));
+        if (args.length < 1) {
+            System.err.println("Usage: PasswordUtil <password>");
+            System.exit(1);
+        }
+        String input = args[0];
+        if (input.startsWith(__OBFUSCATE)) {
+            System.out.println(deobfuscate(input));
         } else {
-            System.out.println(PasswordUtil.obfuscate(args[1]));
+            System.out.println(obfuscate(input));
         }
-    }
-}
+    }}
diff --git a/src/main/java/org/apache/tomcat/maven/runner/TomcatRunner.java 
b/src/main/java/org/apache/tomcat/maven/runner/TomcatRunner.java
index ee0fb0e..fd6f5f8 100644
--- a/src/main/java/org/apache/tomcat/maven/runner/TomcatRunner.java
+++ b/src/main/java/org/apache/tomcat/maven/runner/TomcatRunner.java
@@ -49,8 +49,7 @@ import org.apache.tomcat.util.ExceptionUtils;
 import org.apache.tomcat.util.http.fileupload.FileUtils;
 
 /**
- * FIXME add junit for that but when 
https://issues.apache.org/bugzilla/show_bug.cgi?id=52028 fixed Main class used 
to
- * run the standalone wars in a Apache Tomcat instance.
+ * Main class used to run the standalone wars in a Apache Tomcat instance.
  *
  * @author Olivier Lamy
  * 
@@ -118,6 +117,11 @@ public class TomcatRunner {
      */
     public int ajpPort;
 
+    /**
+     * AJP port number.
+     */
+    public String ajpSecret;
+
     /**
      * Path to the server.xml configuration file.
      */
@@ -126,7 +130,7 @@ public class TomcatRunner {
     /**
      * Runtime properties loaded from the standalone properties file.
      */
-    public Properties runtimeProperties;
+    public Properties runtimeProperties = new Properties();
 
     /**
      * Whether to reset the extraction directory on startup.
@@ -380,7 +384,11 @@ public class TomcatRunner {
                 Connector ajpConnector = new 
Connector("org.apache.coyote.ajp.AjpProtocol");
                 ajpConnector.setPort(ajpPort);
                 ajpConnector.setURIEncoding(uriEncoding);
-                ajpConnector.setProperty("secretRequired", "false");
+                if (ajpSecret != null) {
+                    ajpConnector.setProperty("secret", ajpSecret);
+                } else {
+                    ajpConnector.setProperty("secretRequired", "false");
+                }
                 tomcat.getService().addConnector(ajpConnector);
             }
 
@@ -563,6 +571,9 @@ public class TomcatRunner {
                     throw new Exception("FATAL: impossible to create 
directories:" + parentFile);
                 }
 
+                if (inputStream == null) {
+                    throw new IOException("War resource not found on 
classpath: " + entry.getValue());
+                }
                 expand(inputStream, expandFile);
 
             } finally {
@@ -613,7 +624,7 @@ public class TomcatRunner {
     }
 
     /**
-     * @param warsValue we can value in format: 
wars=foo.war|contextpath;bar.war ( |contextpath is optionnal if empty
+     * @param warsValue we can value in format: 
wars=foo.war|contextpath;bar.war ( |contextpath is optional if empty
      *                      use the war name) so here we return war file name 
and populate webappWarPerContext
      */
     private void populateWebAppWarPerContext(String warsValue) {
@@ -631,9 +642,9 @@ public class TomcatRunner {
             if (separatorIndex >= 0) {
                 warFileName = warValue.substring(0, separatorIndex);
                 contextValue = warValue.substring(separatorIndex + 1);
-
             } else {
-                warFileName = contextValue;
+                warFileName = warValue;
+                contextValue = warValue;
             }
             debugMessage("populateWebAppWarPerContext 
contextValue/warFileName:" + contextValue + "/" + warFileName);
             this.webappWarPerContext.put(contextValue, warFileName);
diff --git a/src/main/java/org/apache/tomcat/maven/runner/TomcatRunnerCli.java 
b/src/main/java/org/apache/tomcat/maven/runner/TomcatRunnerCli.java
index f701055..77990eb 100644
--- a/src/main/java/org/apache/tomcat/maven/runner/TomcatRunnerCli.java
+++ b/src/main/java/org/apache/tomcat/maven/runner/TomcatRunnerCli.java
@@ -63,6 +63,9 @@ public class TomcatRunnerCli {
     static final Option AJP_PORT = 
Option.builder().longOpt("ajpPort").hasArg().argName("ajpPort")
             .desc("ajp port to use").get();
 
+    static final Option AJP_SECRET = 
Option.builder().longOpt("ajpSecret").hasArg().argName("ajpSecret")
+            .desc("ajp secret to use").get();
+
     static final Option SERVER_XML_PATH = 
Option.builder().longOpt("serverXmlPath").hasArg().argName("serverXmlPath")
             .desc("server.xml to use, optional").get();
 
@@ -97,7 +100,7 @@ public class TomcatRunnerCli {
     static final Options OPTIONS = new Options();
 
     static {
-        
OPTIONS.addOption(HTTP_PORT).addOption(HTTPS_PORT).addOption(AJP_PORT).addOption(MAX_POST_SIZE)
+        
OPTIONS.addOption(HTTP_PORT).addOption(HTTPS_PORT).addOption(AJP_PORT).addOption(AJP_SECRET).addOption(MAX_POST_SIZE)
                 
.addOption(SERVER_XML_PATH).addOption(RESET_EXTRACT).addOption(HELP).addOption(DEBUG)
                 
.addOption(SYS_PROPS).addOption(HTTP_PROTOCOL).addOption(CLIENT_AUTH).addOption(KEY_ALIAS)
                 
.addOption(OBFUSCATE).addOption(EXTRACT_DIRECTORY).addOption(URI_ENCODING);
@@ -145,23 +148,55 @@ public class TomcatRunnerCli {
 
         String port = 
tomcatRunner.runtimeProperties.getProperty(TomcatRunner.HTTP_PORT_KEY);
         if (port != null) {
-            tomcatRunner.httpPort = Integer.parseInt(port);
+            try {
+                tomcatRunner.httpPort = Integer.parseInt(port);
+            } catch (NumberFormatException e) {
+                System.err.println("Invalid value for " + 
HTTP_PORT.getArgName() + " '" +
+                        port + "'. Must be an integer.");
+                System.exit(1);
+                System.exit(1);
+            }
         }
 
         // cli win for the port
         if (line.hasOption(HTTP_PORT)) {
-            tomcatRunner.httpPort = 
Integer.parseInt(line.getOptionValue(HTTP_PORT));
+            try {
+                tomcatRunner.httpPort = 
Integer.parseInt(line.getOptionValue(HTTP_PORT));
+            } catch (NumberFormatException e) {
+                System.err.println("Invalid value for " + 
HTTP_PORT.getArgName() + " '" +
+                        line.getOptionValue(HTTP_PORT) + "'. Must be an 
integer.");
+                System.exit(1);
+            }
         }
-
         if (line.hasOption(MAX_POST_SIZE)) {
-            tomcatRunner.maxPostSize = 
Integer.parseInt(line.getOptionValue(MAX_POST_SIZE));
+            try {
+                tomcatRunner.maxPostSize = 
Integer.parseInt(line.getOptionValue(MAX_POST_SIZE));
+            } catch (NumberFormatException e) {
+                System.err.println("Invalid value for " + 
MAX_POST_SIZE.getArgName() + " '" +
+                        line.getOptionValue(MAX_POST_SIZE) + "'. Must be an 
integer.");
+                System.exit(1);
+            }
         }
-
         if (line.hasOption(HTTPS_PORT)) {
-            tomcatRunner.httpsPort = 
Integer.parseInt(line.getOptionValue(HTTPS_PORT));
+            try {
+                tomcatRunner.httpsPort = 
Integer.parseInt(line.getOptionValue(HTTPS_PORT));
+            } catch (NumberFormatException e) {
+                System.err.println("Invalid value for " + 
HTTPS_PORT.getArgName() + " '" +
+                        line.getOptionValue(HTTPS_PORT) + "'. Must be an 
integer.");
+                System.exit(1);
+            }
         }
         if (line.hasOption(AJP_PORT)) {
-            tomcatRunner.ajpPort = 
Integer.parseInt(line.getOptionValue(AJP_PORT));
+            try {
+                tomcatRunner.ajpPort = 
Integer.parseInt(line.getOptionValue(AJP_PORT));
+            } catch (NumberFormatException e) {
+                System.err.println("Invalid value for " + 
AJP_PORT.getArgName() + " '" +
+                        line.getOptionValue(AJP_PORT) + "'. Must be an 
integer.");
+                System.exit(1);
+            }
+        }
+        if (line.hasOption(AJP_SECRET)) {
+            tomcatRunner.ajpSecret = line.getOptionValue(AJP_SECRET);
         }
         if (line.hasOption(RESET_EXTRACT)) {
             tomcatRunner.resetExtract = true;
@@ -205,7 +240,9 @@ public class TomcatRunnerCli {
         InputStream is = Thread.currentThread().getContextClassLoader()
                 .getResourceAsStream(STAND_ALONE_PROPERTIES_FILENAME);
         Properties properties = new Properties();
-        properties.load(is);
+        if (is != null) {
+            properties.load(is);
+        }
         return properties;
     }
 


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to