tomee-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From andygumbre...@apache.org
Subject [2/3] tomee git commit: Delegate RemoteServer.destroy() to usage - Try/catch
Date Sat, 07 Nov 2015 01:27:24 GMT
http://git-wip-us.apache.org/repos/asf/tomee/blob/6df9839b/container/openejb-core/src/main/java/org/apache/openejb/config/RemoteServer.java
----------------------------------------------------------------------
diff --git a/container/openejb-core/src/main/java/org/apache/openejb/config/RemoteServer.java b/container/openejb-core/src/main/java/org/apache/openejb/config/RemoteServer.java
index 891833e..9f7da52 100644
--- a/container/openejb-core/src/main/java/org/apache/openejb/config/RemoteServer.java
+++ b/container/openejb-core/src/main/java/org/apache/openejb/config/RemoteServer.java
@@ -1,704 +1,714 @@
-/*
- * 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.openejb.config;
-
-import org.apache.openejb.OpenEJBRuntimeException;
-import org.apache.openejb.loader.Options;
-import org.apache.openejb.util.Join;
-import org.apache.openejb.util.Pipe;
-
-import java.io.File;
-import java.io.IOException;
-import java.io.OutputStream;
-import java.lang.reflect.Field;
-import java.net.InetSocketAddress;
-import java.net.Socket;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Properties;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicReference;
-
-//import org.apache.openejb.loader.IO;
-
-/**
- * NOTE: Do not add inner or anonymous classes or a dependency without updating ExecMojo
- *
- * @version $Rev$ $Date$
- */
-@SuppressWarnings("UseOfSystemOutOrSystemErr")
-public class RemoteServer {
-
-    private static final Options options = new Options(System.getProperties());
-    public static final String SERVER_DEBUG_PORT = "server.debug.port";
-    public static final String SERVER_SHUTDOWN_PORT = "server.shutdown.port";
-    public static final String SERVER_SHUTDOWN_HOST = "server.shutdown.host";
-    public static final String SERVER_SHUTDOWN_COMMAND = "server.shutdown.command";
-    public static final String OPENEJB_SERVER_DEBUG = "openejb.server.debug";
-    public static final String START = "start";
-    public static final String STOP = "stop";
-
-    private final boolean debug = options.get(OPENEJB_SERVER_DEBUG, false);
-    private final boolean profile = options.get("openejb.server.profile", false);
-    private final boolean tomcat;
-    private final String javaOpts = System.getProperty("java.opts");
-    private String additionalClasspath;
-
-    /**
-     * Has the remote server's instance been already running ?
-     */
-    private boolean serverHasAlreadyBeenStarted = true;
-
-    private Properties properties;
-    private final AtomicReference<Process> server = new AtomicReference<Process>();
-    private final int tries;
-    private final boolean verbose;
-    private final int portShutdown;
-    private final String host;
-    private final String command;
-    private File home;
-    private int portStartup;
-
-    public RemoteServer() {
-        this(options.get("connect.tries", 60), options.get("verbose", false));
-    }
-
-    public RemoteServer(final int tries, final boolean verbose) {
-        this.tries = (tries < 1 ? 1 : (tries > 3600 ? 3600 : tries)); //Wait at least 1 second to start or stop, but not more than an hour.
-        this.verbose = verbose;
-        home = getHome();
-        tomcat = (home != null) && (new File(new File(home, "bin"), "catalina.sh").exists());
-
-        portShutdown = options.get(SERVER_SHUTDOWN_PORT, tomcat ? 8005 : 4200);
-        portStartup = portShutdown;
-        command = options.get(SERVER_SHUTDOWN_COMMAND, "SHUTDOWN");
-        host = options.get(SERVER_SHUTDOWN_HOST, "localhost");
-    }
-
-    public void init(final Properties props) {
-        properties = props;
-
-        props.put("java.naming.factory.initial", "org.apache.openejb.client.RemoteInitialContextFactory");
-        final int port = options.get("ejbd.port", 4201);
-        props.put("java.naming.provider.url", options.get("java.naming.provider.url", "127.0.0.1:" + port));
-        props.put("java.naming.security.principal", "testuser");
-        props.put("java.naming.security.credentials", "testpassword");
-    }
-
-    public static void main(final String[] args) {
-        assert args.length > 0 : "no arguments supplied: valid arguments are 'start' or 'stop'";
-        if (args[0].equalsIgnoreCase(START)) {
-            new RemoteServer().start();
-        } else if (args[0].equalsIgnoreCase(STOP)) {
-            final RemoteServer remoteServer = new RemoteServer();
-            remoteServer.serverHasAlreadyBeenStarted = false;
-            try {
-                remoteServer.forceStop();
-            } catch (final Exception e) {
-                e.printStackTrace(System.err);
-            }
-        } else {
-            throw new OpenEJBRuntimeException("valid arguments are 'start' or 'stop'");
-        }
-    }
-
-    public int getPortStartup() {
-        return this.portStartup;
-    }
-
-    public void setPortStartup(final int portStartup) {
-        this.portStartup = portStartup;
-    }
-
-    public Properties getProperties() {
-        return this.properties;
-    }
-
-    public void destroy() {
-
-        final boolean stopSent = stop();
-
-        final Process p = server.get();
-        if (p != null) {
-
-            if (stopSent) {
-                waitFor(p);
-            } else {
-                p.destroy();
-            }
-        }
-    }
-
-    public void start() {
-        start(Collections.<String>emptyList(), START, true);
-    }
-
-    public void start(final List<String> additionalArgs, final String cmd, final boolean checkPortAvailable) {
-        cmd(additionalArgs, cmd, checkPortAvailable);
-    }
-
-    private void cmd(final List<String> additionalArgs, final String cmd, final boolean checkPortAvailable) {
-        boolean ok = true;
-        final int port = START.equals(cmd) ? portStartup : portShutdown;
-
-        if (checkPortAvailable) {
-            ok = !connect(port, 1);
-        }
-
-        if (ok) {
-            try {
-                if (verbose) {
-                    System.out.println("[] " + cmd.toUpperCase() + " SERVER");
-                }
-
-                final File home = getHome();
-                final String javaVersion = System.getProperty("java.version");
-                if (verbose) {
-                    System.out.println("OPENEJB_HOME = " + home.getAbsolutePath());
-                    final String systemInfo = "Java " + javaVersion + "; " + System.getProperty("os.name") + "/" + System.getProperty("os.version");
-                    System.out.println("SYSTEM_INFO  = " + systemInfo);
-                }
-
-                serverHasAlreadyBeenStarted = false;
-
-                final File lib = new File(home, "lib");
-                final File webapplib = new File(new File(new File(home, "webapps"), "tomee"), "lib");
-
-                File javaagentJar = null;
-                try {
-                    javaagentJar = lib("openejb-javaagent", lib, webapplib);
-                } catch (final IllegalStateException ise) {
-                    // no-op
-                }
-
-                final File conf = new File(home, "conf");
-                final File loggingProperties = new File(conf, "logging.properties");
-
-                //File openejbJar = new File(lib, "openejb-core-" + version + ".jar");
-
-                final String java;
-                final boolean isWindows = System.getProperty("os.name", "unknown").toLowerCase().startsWith("windows");
-                if (isWindows && START.equals(cmd) && options.get("server.windows.fork", false)) {
-                    // run and forget
-                    java = new File(System.getProperty("java.home"), "bin/javaw").getAbsolutePath();
-                } else {
-                    java = new File(System.getProperty("java.home"), "bin/java").getAbsolutePath();
-                }
-
-                final List<String> argsList = new ArrayList<String>(20);
-                argsList.add(java);
-                argsList.add("-XX:+HeapDumpOnOutOfMemoryError");
-
-                if (debug) {
-                    argsList.add("-Xdebug");
-                    argsList.add("-Xnoagent");
-                    argsList.add("-Djava.compiler=NONE");
-                    argsList.add("-Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=" + options.get(SERVER_DEBUG_PORT, 5005));
-                }
-
-                if (profile) {
-                    String yourkitHome = options.get("yourkit.home", "/Applications/YourKit_Java_Profiler_9.5.6.app/bin/mac/");
-                    if (!yourkitHome.endsWith("/")) {
-                        yourkitHome += "/";
-                    }
-                    final String yourkitOpts = options.get("yourkit.opts", "disablestacktelemetry,disableexceptiontelemetry,builtinprobes=none,delay=10000,sessionname=Tomcat");
-                    argsList.add("-agentpath:" + yourkitHome + "libyjpagent.jnilib=" + yourkitOpts);
-                }
-
-                if (javaOpts != null) {
-                    Collections.addAll(argsList, javaOpts.split(" +"));
-                }
-
-                final Map<String, String> addedArgs = new HashMap<String, String>();
-                if (additionalArgs != null) {
-                    for (final String arg : additionalArgs) {
-                        final String[] values = arg.split("=");
-                        if (values.length == 1) {
-                            addedArgs.put(values[0], "null");
-                        } else {
-                            addedArgs.put(values[0], values[1]);
-                        }
-                        argsList.add(arg);
-                    }
-                }
-
-                if (!addedArgs.containsKey("-Djava.util.logging.config.file") && loggingProperties.exists()) {
-                    argsList.add("-Djava.util.logging.config.file=" + loggingProperties.getAbsolutePath());
-                }
-
-                if (javaagentJar != null && javaagentJar.exists()) {
-                    argsList.add("-javaagent:" + javaagentJar.getAbsolutePath());
-                }
-
-                //DMB: If you don't use an array, you get problems with jar paths containing spaces
-                // the command won't parse correctly
-                final String ps = File.pathSeparator;
-
-                final String[] args;
-                if (!tomcat) {
-                    final File openejbJar = lib("openejb-core", lib, webapplib);
-                    final StringBuilder cp = new StringBuilder(openejbJar.getAbsolutePath());
-                    if (additionalClasspath != null) {
-                        cp.append(ps).append(additionalClasspath);
-                    }
-
-                    argsList.add("-cp");
-                    argsList.add(cp.toString());
-                    argsList.add("org.apache.openejb.cli.Bootstrap");
-                } else {
-                    final File bin = new File(home, "bin");
-                    final File tlib = new File(home, "lib");
-                    final File bootstrapJar = new File(bin, "bootstrap.jar");
-                    final File juliJar = new File(bin, "tomcat-juli.jar");
-                    final File commonsLoggingJar = new File(bin, "commons-logging-api.jar");
-
-                    final File endorsed = new File(home, "endorsed");
-                    final File temp = new File(home, "temp");
-
-//                    if (!addedArgs.containsKey("-Dcom.sun.management.jmxremote")) {
-//                        argsList.add("-Dcom.sun.management.jmxremote");
-//                    }
-                    if (!addedArgs.containsKey("-Djava.util.logging.manager")) {
-                        argsList.add("-Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager");
-                    }
-                    if (!addedArgs.containsKey("-Djava.io.tmpdir")) {
-                        argsList.add("-Djava.io.tmpdir=" + temp.getAbsolutePath());
-                    }
-                    if (!addedArgs.containsKey("-Djava.endorsed.dirs")) {
-                        argsList.add("-Djava.endorsed.dirs=" + endorsed.getAbsolutePath());
-                    }
-                    if (!addedArgs.containsKey("-Dcatalina.base")) {
-                        argsList.add("-Dcatalina.base=" + home.getAbsolutePath());
-                    }
-                    if (!addedArgs.containsKey("-Dcatalina.home")) {
-                        argsList.add("-Dcatalina.home=" + home.getAbsolutePath());
-                    }
-                    if (!addedArgs.containsKey("-Dcatalina.ext.dirs")) {
-                        argsList.add("-Dcatalina.ext.dirs=" + tlib.getAbsolutePath());
-                    }
-                    if (!addedArgs.containsKey("-Dorg.apache.catalina.STRICT_SERVLET_COMPLIANCE")) {
-                        argsList.add("-Dorg.apache.catalina.STRICT_SERVLET_COMPLIANCE=true");
-                    }
-                    if (!addedArgs.containsKey("-Dorg.apache.tomcat.util.http.ServerCookie.ALLOW_HTTP_SEPARATORS_IN_V0")) {
-                        argsList.add("-Dorg.apache.tomcat.util.http.ServerCookie.ALLOW_HTTP_SEPARATORS_IN_V0=true");
-                    }
-
-                    if (addedArgs.isEmpty()) { // default case
-                        addIfSet(argsList, "javax.net.ssl.keyStore");
-                        addIfSet(argsList, "javax.net.ssl.keyStorePassword");
-                        addIfSet(argsList, "javax.net.ssl.trustStore");
-                        addIfSet(argsList, "java.protocol.handler.pkgs");
-                    }
-
-                    argsList.add("-ea");
-                    argsList.add("-classpath");
-
-                    final StringBuilder cp = new StringBuilder(bootstrapJar.getAbsolutePath()).append(ps).append(juliJar.getAbsolutePath());
-                    if (commonsLoggingJar.exists()) {
-                        cp.append(ps).append(commonsLoggingJar.getAbsolutePath());
-                    }
-                    if (additionalClasspath != null) {
-                        cp.append(ps).append(additionalClasspath);
-                    }
-                    argsList.add(cp.toString());
-
-                    argsList.add("org.apache.catalina.startup.Bootstrap");
-                }
-
-                if (cmd == null) {
-                    argsList.add(START);
-                } else {
-                    argsList.add(cmd);
-                }
-                args = argsList.toArray(new String[argsList.size()]);
-
-                if (verbose) {
-                    System.out.println(Join.join("\n", args));
-                }
-
-                // kill3UNIXDebug();
-                final ProcessBuilder pb = new ProcessBuilder(args);
-                pb.directory(home.getAbsoluteFile());
-                Process p = pb.start();
-
-                //Process p = Runtime.getRuntime().exec(args);
-                Pipe.pipeOut(p); // why would we need to redirect System.in to the process, TomEE doesn't use it
-
-                if (START.equals(cmd)) {
-                    server.set(p);
-                } else if (STOP.equals(cmd)) {
-                    waitFor(p);
-                    p = server.get();
-                    if (p != null) {
-                        waitFor(p);
-                    }
-                }
-
-                System.out.println("Started server process on port: " + port);
-
-            } catch (final Exception e) {
-                throw (RuntimeException) new OpenEJBRuntimeException("Cannot start the server.  Exception: " + e.getClass().getName() + ": " + e.getMessage()).initCause(e);
-            }
-
-            if (debug) {
-                if (!connect(port, Integer.MAX_VALUE)) {
-                    destroy();
-                    throw new OpenEJBRuntimeException("Could not connect to server");
-                }
-            } else {
-                if (!connect(port, tries)) {
-                    destroy();
-                    throw new OpenEJBRuntimeException("Could not connect to server");
-                }
-            }
-
-        } else {
-            if (verbose) {
-                System.out.println("[] FOUND STARTED SERVER");
-            }
-        }
-    }
-
-    private void waitFor(final Process p) {
-        final CountDownLatch latch = new CountDownLatch(1);
-        final Thread t = new Thread(new Runnable() {
-            @Override
-            public void run() {
-                try {
-                    p.waitFor();
-                } catch (final InterruptedException e) {
-                    //Ignore
-                }
-
-                latch.countDown();
-            }
-        }, "process-waitFor");
-
-        t.start();
-
-        try {
-            if (!latch.await(10, TimeUnit.SECONDS)) {
-                killOnExit(p);
-                throw new RuntimeException("Timeout waiting for process");
-            }
-        } catch (final InterruptedException e) {
-            killOnExit(p);
-        }
-    }
-
-    public void kill3UNIX() { // debug purpose only
-        if (System.getProperty("os.name", "unknown").toLowerCase().startsWith("windows")) {
-            return;
-        }
-
-        try {
-            final Field f = server.get().getClass().getDeclaredField("pid");
-            f.setAccessible(true);
-            final int pid = (Integer) f.get(server.get());
-            Pipe.pipe(Runtime.getRuntime().exec("kill -3 " + pid));
-        } catch (final Exception e1) {
-            e1.printStackTrace();
-        }
-    }
-
-    private File lib(final String name, final File... dirs) {
-        for (final File dir : dirs) {
-            final File[] files = dir.listFiles();
-            if (files != null) {
-                for (final File file : files) {
-                    if (!file.isFile()) {
-                        continue;
-                    }
-                    if (!file.getName().endsWith(".jar")) {
-                        continue;
-                    }
-                    if (file.getName().startsWith(name)) {
-                        return file;
-                    }
-                }
-            }
-        }
-
-        if (debug) {
-            for (final File dir : dirs) {
-                dumpLibs(dir);
-            }
-        }
-        throw new IllegalStateException("Cannot find the " + name + " jar");
-    }
-
-    // for debug purpose
-    private static void dumpLibs(final File dir) {
-        if (!dir.exists()) {
-            System.out.println("lib dir doesn't exist");
-            return;
-        }
-        final File[] files = dir.listFiles();
-        if (files != null) {
-            for (final File lib : files) {
-                System.out.println(lib.getAbsolutePath());
-            }
-        }
-    }
-
-    public Process getServer() {
-        return server.get();
-    }
-
-    private void addIfSet(final List<String> argsList, final String key) {
-        if (System.getProperties().containsKey(key)) {
-            argsList.add("-D" + key + "=" + System.getProperty(key));
-        }
-    }
-
-    private File getHome() {
-        if (home != null) {
-            return home;
-        }
-
-        final String openejbHome = System.getProperty("openejb.home");
-
-        if (openejbHome != null) {
-            home = new File(openejbHome);
-        }
-        return home;
-    }
-
-    public boolean stop() {
-        if (sendShutdown(5)) {
-            return true;
-        } else {
-            if (verbose) {
-                notSent();
-            }
-
-            return false;
-        }
-    }
-
-    private void notSent() {
-        System.out.println("Failed to send the shutdown notification - TomEE is likely shut down already");
-    }
-
-    public void forceStop() throws Exception {
-        if (sendShutdown(5)) {
-
-            // Check TomEE was effectively shut down after getting the message
-            // There can be concurrent shutdown operations (catalina shutdown hook for instance),
-            // so we have to wait here since it is important to be synchronous in this method
-            waitForServerShutdown();
-        } else {
-            if (verbose) {
-                notSent();
-            }
-        }
-    }
-
-    private void waitForServerShutdown() throws Exception {
-
-        if (verbose) {
-            System.out.print("Waiting for TomEE shutdown.");
-        }
-
-        final boolean b = disconnect(portShutdown, tries);
-
-        if (verbose) {
-            System.out.println();
-        }
-
-        if (!b) {
-            //We need to know about this
-            System.out.println("SEVERE: Failed to shutdown TomEE running on port " + portStartup + " using shutdown port: " + portShutdown);
-        }
-    }
-
-    /**
-     * Send the shutdown message to the running server
-     *
-     * @param attempts How many times to try to send the message before giving up
-     * @return True is the message was sent, else false if unable to connect after the defined number of attempts
-     */
-    private boolean sendShutdown(int attempts) {
-        Socket socket = null;
-        OutputStream stream = null;
-        try {
-            socket = new Socket(host, portShutdown);
-            stream = socket.getOutputStream();
-            final String shutdown = command + Character.toString((char) 0);
-            for (int i = 0; i < shutdown.length(); i++) {
-                stream.write(shutdown.charAt(i));
-            }
-            stream.flush();
-        } catch (final Exception e) {
-            if (attempts > 0) {
-                try {
-                    Thread.sleep(1000);
-                } catch (final InterruptedException ie) {
-                    return false;
-                }
-                return sendShutdown(--attempts);
-            } else {
-                return false;
-            }
-        } finally {
-            if (null != stream) {
-                try {
-                    stream.close();
-                } catch (final Exception e) {
-                    // Ignore
-                }
-            }
-            if (socket != null) {
-                try {
-                    socket.close();
-                } catch (final Exception e) {
-                    // Ignore
-                }
-            }
-        }
-
-        return true;
-    }
-
-    private boolean connect(final int port, int tries) {
-        if (verbose) {
-            System.out.println("[] CONNECT ATTEMPT " + (this.tries - tries) + " on port: " + port);
-        }
-
-        Socket s = null;
-        try {
-            s = new Socket();
-            s.connect(new InetSocketAddress(this.host, port), 1000);
-            s.getOutputStream().close();
-            if (verbose) {
-                System.out.println("[] CONNECTED IN " + (this.tries - tries));
-            }
-        } catch (final Exception e) {
-            if (tries < 2) {
-                if (verbose) {
-                    System.out.println("[] CONNECT ATTEMPTS FAILED ( " + (this.tries - tries) + " ATTEMPTS)");
-                }
-                return false;
-            } else {
-                try {
-                    Thread.sleep(1000);
-                } catch (final Exception e2) {
-                    e2.printStackTrace();
-                }
-                return connect(port, --tries);
-            }
-        } finally {
-            if (s != null) {
-                try {
-                    s.close();
-                } catch (final Exception ignored) {
-                    // no-op
-                }
-            }
-        }
-
-        return true;
-    }
-
-    private boolean disconnect(final int port, int tries) {
-        if (verbose) {
-            System.out.println("[] DISCONNECT ATTEMPT " + (this.tries - tries) + " on port: " + port);
-        }
-
-        Socket s = null;
-        try {
-            s = new Socket();
-            s.connect(new InetSocketAddress(this.host, port), 500);
-            s.getOutputStream().close();
-
-            if (verbose) {
-                System.out.println("[] NOT DISCONNECTED AFTER ( " + (this.tries - tries) + " ATTEMPTS)");
-            }
-
-            if (tries < 2) {
-                //Give up
-                return false;
-            } else {
-                try {
-                    Thread.sleep(1000);
-                } catch (final Exception e2) {
-                    e2.printStackTrace();
-                }
-
-                return disconnect(port, --tries);
-            }
-
-        } catch (final IOException e) {
-            //This is what we want
-        } finally {
-            if (s != null) {
-                try {
-                    s.close();
-                } catch (final Exception ignored) {
-                    // no-op
-                }
-            }
-        }
-
-        return true;
-    }
-
-    public void setAdditionalClasspath(final String additionalClasspath) {
-        this.additionalClasspath = additionalClasspath;
-    }
-
-    public void killOnExit() {
-        final Process p = this.server.get();
-        if (!serverHasAlreadyBeenStarted && kill.contains(p)) {
-            return;
-        }
-
-        killOnExit(p);
-    }
-
-    private static void killOnExit(final Process p) {
-        kill.add(p);
-    }
-
-    // Shutdown hook for processes
-    private static final List<Process> kill = new ArrayList<Process>();
-
-    static {
-        Runtime.getRuntime().addShutdownHook(new CleanUpThread());
-    }
-
-    public static class CleanUpThread extends Thread {
-        @Override
-        public void run() {
-            for (final Process server : kill) {
-                try {
-                    if (server != null) {
-                        server.destroy();
-                        server.waitFor();
-                    }
-                } catch (final Throwable e) {
-                    //Ignore
-                }
-            }
-        }
-    }
-}
+/*
+ * 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.openejb.config;
+
+import org.apache.openejb.OpenEJBRuntimeException;
+import org.apache.openejb.loader.Options;
+import org.apache.openejb.util.Join;
+import org.apache.openejb.util.Pipe;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.lang.reflect.Field;
+import java.net.InetSocketAddress;
+import java.net.Socket;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicReference;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+//import org.apache.openejb.loader.IO;
+
+/**
+ * NOTE: Do not add inner or anonymous classes or a dependency without updating ExecMojo
+ *
+ * @version $Rev$ $Date$
+ */
+@SuppressWarnings("UseOfSystemOutOrSystemErr")
+public class RemoteServer {
+
+    private static final Options options = new Options(System.getProperties());
+    public static final String SERVER_DEBUG_PORT = "server.debug.port";
+    public static final String SERVER_SHUTDOWN_PORT = "server.shutdown.port";
+    public static final String SERVER_SHUTDOWN_HOST = "server.shutdown.host";
+    public static final String SERVER_SHUTDOWN_COMMAND = "server.shutdown.command";
+    public static final String OPENEJB_SERVER_DEBUG = "openejb.server.debug";
+    public static final String START = "start";
+    public static final String STOP = "stop";
+
+    private final boolean debug = options.get(OPENEJB_SERVER_DEBUG, false);
+    private final boolean profile = options.get("openejb.server.profile", false);
+    private final boolean tomcat;
+    private final String javaOpts = System.getProperty("java.opts");
+    private String additionalClasspath;
+
+    /**
+     * Has the remote server's instance been already running ?
+     */
+    private boolean serverHasAlreadyBeenStarted = true;
+
+    private Properties properties;
+    private final AtomicReference<Process> server = new AtomicReference<Process>();
+    private final int tries;
+    private final boolean verbose;
+    private final int portShutdown;
+    private final String host;
+    private final String command;
+    private File home;
+    private int portStartup;
+
+    public RemoteServer() {
+        this(options.get("connect.tries", 60), options.get("verbose", false));
+    }
+
+    public RemoteServer(final int tries, final boolean verbose) {
+        this.tries = (tries < 1 ? 1 : (tries > 3600 ? 3600 : tries)); //Wait at least 1 second to start or stop, but not more than an hour.
+        this.verbose = verbose;
+        home = getHome();
+        tomcat = (home != null) && (new File(new File(home, "bin"), "catalina.sh").exists());
+
+        portShutdown = options.get(SERVER_SHUTDOWN_PORT, tomcat ? 8005 : 4200);
+        portStartup = portShutdown;
+        command = options.get(SERVER_SHUTDOWN_COMMAND, "SHUTDOWN");
+        host = options.get(SERVER_SHUTDOWN_HOST, "localhost");
+    }
+
+    public void init(final Properties props) {
+        properties = props;
+
+        props.put("java.naming.factory.initial", "org.apache.openejb.client.RemoteInitialContextFactory");
+        final int port = options.get("ejbd.port", 4201);
+        props.put("java.naming.provider.url", options.get("java.naming.provider.url", "127.0.0.1:" + port));
+        props.put("java.naming.security.principal", "testuser");
+        props.put("java.naming.security.credentials", "testpassword");
+    }
+
+    public static void main(final String[] args) {
+        assert args.length > 0 : "no arguments supplied: valid arguments are 'start' or 'stop'";
+        if (args[0].equalsIgnoreCase(START)) {
+            final RemoteServer remoteServer = new RemoteServer();
+            try {
+                remoteServer.start();
+            } catch (final Exception e) {
+                remoteServer.destroy();
+                e.printStackTrace(System.err);
+            }
+        } else if (args[0].equalsIgnoreCase(STOP)) {
+            final RemoteServer remoteServer = new RemoteServer();
+            remoteServer.serverHasAlreadyBeenStarted = false;
+            try {
+                remoteServer.forceStop();
+            } catch (final Exception e) {
+                e.printStackTrace(System.err);
+            }
+        } else {
+            throw new OpenEJBRuntimeException("valid arguments are 'start' or 'stop'");
+        }
+    }
+
+    public int getPortStartup() {
+        return this.portStartup;
+    }
+
+    public void setPortStartup(final int portStartup) {
+        this.portStartup = portStartup;
+    }
+
+    public Properties getProperties() {
+        return this.properties;
+    }
+
+    public void destroy() {
+
+        try {
+            final boolean stopSent = stop();
+
+            final Process p = server.get();
+            if (p != null) {
+
+                if (stopSent) {
+                    waitFor(p);
+                } else {
+                    p.destroy();
+                }
+            }
+        } catch (final Exception e) {
+            Logger.getLogger(RemoteServer.class.getName()).log(Level.WARNING, "Failed to destroy remote server process", e);
+        }
+    }
+
+    public void start() {
+        start(Collections.<String>emptyList(), START, true);
+    }
+
+    public void start(final List<String> additionalArgs, final String cmd, final boolean checkPortAvailable) {
+        cmd(additionalArgs, cmd, checkPortAvailable);
+    }
+
+    private void cmd(final List<String> additionalArgs, final String cmd, final boolean checkPortAvailable) {
+        boolean ok = true;
+        final int port = START.equals(cmd) ? portStartup : portShutdown;
+
+        if (checkPortAvailable) {
+            ok = !connect(port, 1);
+        }
+
+        if (ok) {
+            try {
+                if (verbose) {
+                    System.out.println("[] " + cmd.toUpperCase() + " SERVER");
+                }
+
+                final File home = getHome();
+                final String javaVersion = System.getProperty("java.version");
+                if (verbose) {
+                    System.out.println("OPENEJB_HOME = " + home.getAbsolutePath());
+                    final String systemInfo = "Java " + javaVersion + "; " + System.getProperty("os.name") + "/" + System.getProperty("os.version");
+                    System.out.println("SYSTEM_INFO  = " + systemInfo);
+                }
+
+                serverHasAlreadyBeenStarted = false;
+
+                final File lib = new File(home, "lib");
+                final File webapplib = new File(new File(new File(home, "webapps"), "tomee"), "lib");
+
+                File javaagentJar = null;
+                try {
+                    javaagentJar = lib("openejb-javaagent", lib, webapplib);
+                } catch (final IllegalStateException ise) {
+                    // no-op
+                }
+
+                final File conf = new File(home, "conf");
+                final File loggingProperties = new File(conf, "logging.properties");
+
+                //File openejbJar = new File(lib, "openejb-core-" + version + ".jar");
+
+                final String java;
+                final boolean isWindows = System.getProperty("os.name", "unknown").toLowerCase().startsWith("windows");
+                if (isWindows && START.equals(cmd) && options.get("server.windows.fork", false)) {
+                    // run and forget
+                    java = new File(System.getProperty("java.home"), "bin/javaw").getAbsolutePath();
+                } else {
+                    java = new File(System.getProperty("java.home"), "bin/java").getAbsolutePath();
+                }
+
+                final List<String> argsList = new ArrayList<String>(20);
+                argsList.add(java);
+                argsList.add("-XX:+HeapDumpOnOutOfMemoryError");
+
+                if (debug) {
+                    argsList.add("-Xdebug");
+                    argsList.add("-Xnoagent");
+                    argsList.add("-Djava.compiler=NONE");
+                    argsList.add("-Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=" + options.get(SERVER_DEBUG_PORT, 5005));
+                }
+
+                if (profile) {
+                    String yourkitHome = options.get("yourkit.home", "/Applications/YourKit_Java_Profiler_9.5.6.app/bin/mac/");
+                    if (!yourkitHome.endsWith("/")) {
+                        yourkitHome += "/";
+                    }
+                    final String yourkitOpts = options.get("yourkit.opts", "disablestacktelemetry,disableexceptiontelemetry,builtinprobes=none,delay=10000,sessionname=Tomcat");
+                    argsList.add("-agentpath:" + yourkitHome + "libyjpagent.jnilib=" + yourkitOpts);
+                }
+
+                if (javaOpts != null) {
+                    Collections.addAll(argsList, javaOpts.split(" +"));
+                }
+
+                final Map<String, String> addedArgs = new HashMap<String, String>();
+                if (additionalArgs != null) {
+                    for (final String arg : additionalArgs) {
+                        final String[] values = arg.split("=");
+                        if (values.length == 1) {
+                            addedArgs.put(values[0], "null");
+                        } else {
+                            addedArgs.put(values[0], values[1]);
+                        }
+                        argsList.add(arg);
+                    }
+                }
+
+                if (!addedArgs.containsKey("-Djava.util.logging.config.file") && loggingProperties.exists()) {
+                    argsList.add("-Djava.util.logging.config.file=" + loggingProperties.getAbsolutePath());
+                }
+
+                if (javaagentJar != null && javaagentJar.exists()) {
+                    argsList.add("-javaagent:" + javaagentJar.getAbsolutePath());
+                }
+
+                //DMB: If you don't use an array, you get problems with jar paths containing spaces
+                // the command won't parse correctly
+                final String ps = File.pathSeparator;
+
+                final String[] args;
+                if (!tomcat) {
+                    final File openejbJar = lib("openejb-core", lib, webapplib);
+                    final StringBuilder cp = new StringBuilder(openejbJar.getAbsolutePath());
+                    if (additionalClasspath != null) {
+                        cp.append(ps).append(additionalClasspath);
+                    }
+
+                    argsList.add("-cp");
+                    argsList.add(cp.toString());
+                    argsList.add("org.apache.openejb.cli.Bootstrap");
+                } else {
+                    final File bin = new File(home, "bin");
+                    final File tlib = new File(home, "lib");
+                    final File bootstrapJar = new File(bin, "bootstrap.jar");
+                    final File juliJar = new File(bin, "tomcat-juli.jar");
+                    final File commonsLoggingJar = new File(bin, "commons-logging-api.jar");
+
+                    final File endorsed = new File(home, "endorsed");
+                    final File temp = new File(home, "temp");
+
+//                    if (!addedArgs.containsKey("-Dcom.sun.management.jmxremote")) {
+//                        argsList.add("-Dcom.sun.management.jmxremote");
+//                    }
+                    if (!addedArgs.containsKey("-Djava.util.logging.manager")) {
+                        argsList.add("-Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager");
+                    }
+                    if (!addedArgs.containsKey("-Djava.io.tmpdir")) {
+                        argsList.add("-Djava.io.tmpdir=" + temp.getAbsolutePath());
+                    }
+                    if (!addedArgs.containsKey("-Djava.endorsed.dirs")) {
+                        argsList.add("-Djava.endorsed.dirs=" + endorsed.getAbsolutePath());
+                    }
+                    if (!addedArgs.containsKey("-Dcatalina.base")) {
+                        argsList.add("-Dcatalina.base=" + home.getAbsolutePath());
+                    }
+                    if (!addedArgs.containsKey("-Dcatalina.home")) {
+                        argsList.add("-Dcatalina.home=" + home.getAbsolutePath());
+                    }
+                    if (!addedArgs.containsKey("-Dcatalina.ext.dirs")) {
+                        argsList.add("-Dcatalina.ext.dirs=" + tlib.getAbsolutePath());
+                    }
+                    if (!addedArgs.containsKey("-Dorg.apache.catalina.STRICT_SERVLET_COMPLIANCE")) {
+                        argsList.add("-Dorg.apache.catalina.STRICT_SERVLET_COMPLIANCE=true");
+                    }
+                    if (!addedArgs.containsKey("-Dorg.apache.tomcat.util.http.ServerCookie.ALLOW_HTTP_SEPARATORS_IN_V0")) {
+                        argsList.add("-Dorg.apache.tomcat.util.http.ServerCookie.ALLOW_HTTP_SEPARATORS_IN_V0=true");
+                    }
+
+                    if (addedArgs.isEmpty()) { // default case
+                        addIfSet(argsList, "javax.net.ssl.keyStore");
+                        addIfSet(argsList, "javax.net.ssl.keyStorePassword");
+                        addIfSet(argsList, "javax.net.ssl.trustStore");
+                        addIfSet(argsList, "java.protocol.handler.pkgs");
+                    }
+
+                    argsList.add("-ea");
+                    argsList.add("-classpath");
+
+                    final StringBuilder cp = new StringBuilder(bootstrapJar.getAbsolutePath()).append(ps).append(juliJar.getAbsolutePath());
+                    if (commonsLoggingJar.exists()) {
+                        cp.append(ps).append(commonsLoggingJar.getAbsolutePath());
+                    }
+                    if (additionalClasspath != null) {
+                        cp.append(ps).append(additionalClasspath);
+                    }
+                    argsList.add(cp.toString());
+
+                    argsList.add("org.apache.catalina.startup.Bootstrap");
+                }
+
+                if (cmd == null) {
+                    argsList.add(START);
+                } else {
+                    argsList.add(cmd);
+                }
+                args = argsList.toArray(new String[argsList.size()]);
+
+                if (verbose) {
+                    System.out.println(Join.join("\n", args));
+                }
+
+                // kill3UNIXDebug();
+                final ProcessBuilder pb = new ProcessBuilder(args);
+                pb.directory(home.getAbsoluteFile());
+                Process p = pb.start();
+
+                //Process p = Runtime.getRuntime().exec(args);
+                Pipe.pipeOut(p); // why would we need to redirect System.in to the process, TomEE doesn't use it
+
+                if (START.equals(cmd)) {
+                    server.set(p);
+                } else if (STOP.equals(cmd)) {
+                    waitFor(p);
+                    p = server.get();
+                    if (p != null) {
+                        waitFor(p);
+                    }
+                }
+
+                System.out.println("Started server process on port: " + port);
+
+            } catch (final Exception e) {
+                throw (RuntimeException) new OpenEJBRuntimeException("Cannot start the server.  Exception: " + e.getClass().getName() + ": " + e.getMessage()).initCause(e);
+            }
+
+            if (debug) {
+                if (!connect(port, Integer.MAX_VALUE)) {
+                    throw new OpenEJBRuntimeException("Could not connect to server: " + this.host + ":" + port);
+                }
+            } else {
+                if (!connect(port, tries)) {
+                    throw new OpenEJBRuntimeException("Could not connect to server: " + this.host + ":" + port);
+                }
+            }
+
+        } else {
+            if (verbose) {
+                System.out.println("[] FOUND STARTED SERVER");
+            }
+        }
+    }
+
+    private void waitFor(final Process p) {
+        final CountDownLatch latch = new CountDownLatch(1);
+        final Thread t = new Thread(new Runnable() {
+            @Override
+            public void run() {
+                try {
+                    p.waitFor();
+                } catch (final InterruptedException e) {
+                    //Ignore
+                }
+
+                latch.countDown();
+            }
+        }, "process-waitFor");
+
+        t.start();
+
+        try {
+            if (!latch.await(10, TimeUnit.SECONDS)) {
+                killOnExit(p);
+                throw new RuntimeException("Timeout waiting for process");
+            }
+        } catch (final InterruptedException e) {
+            killOnExit(p);
+        }
+    }
+
+    public void kill3UNIX() { // debug purpose only
+        if (System.getProperty("os.name", "unknown").toLowerCase().startsWith("windows")) {
+            return;
+        }
+
+        try {
+            final Field f = server.get().getClass().getDeclaredField("pid");
+            f.setAccessible(true);
+            final int pid = (Integer) f.get(server.get());
+            Pipe.pipe(Runtime.getRuntime().exec("kill -3 " + pid));
+        } catch (final Exception e1) {
+            e1.printStackTrace();
+        }
+    }
+
+    private File lib(final String name, final File... dirs) {
+        for (final File dir : dirs) {
+            final File[] files = dir.listFiles();
+            if (files != null) {
+                for (final File file : files) {
+                    if (!file.isFile()) {
+                        continue;
+                    }
+                    if (!file.getName().endsWith(".jar")) {
+                        continue;
+                    }
+                    if (file.getName().startsWith(name)) {
+                        return file;
+                    }
+                }
+            }
+        }
+
+        if (debug) {
+            for (final File dir : dirs) {
+                dumpLibs(dir);
+            }
+        }
+        throw new IllegalStateException("Cannot find the " + name + " jar");
+    }
+
+    // for debug purpose
+    private static void dumpLibs(final File dir) {
+        if (!dir.exists()) {
+            System.out.println("lib dir doesn't exist");
+            return;
+        }
+        final File[] files = dir.listFiles();
+        if (files != null) {
+            for (final File lib : files) {
+                System.out.println(lib.getAbsolutePath());
+            }
+        }
+    }
+
+    public Process getServer() {
+        return server.get();
+    }
+
+    private void addIfSet(final List<String> argsList, final String key) {
+        if (System.getProperties().containsKey(key)) {
+            argsList.add("-D" + key + "=" + System.getProperty(key));
+        }
+    }
+
+    private File getHome() {
+        if (home != null) {
+            return home;
+        }
+
+        final String openejbHome = System.getProperty("openejb.home");
+
+        if (openejbHome != null) {
+            home = new File(openejbHome);
+        }
+        return home;
+    }
+
+    public boolean stop() {
+        if (sendShutdown(5)) {
+            return true;
+        } else {
+            if (verbose) {
+                notSent();
+            }
+
+            return false;
+        }
+    }
+
+    private void notSent() {
+        System.out.println("Failed to send the shutdown notification - TomEE is likely shut down already");
+    }
+
+    public void forceStop() throws Exception {
+        if (sendShutdown(5)) {
+
+            // Check TomEE was effectively shut down after getting the message
+            // There can be concurrent shutdown operations (catalina shutdown hook for instance),
+            // so we have to wait here since it is important to be synchronous in this method
+            waitForServerShutdown();
+        } else {
+            if (verbose) {
+                notSent();
+            }
+        }
+    }
+
+    private void waitForServerShutdown() throws Exception {
+
+        if (verbose) {
+            System.out.print("Waiting for TomEE shutdown.");
+        }
+
+        final boolean b = disconnect(portShutdown, tries);
+
+        if (verbose) {
+            System.out.println();
+        }
+
+        if (!b) {
+            //We need to know about this
+            System.out.println("SEVERE: Failed to shutdown TomEE running on port " + portStartup + " using shutdown port: " + portShutdown);
+        }
+    }
+
+    /**
+     * Send the shutdown message to the running server
+     *
+     * @param attempts How many times to try to send the message before giving up
+     * @return True is the message was sent, else false if unable to connect after the defined number of attempts
+     */
+    private boolean sendShutdown(int attempts) {
+        Socket socket = null;
+        OutputStream stream = null;
+        try {
+            socket = new Socket(host, portShutdown);
+            stream = socket.getOutputStream();
+            final String shutdown = command + Character.toString((char) 0);
+            for (int i = 0; i < shutdown.length(); i++) {
+                stream.write(shutdown.charAt(i));
+            }
+            stream.flush();
+        } catch (final Exception e) {
+            if (attempts > 0) {
+                try {
+                    Thread.sleep(1000);
+                } catch (final InterruptedException ie) {
+                    return false;
+                }
+                return sendShutdown(--attempts);
+            } else {
+                return false;
+            }
+        } finally {
+            if (null != stream) {
+                try {
+                    stream.close();
+                } catch (final Exception e) {
+                    // Ignore
+                }
+            }
+            if (socket != null) {
+                try {
+                    socket.close();
+                } catch (final Exception e) {
+                    // Ignore
+                }
+            }
+        }
+
+        return true;
+    }
+
+    private boolean connect(final int port, int tries) {
+        if (verbose) {
+            System.out.println("[] CONNECT ATTEMPT " + (this.tries - tries) + " on port: " + port);
+        }
+
+        Socket s = null;
+        try {
+            s = new Socket();
+            s.connect(new InetSocketAddress(this.host, port), 1000);
+            s.getOutputStream().close();
+            if (verbose) {
+                System.out.println("[] CONNECTED IN " + (this.tries - tries));
+            }
+        } catch (final Exception e) {
+            if (tries < 2) {
+                if (verbose) {
+                    System.out.println("[] CONNECT ATTEMPTS FAILED ( " + (this.tries - tries) + " ATTEMPTS)");
+                }
+                return false;
+            } else {
+                try {
+                    Thread.sleep(1000);
+                } catch (final Exception e2) {
+                    e2.printStackTrace();
+                }
+                return connect(port, --tries);
+            }
+        } finally {
+            if (s != null) {
+                try {
+                    s.close();
+                } catch (final Exception ignored) {
+                    // no-op
+                }
+            }
+        }
+
+        return true;
+    }
+
+    private boolean disconnect(final int port, int tries) {
+        if (verbose) {
+            System.out.println("[] DISCONNECT ATTEMPT " + (this.tries - tries) + " on port: " + port);
+        }
+
+        Socket s = null;
+        try {
+            s = new Socket();
+            s.connect(new InetSocketAddress(this.host, port), 500);
+            s.getOutputStream().close();
+
+            if (verbose) {
+                System.out.println("[] NOT DISCONNECTED AFTER ( " + (this.tries - tries) + " ATTEMPTS)");
+            }
+
+            if (tries < 2) {
+                //Give up
+                return false;
+            } else {
+                try {
+                    Thread.sleep(1000);
+                } catch (final Exception e2) {
+                    e2.printStackTrace();
+                }
+
+                return disconnect(port, --tries);
+            }
+
+        } catch (final IOException e) {
+            //This is what we want
+        } finally {
+            if (s != null) {
+                try {
+                    s.close();
+                } catch (final Exception ignored) {
+                    // no-op
+                }
+            }
+        }
+
+        return true;
+    }
+
+    public void setAdditionalClasspath(final String additionalClasspath) {
+        this.additionalClasspath = additionalClasspath;
+    }
+
+    public void killOnExit() {
+        final Process p = this.server.get();
+        if (!serverHasAlreadyBeenStarted && kill.contains(p)) {
+            return;
+        }
+
+        killOnExit(p);
+    }
+
+    private static void killOnExit(final Process p) {
+        kill.add(p);
+    }
+
+    // Shutdown hook for processes
+    private static final List<Process> kill = new ArrayList<Process>();
+
+    static {
+        Runtime.getRuntime().addShutdownHook(new CleanUpThread());
+    }
+
+    public static class CleanUpThread extends Thread {
+        @Override
+        public void run() {
+            for (final Process server : kill) {
+                try {
+                    if (server != null) {
+                        server.destroy();
+                        server.waitFor();
+                    }
+                } catch (final Throwable e) {
+                    //Ignore
+                }
+            }
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/tomee/blob/6df9839b/maven/tomee-maven-plugin/src/main/java/org/apache/openejb/maven/plugin/AbstractTomEEMojo.java
----------------------------------------------------------------------
diff --git a/maven/tomee-maven-plugin/src/main/java/org/apache/openejb/maven/plugin/AbstractTomEEMojo.java b/maven/tomee-maven-plugin/src/main/java/org/apache/openejb/maven/plugin/AbstractTomEEMojo.java
index 9e602b3..9936bca 100644
--- a/maven/tomee-maven-plugin/src/main/java/org/apache/openejb/maven/plugin/AbstractTomEEMojo.java
+++ b/maven/tomee-maven-plugin/src/main/java/org/apache/openejb/maven/plugin/AbstractTomEEMojo.java
@@ -247,7 +247,7 @@ public abstract class AbstractTomEEMojo extends AbstractAddressMojo {
 
     @Parameter
     protected List<String> endorsedLibs;
-    
+
     @Parameter
     protected List<String> javaagents;
 
@@ -740,9 +740,9 @@ public abstract class AbstractTomEEMojo extends AbstractAddressMojo {
         if (tomeeHttpsPort != null && tomeeHttpsPort > 0 && parser.value("HTTPS", null) == null) {
             // ensure connector is not commented
             value = value.replace("<Service name=\"Catalina\">", "<Service name=\"Catalina\">\n"
-                + "    <Connector port=\"" + tomeeHttpsPort + "\" protocol=\"HTTP/1.1\" SSLEnabled=\"true\"\n" +
-                "                scheme=\"https\" secure=\"true\"\n" +
-                "                clientAuth=\"false\" sslProtocol=\"TLS\" keystoreFile=\"" + keystoreFilePath + "\" />\n");
+                    + "    <Connector port=\"" + tomeeHttpsPort + "\" protocol=\"HTTP/1.1\" SSLEnabled=\"true\"\n" +
+                    "                scheme=\"https\" secure=\"true\"\n" +
+                    "                clientAuth=\"false\" sslProtocol=\"TLS\" keystoreFile=\"" + keystoreFilePath + "\" />\n");
         }
 
         if (tomeeHttpsPort == null) {
@@ -754,12 +754,12 @@ public abstract class AbstractTomEEMojo extends AbstractAddressMojo {
         try {
             writer = new FileWriter(serverXml);
             writer.write(value
-                .replace(parser.http(), Integer.toString(this.getTomeeHttpPortChecked()))
-                .replace(parser.https(), Integer.toString(tomeeHttpsPort))
-                .replace(parser.ajp(), Integer.toString(tomeeAjpPort))
-                .replace(parser.stop(), Integer.toString(this.getTomeeShutdownPortChecked()))
-                .replace(parser.host(), tomeeHost)
-                .replace(parser.appBase(), webappDir));
+                    .replace(parser.http(), Integer.toString(this.getTomeeHttpPortChecked()))
+                    .replace(parser.https(), Integer.toString(tomeeHttpsPort))
+                    .replace(parser.ajp(), Integer.toString(tomeeAjpPort))
+                    .replace(parser.stop(), Integer.toString(this.getTomeeShutdownPortChecked()))
+                    .replace(parser.host(), tomeeHost)
+                    .replace(parser.appBase(), webappDir));
         } catch (final IOException e) {
             throw new TomEEException(e.getMessage(), e);
         } finally {
@@ -858,8 +858,8 @@ public abstract class AbstractTomEEMojo extends AbstractAddressMojo {
             server.setPortStartup(this.getTomeeHttpPortChecked());
 
             getLog().info("Running '" + getClass().getName().replace("TomEEMojo", "").toLowerCase(Locale.ENGLISH)
-                + "'. Configured TomEE in plugin is " + tomeeHost + ":" + this.getTomeeHttpPortChecked()
-                + " (plugin shutdown port is " + this.getTomeeShutdownPortChecked() + " and https port is " + tomeeHttpsPort + ")");
+                    + "'. Configured TomEE in plugin is " + tomeeHost + ":" + this.getTomeeHttpPortChecked()
+                    + " (plugin shutdown port is " + this.getTomeeShutdownPortChecked() + " and https port is " + tomeeHttpsPort + ")");
         } else {
             getLog().info("Running '" + getClass().getSimpleName().replace("TomEEMojo", "").toLowerCase(Locale.ENGLISH));
         }
@@ -890,7 +890,7 @@ public abstract class AbstractTomEEMojo extends AbstractAddressMojo {
                         break;
                     }
 
-                    if("ignore".equals(line)){
+                    if ("ignore".equals(line)) {
                         continue;
                     }
 
@@ -913,14 +913,14 @@ public abstract class AbstractTomEEMojo extends AbstractAddressMojo {
     }
 
     private synchronized int getTomeeHttpPortChecked() {
-        if(this.tomeeHttpPort <=  0){
+        if (this.tomeeHttpPort <= 0) {
             this.tomeeHttpPort = NetworkUtil.getNextAvailablePort();
         }
         return this.tomeeHttpPort;
     }
 
     private synchronized int getTomeeShutdownPortChecked() {
-        if(this.tomeeShutdownPort <=  0){
+        if (this.tomeeShutdownPort <= 0) {
             this.tomeeHttpPort = NetworkUtil.getNextAvailablePort();
         }
         return this.tomeeHttpPort;
@@ -1176,11 +1176,19 @@ public abstract class AbstractTomEEMojo extends AbstractAddressMojo {
     }
 
     protected void serverCmd(final RemoteServer server, final List<String> strings) {
-        try {
-            server.start(strings, getCmd(), checkStarted);
-        } catch (final OpenEJBRuntimeException e) {
-            getLog().warn("Failed to check or track server startup on port: " + this.getTomeeHttpPortChecked());
+
+        final Process p = this.server.getServer();
+
+        if (null == p) {
+
+            try {
+                server.start(strings, getCmd(), checkStarted);
+            } catch (final Exception e) {
+                //TODO - Optional server.destroy() call
+                getLog().warn("Failed to check or track server startup on port: " + this.getTomeeHttpPortChecked());
+            }
         }
+
     }
 
     protected void addShutdownHooks(final RemoteServer server) {
@@ -1200,16 +1208,16 @@ public abstract class AbstractTomEEMojo extends AbstractAddressMojo {
             try {
                 if ("snapshots".equals(apacheRepos) || "true".equals(apacheRepos)) {
                     remoteRepos.add(new DefaultArtifactRepository("apache", "https://repository.apache.org/content/repositories/snapshots/",
-                        new DefaultRepositoryLayout(),
-                        new ArtifactRepositoryPolicy(true, UPDATE_POLICY_DAILY, CHECKSUM_POLICY_WARN),
-                        new ArtifactRepositoryPolicy(false, UPDATE_POLICY_NEVER, CHECKSUM_POLICY_WARN)));
+                            new DefaultRepositoryLayout(),
+                            new ArtifactRepositoryPolicy(true, UPDATE_POLICY_DAILY, CHECKSUM_POLICY_WARN),
+                            new ArtifactRepositoryPolicy(false, UPDATE_POLICY_NEVER, CHECKSUM_POLICY_WARN)));
                 } else {
                     try {
                         new URI(apacheRepos); // to check it is a uri
                         remoteRepos.add(new DefaultArtifactRepository("additional-repo-tomee-mvn-plugin", apacheRepos,
-                            new DefaultRepositoryLayout(),
-                            new ArtifactRepositoryPolicy(true, UPDATE_POLICY_DAILY, CHECKSUM_POLICY_WARN),
-                            new ArtifactRepositoryPolicy(true, UPDATE_POLICY_NEVER, CHECKSUM_POLICY_WARN)));
+                                new DefaultRepositoryLayout(),
+                                new ArtifactRepositoryPolicy(true, UPDATE_POLICY_DAILY, CHECKSUM_POLICY_WARN),
+                                new ArtifactRepositoryPolicy(true, UPDATE_POLICY_NEVER, CHECKSUM_POLICY_WARN)));
                     } catch (final URISyntaxException e) {
                         // ignored, use classical repos
                     }
@@ -1223,7 +1231,7 @@ public abstract class AbstractTomEEMojo extends AbstractAddressMojo {
         }
 
         if ((tomeeClassifier != null && (tomeeClassifier.isEmpty() || tomeeClassifier.equals("ignore")))
-            || ("org.apache.openejb".equals(tomeeGroupId) && "openejb-standalone".equals(tomeeArtifactId))) {
+                || ("org.apache.openejb".equals(tomeeGroupId) && "openejb-standalone".equals(tomeeArtifactId))) {
             tomeeClassifier = null;
         }
 
@@ -1258,8 +1266,8 @@ public abstract class AbstractTomEEMojo extends AbstractAddressMojo {
                 if (!dest.exists()) {
                     final File parent = dest.getParentFile();
                     if ((!parent.exists() && !parent.mkdirs())
-                        || (!parent.canWrite() && !parent.setWritable(true))
-                        || (!parent.canRead() && !parent.setReadable(true))) {
+                            || (!parent.canWrite() && !parent.setWritable(true))
+                            || (!parent.canRead() && !parent.setReadable(true))) {
                         throw new RuntimeException("Failed to create or set permissions on: " + parent);
                     }
                 }
@@ -1316,16 +1324,16 @@ public abstract class AbstractTomEEMojo extends AbstractAddressMojo {
 
     private void ensureAppsFolderExistAndIsConfiguredByDefault(final File file) throws IOException {
         if ("openejb".equals(container.toLowerCase(Locale.ENGLISH))
-            || (file.exists()
-            && (
-            (apps != null && !apps.isEmpty())
-                || (!"pom".equals(packaging) && !"war".equals(packaging))))) { // webapps doesn't need apps folder in tomee
+                || (file.exists()
+                && (
+                (apps != null && !apps.isEmpty())
+                        || (!"pom".equals(packaging) && !"war".equals(packaging))))) { // webapps doesn't need apps folder in tomee
             final FileWriter writer = new FileWriter(file);
             final String rootTag = container.toLowerCase(Locale.ENGLISH);
             writer.write("<?xml version=\"1.0\"?>\n" +
-                "<" + rootTag + ">\n" +
-                "  <Deployments dir=\"apps\" />\n" +
-                "</" + rootTag + ">\n");
+                    "<" + rootTag + ">\n" +
+                    "  <Deployments dir=\"apps\" />\n" +
+                    "</" + rootTag + ">\n");
             writer.close();
 
             final File appsFolder = new File(catalinaBase, "apps");

http://git-wip-us.apache.org/repos/asf/tomee/blob/6df9839b/maven/tomee-maven-plugin/src/main/java/org/apache/openejb/maven/plugin/runner/ExecRunner.java
----------------------------------------------------------------------
diff --git a/maven/tomee-maven-plugin/src/main/java/org/apache/openejb/maven/plugin/runner/ExecRunner.java b/maven/tomee-maven-plugin/src/main/java/org/apache/openejb/maven/plugin/runner/ExecRunner.java
index 3677f98..e598d98 100644
--- a/maven/tomee-maven-plugin/src/main/java/org/apache/openejb/maven/plugin/runner/ExecRunner.java
+++ b/maven/tomee-maven-plugin/src/main/java/org/apache/openejb/maven/plugin/runner/ExecRunner.java
@@ -42,7 +42,7 @@ public class ExecRunner {
     public static void main(final String[] rawArgs) throws Exception {
         final String[] args;
         if (rawArgs == null || rawArgs.length == 0) {
-            args = new String[] { "run" };
+            args = new String[]{"run"};
         } else {
             args = rawArgs;
         }
@@ -65,8 +65,8 @@ public class ExecRunner {
         final File timestampFile = new File(distribOutput, "timestamp.txt");
         final boolean forceDelete = Boolean.getBoolean("tomee.runner.force-delete");
         if (forceDelete
-            || !timestampFile.exists()
-            || Long.parseLong(IO.slurp(timestampFile).replace(System.getProperty("line.separator"), "")) < Long.parseLong(config.getProperty("timestamp"))) {
+                || !timestampFile.exists()
+                || Long.parseLong(IO.slurp(timestampFile).replace(System.getProperty("line.separator"), "")) < Long.parseLong(config.getProperty("timestamp"))) {
             if (forceDelete || timestampFile.exists()) {
                 System.out.println("Deleting " + distribOutput.getAbsolutePath());
                 Files.delete(distribOutput);
@@ -80,7 +80,7 @@ public class ExecRunner {
         if (scripts != null) { // dont use filefilter to avoid dependency issue
             for (final File f : scripts) {
                 if (f.getName().endsWith(".sh") && !f.canExecute()) {
-                    if(!f.setExecutable(true, true)){
+                    if (!f.setExecutable(true, true)) {
                         System.err.println("Failed make file executable: " + f);
                     }
                 }
@@ -94,14 +94,14 @@ public class ExecRunner {
                 final String dir = cmd.substring(0, lastSlash);
                 final boolean isWin = System.getProperty("os.name").toLowerCase(Locale.ENGLISH).contains("win");
                 final String script = cmd.substring(lastSlash + 1, cmd.length() - SH_BAT_AUTO.length()).replace('/', isWin ? '\\' : '/')
-                    + (isWin ? ".bat" : ".sh");
+                        + (isWin ? ".bat" : ".sh");
                 final File scriptFile = new File(distribOutput, dir + File.separator + script);
                 if (!scriptFile.exists()) {
                     throw new IllegalArgumentException("Can't find  " + cmd);
                 }
                 cmd = scriptFile.getAbsolutePath();
                 if (cmd.endsWith(".sh")) {
-                    if(!scriptFile.setExecutable(true)){
+                    if (!scriptFile.setExecutable(true)) {
                         System.err.println("Failed make script file executable: " + scriptFile);
                     }
                 }
@@ -130,7 +130,7 @@ public class ExecRunner {
                 }
             }
 
-            final QuickServerXmlParser parser = QuickServerXmlParser.parse(new File(distribOutput,"conf/server.xml"));
+            final QuickServerXmlParser parser = QuickServerXmlParser.parse(new File(distribOutput, "conf/server.xml"));
 
             System.setProperty("openejb.home", distribOutput.getAbsolutePath());
             System.setProperty("server.shutdown.port", parser.stop());
@@ -156,8 +156,12 @@ public class ExecRunner {
             if ("run".equals(args[0])) {
                 args[0] = "start";
             }
-            server.start(jvmArgs, args[0], true);
-            server.getServer().waitFor();
+            try {
+                server.start(jvmArgs, args[0], true);
+                server.getServer().waitFor();
+            } catch (final Exception e) {
+                server.destroy();
+            }
         } else {
             // TODO: split cmd correctly to support multiple inlined segments in cmd
             if (cmd.endsWith(".bat") && !cmd.startsWith("cmd.exe")) {
@@ -178,7 +182,7 @@ public class ExecRunner {
             boolean redirectOut = false;
             try { // java >= 7
                 ProcessBuilder.class.getDeclaredMethod("inheritIO").invoke(builder);
-            } catch (final Throwable th){ // java 6
+            } catch (final Throwable th) { // java 6
                 redirectOut = true;
             }
 

http://git-wip-us.apache.org/repos/asf/tomee/blob/6df9839b/tck/tck-common/src/main/java/org/apache/openejb/tck/impl/ContainersImplTomEE.java
----------------------------------------------------------------------
diff --git a/tck/tck-common/src/main/java/org/apache/openejb/tck/impl/ContainersImplTomEE.java b/tck/tck-common/src/main/java/org/apache/openejb/tck/impl/ContainersImplTomEE.java
index 301a8d1..e4a71f5 100644
--- a/tck/tck-common/src/main/java/org/apache/openejb/tck/impl/ContainersImplTomEE.java
+++ b/tck/tck-common/src/main/java/org/apache/openejb/tck/impl/ContainersImplTomEE.java
@@ -1,164 +1,169 @@
-/*
- * 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.openejb.tck.impl;
-
-import org.apache.openejb.assembler.Deployer;
-import org.apache.openejb.assembler.classic.AppInfo;
-import org.apache.openejb.client.RemoteInitialContextFactory;
-import org.apache.openejb.config.RemoteServer;
-import org.apache.openejb.config.ValidationException;
-import org.apache.openejb.loader.Options;
-import org.apache.openejb.tck.OpenEJBTCKRuntimeException;
-import org.apache.openejb.tck.util.ServerLocal;
-import org.jboss.testharness.api.DeploymentException;
-import org.jboss.testharness.spi.Containers;
-
-import javax.naming.Context;
-import javax.naming.InitialContext;
-import java.io.File;
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.Arrays;
-import java.util.Properties;
-
-/**
- * @version $Rev$ $Date$
- */
-public class ContainersImplTomEE extends AbstractContainers implements Containers {
-    private static int count = 0;
-    private final RemoteServer server;
-    private Deployer deployer = null;
-    private Exception exception;
-    private AppInfo appInfo;
-    private File currentFile = null;
-    private final int port = ServerLocal.getPort(8080);
-
-    private Deployer lookup() {
-        final Options options = new Options(System.getProperties());
-        final Properties props = new Properties();
-        props.put(Context.INITIAL_CONTEXT_FACTORY, RemoteInitialContextFactory.class.getName());
-        props.put(Context.PROVIDER_URL, options.get(Context.PROVIDER_URL, "http://localhost:" + port + "/tomee/ejb"));
-
-        final String deployerJndi = System.getProperty("openejb.deployer.jndiname", "openejb/DeployerBusinessRemote");
-
-        try {
-            final InitialContext context = new InitialContext(props);
-            return (Deployer) context.lookup(deployerJndi);
-        } catch (final Exception e) {
-            throw new OpenEJBTCKRuntimeException(e);
-        }
-    }
-
-    public ContainersImplTomEE() {
-        System.out.println("ContainersImpl=" + ContainersImplTomEE.class.getName());
-        System.out.println("Initialized ContainersImplTomEE " + (++count));
-        server = new RemoteServer();
-        server.setPortStartup(this.port);
-    }
-
-    @Override
-    public boolean deploy(final InputStream archive, final String name) throws IOException {
-        exception = null;
-        appInfo = null;
-
-        System.out.println("Deploying " + archive + " with name " + name);
-
-        currentFile = getFile(name);
-        System.out.println(currentFile);
-        writeToFile(currentFile, archive);
-        try {
-            if (deployer == null) {
-                deployer = lookup();
-            }
-            appInfo = deployer.deploy(currentFile.getAbsolutePath());
-        } catch (final Exception ex) {
-            Exception e = ex;
-            if (e.getCause() instanceof ValidationException) {
-                e = (Exception) e.getCause();
-            }
-
-            if (name.contains(".broken.")) {
-                // Tests that contain the name '.broken.' are expected to fail deployment
-                // This is how the TCK verifies the container is doing the required error checking
-                exception = (DeploymentException) new DeploymentException("deploy failed").initCause(e);
-            } else {
-                // This on the other hand is not good ....
-                System.out.println("FIX Deployment of " + name);
-                e.printStackTrace();
-                exception = e;
-            }
-
-            return false;
-        }
-        return true;
-    }
-
-    @Override
-    public DeploymentException getDeploymentException() {
-        try {
-            return (DeploymentException) exception;
-        } catch (final Exception e) {
-            System.out.println("BADCAST");
-            return new DeploymentException("", exception);
-        }
-    }
-
-    @Override
-    public void undeploy(final String name) throws IOException {
-        if (appInfo == null) {
-            if (!(exception instanceof DeploymentException)) {
-                System.out.println("Nothing to undeploy" + name);
-            }
-            return;
-        }
-
-        System.out.println("Undeploying " + name);
-        try {
-            deployer.undeploy(appInfo.path);
-        } catch (final Exception e) {
-            e.printStackTrace();
-            throw new OpenEJBTCKRuntimeException(e);
-        }
-
-        final File toDelete;
-        if (currentFile != null && (toDelete = currentFile.getParentFile()).exists()) {
-            System.out.println("deleting " + toDelete.getAbsolutePath());
-            delete(toDelete);
-        }
-    }
-
-    protected File getFile(final String name) {
-        final File dir = new File(tmpDir, Math.random() + "");
-        if (!dir.exists() && !dir.mkdir()) {
-            throw new RuntimeException("Failed to create directory: " + dir);
-        }
-        dir.deleteOnExit();
-        return new File(dir, name);
-    }
-
-    @Override
-    public void setup() throws IOException {
-        System.out.println("Setup called");
-        server.start(Arrays.asList("-Dopenejb.classloader.forced-load=org.apache.openejb.tck"), "start", true);
-    }
-
-    @Override
-    public void cleanup() throws IOException {
-        System.out.println("Cleanup called");
-        server.destroy();
-    }
-}
+/*
+ * 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.openejb.tck.impl;
+
+import org.apache.openejb.assembler.Deployer;
+import org.apache.openejb.assembler.classic.AppInfo;
+import org.apache.openejb.client.RemoteInitialContextFactory;
+import org.apache.openejb.config.RemoteServer;
+import org.apache.openejb.config.ValidationException;
+import org.apache.openejb.loader.Options;
+import org.apache.openejb.tck.OpenEJBTCKRuntimeException;
+import org.apache.openejb.tck.util.ServerLocal;
+import org.jboss.testharness.api.DeploymentException;
+import org.jboss.testharness.spi.Containers;
+
+import javax.naming.Context;
+import javax.naming.InitialContext;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Arrays;
+import java.util.Properties;
+
+/**
+ * @version $Rev$ $Date$
+ */
+public class ContainersImplTomEE extends AbstractContainers implements Containers {
+    private static int count = 0;
+    private final RemoteServer server;
+    private Deployer deployer = null;
+    private Exception exception;
+    private AppInfo appInfo;
+    private File currentFile = null;
+    private final int port = ServerLocal.getPort(8080);
+
+    private Deployer lookup() {
+        final Options options = new Options(System.getProperties());
+        final Properties props = new Properties();
+        props.put(Context.INITIAL_CONTEXT_FACTORY, RemoteInitialContextFactory.class.getName());
+        props.put(Context.PROVIDER_URL, options.get(Context.PROVIDER_URL, "http://localhost:" + port + "/tomee/ejb"));
+
+        final String deployerJndi = System.getProperty("openejb.deployer.jndiname", "openejb/DeployerBusinessRemote");
+
+        try {
+            final InitialContext context = new InitialContext(props);
+            return (Deployer) context.lookup(deployerJndi);
+        } catch (final Exception e) {
+            throw new OpenEJBTCKRuntimeException(e);
+        }
+    }
+
+    public ContainersImplTomEE() {
+        System.out.println("ContainersImpl=" + ContainersImplTomEE.class.getName());
+        System.out.println("Initialized ContainersImplTomEE " + (++count));
+        server = new RemoteServer();
+        server.setPortStartup(this.port);
+    }
+
+    @Override
+    public boolean deploy(final InputStream archive, final String name) throws IOException {
+        exception = null;
+        appInfo = null;
+
+        System.out.println("Deploying " + archive + " with name " + name);
+
+        currentFile = getFile(name);
+        System.out.println(currentFile);
+        writeToFile(currentFile, archive);
+        try {
+            if (deployer == null) {
+                deployer = lookup();
+            }
+            appInfo = deployer.deploy(currentFile.getAbsolutePath());
+        } catch (final Exception ex) {
+            Exception e = ex;
+            if (e.getCause() instanceof ValidationException) {
+                e = (Exception) e.getCause();
+            }
+
+            if (name.contains(".broken.")) {
+                // Tests that contain the name '.broken.' are expected to fail deployment
+                // This is how the TCK verifies the container is doing the required error checking
+                exception = (DeploymentException) new DeploymentException("deploy failed").initCause(e);
+            } else {
+                // This on the other hand is not good ....
+                System.out.println("FIX Deployment of " + name);
+                e.printStackTrace();
+                exception = e;
+            }
+
+            return false;
+        }
+        return true;
+    }
+
+    @Override
+    public DeploymentException getDeploymentException() {
+        try {
+            return (DeploymentException) exception;
+        } catch (final Exception e) {
+            System.out.println("BADCAST");
+            return new DeploymentException("", exception);
+        }
+    }
+
+    @Override
+    public void undeploy(final String name) throws IOException {
+        if (appInfo == null) {
+            if (!(exception instanceof DeploymentException)) {
+                System.out.println("Nothing to undeploy" + name);
+            }
+            return;
+        }
+
+        System.out.println("Undeploying " + name);
+        try {
+            deployer.undeploy(appInfo.path);
+        } catch (final Exception e) {
+            e.printStackTrace();
+            throw new OpenEJBTCKRuntimeException(e);
+        }
+
+        final File toDelete;
+        if (currentFile != null && (toDelete = currentFile.getParentFile()).exists()) {
+            System.out.println("deleting " + toDelete.getAbsolutePath());
+            delete(toDelete);
+        }
+    }
+
+    protected File getFile(final String name) {
+        final File dir = new File(tmpDir, Math.random() + "");
+        if (!dir.exists() && !dir.mkdir()) {
+            throw new RuntimeException("Failed to create directory: " + dir);
+        }
+        dir.deleteOnExit();
+        return new File(dir, name);
+    }
+
+    @Override
+    public void setup() throws IOException {
+        System.out.println("Setup called");
+        try {
+            server.start(Arrays.asList("-Dopenejb.classloader.forced-load=org.apache.openejb.tck"), "start", true);
+        } catch (final Exception e) {
+            cleanup();
+            e.printStackTrace();
+        }
+    }
+
+    @Override
+    public void cleanup() throws IOException {
+        System.out.println("Cleanup called");
+        server.destroy();
+    }
+}


Mime
View raw message