You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@karaf.apache.org by gn...@apache.org on 2014/04/10 16:16:09 UTC

[47/59] [abbrv] [KARAF-2852] Merge wrapper/core and wrapper/command

http://git-wip-us.apache.org/repos/asf/karaf/blob/4182735c/wrapper/src/main/java/org/apache/karaf/wrapper/internal/PumpStreamHandler.java
----------------------------------------------------------------------
diff --git a/wrapper/src/main/java/org/apache/karaf/wrapper/internal/PumpStreamHandler.java b/wrapper/src/main/java/org/apache/karaf/wrapper/internal/PumpStreamHandler.java
new file mode 100644
index 0000000..8737547
--- /dev/null
+++ b/wrapper/src/main/java/org/apache/karaf/wrapper/internal/PumpStreamHandler.java
@@ -0,0 +1,246 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.karaf.wrapper.internal;
+
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.IOException;
+
+//
+// Based on Apache Ant 1.6.5
+//
+
+/**
+ * Copies standard output and error of children streams to standard output and error of the parent.
+ */
+public class PumpStreamHandler {
+
+    private final InputStream in;
+
+    private final OutputStream out;
+
+    private final OutputStream err;
+
+    private final String name;
+
+    private StreamPumper outputPump;
+
+    private StreamPumper errorPump;
+
+    private StreamPumper inputPump;
+
+    //
+    // NOTE: May want to use a ThreadPool here, 3 threads per/pair seems kinda expensive :-(
+    //
+
+    public PumpStreamHandler(final InputStream in, final OutputStream out, final OutputStream err, String name) {
+        assert in != null;
+        assert out != null;
+        assert err != null;
+        assert name != null;
+
+        this.in = in;
+        this.out = out;
+        this.err = err;
+        this.name = name;
+    }
+
+    public PumpStreamHandler(final InputStream in, final OutputStream out, final OutputStream err) {
+        this(in, out, err, "<unknown>");
+    }
+
+    public PumpStreamHandler(final OutputStream out, final OutputStream err) {
+        this(null, out, err);
+    }
+
+    public PumpStreamHandler(final OutputStream outAndErr) {
+        this(outAndErr, outAndErr);
+    }
+
+    /**
+     * Set the input stream from which to read the standard output of the child.
+     */
+    public void setChildOutputStream(final InputStream in) {
+        assert in != null;
+
+        createChildOutputPump(in, out);
+    }
+
+    /**
+     * Set the input stream from which to read the standard error of the child.
+     */
+    public void setChildErrorStream(final InputStream in) {
+        assert in != null;
+
+        if (err != null) {
+            createChildErrorPump(in, err);
+        }
+    }
+
+    /**
+     * Set the output stream by means of which input can be sent to the child.
+     */
+    public void setChildInputStream(final OutputStream out) {
+        assert out != null;
+
+        if (in != null) {
+            inputPump = createInputPump(in, out, true);
+        } else {
+            try {
+                out.close();
+            } catch (IOException e) {
+            }
+        }
+    }
+
+    /**
+     * Attach to a child streams from the given process.
+     *
+     * @param p The process to attach to.
+     */
+    public void attach(final Process p) {
+        assert p != null;
+
+        setChildInputStream(p.getOutputStream());
+        setChildOutputStream(p.getInputStream());
+        setChildErrorStream(p.getErrorStream());
+    }
+
+    /**
+     * Start pumping the streams.
+     */
+    public void start() {
+        if (outputPump != null) {
+            Thread thread = new Thread(outputPump);
+            thread.setDaemon(true);
+            thread.setName("Output pump for " + this.name);
+            thread.start();
+        }
+
+        if (errorPump != null) {
+            Thread thread = new Thread(errorPump);
+            thread.setDaemon(true);
+            thread.setName("Error pump for " + this.name);
+            thread.start();
+        }
+
+        if (inputPump != null) {
+            Thread thread = new Thread(inputPump);
+            thread.setDaemon(true);
+            thread.setName("Input pump for " + this.name);
+            thread.start();
+        }
+    }
+
+    /**
+     * Stop pumping the streams.
+     */
+    public void stop() {
+        if (outputPump != null) {
+            try {
+                outputPump.stop();
+                outputPump.waitFor();
+            } catch (InterruptedException e) {
+                // ignore
+            }
+        }
+
+        if (errorPump != null) {
+            try {
+                errorPump.stop();
+                errorPump.waitFor();
+            } catch (InterruptedException e) {
+                // ignore
+            }
+        }
+
+        if (inputPump != null) {
+            inputPump.stop();
+        }
+
+        try {
+            err.flush();
+        } catch (IOException e) {
+        }
+        try {
+            out.flush();
+        } catch (IOException e) {
+        }
+    }
+
+    /**
+     * Create the pump to handle child output.
+     */
+    protected void createChildOutputPump(final InputStream in, final OutputStream out) {
+        assert in != null;
+        assert out != null;
+
+        outputPump = createPump(in, out);
+    }
+
+    /**
+     * Create the pump to handle error output.
+     */
+    protected void createChildErrorPump(final InputStream in, final OutputStream out) {
+        assert in != null;
+        assert out != null;
+
+        errorPump = createPump(in, out);
+    }
+
+    /**
+     * Creates a stream pumper to copy the given input stream to the given output stream.
+     */
+    protected StreamPumper createPump(final InputStream in, final OutputStream out) {
+        assert in != null;
+        assert out != null;
+
+        return createPump(in, out, false);
+    }
+
+    /**
+     * Creates a stream pumper to copy the given input stream to the
+     * given output stream.
+     *
+     * @param in                 The input stream to copy from.
+     * @param out                The output stream to copy to.
+     * @param closeWhenExhausted If true close the inputstream.
+     * @return A thread object that does the pumping.
+     */
+    protected StreamPumper createPump(final InputStream in, final OutputStream out, final boolean closeWhenExhausted) {
+        assert in != null;
+        assert out != null;
+
+        StreamPumper pumper = new StreamPumper(in, out, closeWhenExhausted);
+        return pumper;
+    }
+
+    /**
+     * Creates a stream pumper to copy the given input stream to the
+     * given output stream. Used for standard input.
+     */
+    protected StreamPumper createInputPump(final InputStream in, final OutputStream out, final boolean closeWhenExhausted) {
+        assert in != null;
+        assert out != null;
+
+        StreamPumper pumper = new StreamPumper(in, out, closeWhenExhausted);
+        pumper.setAutoflush(true);
+        return pumper;
+    }
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/4182735c/wrapper/src/main/java/org/apache/karaf/wrapper/internal/StreamPumper.java
----------------------------------------------------------------------
diff --git a/wrapper/src/main/java/org/apache/karaf/wrapper/internal/StreamPumper.java b/wrapper/src/main/java/org/apache/karaf/wrapper/internal/StreamPumper.java
new file mode 100644
index 0000000..330d8fc
--- /dev/null
+++ b/wrapper/src/main/java/org/apache/karaf/wrapper/internal/StreamPumper.java
@@ -0,0 +1,195 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.karaf.wrapper.internal;
+
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.IOException;
+
+//
+// Based on Apache Ant 1.6.5
+//
+
+/**
+ * Copies all data from an input stream to an output stream.
+ */
+public class StreamPumper implements Runnable {
+
+    private InputStream in;
+
+    private OutputStream out;
+
+    private volatile boolean finish;
+
+    private volatile boolean finished;
+
+    private boolean closeWhenExhausted;
+
+    private boolean autoflush;
+
+    private Exception exception;
+
+    private int bufferSize = 128;
+
+    private boolean started;
+
+    /**
+     * Create a new stream pumper.
+     *
+     * @param in                 Input stream to read data from
+     * @param out                Output stream to write data to.
+     * @param closeWhenExhausted If true, the output stream will be closed when
+     *                           the input is exhausted.
+     */
+    public StreamPumper(final InputStream in, final OutputStream out, final boolean closeWhenExhausted) {
+        assert in != null;
+        assert out != null;
+
+        this.in = in;
+        this.out = out;
+        this.closeWhenExhausted = closeWhenExhausted;
+    }
+
+    /**
+     * Create a new stream pumper.
+     *
+     * @param in  Input stream to read data from
+     * @param out Output stream to write data to.
+     */
+    public StreamPumper(final InputStream in, final OutputStream out) {
+        this(in, out, false);
+    }
+
+    /**
+     * Set whether data should be flushed through to the output stream.
+     *
+     * @param autoflush If true, push through data; if false, let it be buffered
+     */
+    public void setAutoflush(boolean autoflush) {
+        this.autoflush = autoflush;
+    }
+
+    /**
+     * Copies data from the input stream to the output stream.
+     * <p/>
+     * Terminates as soon as the input stream is closed or an error occurs.
+     */
+    public void run() {
+        synchronized (this) {
+            started = true;
+        }
+        finished = false;
+        finish = false;
+
+        final byte[] buf = new byte[bufferSize];
+
+        int length;
+        try {
+            while ((length = in.read(buf)) > 0 && !finish) {
+                out.write(buf, 0, length);
+                if (autoflush) {
+                    out.flush();
+                }
+            }
+            out.flush();
+        } catch (Exception e) {
+            synchronized (this) {
+                exception = e;
+            }
+        } finally {
+            if (closeWhenExhausted) {
+                try {
+                    out.close();
+                } catch (IOException e) {
+                }
+            }
+            finished = true;
+
+            synchronized (this) {
+                notifyAll();
+            }
+        }
+    }
+
+    /**
+     * Tells whether the end of the stream has been reached.
+     *
+     * @return true     If the stream has been exhausted.
+     */
+    public boolean isFinished() {
+        return finished;
+    }
+
+    /**
+     * This method blocks until the stream pumper finishes.
+     *
+     * @see #isFinished()
+     */
+    public synchronized void waitFor() throws InterruptedException {
+        while (!isFinished()) {
+            wait();
+        }
+    }
+
+    /**
+     * Set the size in bytes of the read buffer.
+     *
+     * @param bufferSize the buffer size to use.
+     * @throws IllegalStateException if the StreamPumper is already running.
+     */
+    public synchronized void setBufferSize(final int bufferSize) {
+        if (started) {
+            throw new IllegalStateException("Cannot set buffer size on a running StreamPumper");
+        }
+
+        this.bufferSize = bufferSize;
+    }
+
+    /**
+     * Get the size in bytes of the read buffer.
+     *
+     * @return The size of the read buffer.
+     */
+    public synchronized int getBufferSize() {
+        return bufferSize;
+    }
+
+    /**
+     * Get the exception encountered, if any.
+     *
+     * @return The Exception encountered; or null if there was none.
+     */
+    public synchronized Exception getException() {
+        return exception;
+    }
+
+    /**
+     * Stop the pumper as soon as possible.
+     * <p/>
+     * Note that it may continue to block on the input stream
+     * but it will really stop the thread as soon as it gets EOF
+     * or any byte, and it will be marked as finished.
+     */
+    public synchronized void stop() {
+        finish = true;
+
+        notifyAll();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/4182735c/wrapper/src/main/java/org/apache/karaf/wrapper/internal/WrapperServiceImpl.java
----------------------------------------------------------------------
diff --git a/wrapper/src/main/java/org/apache/karaf/wrapper/internal/WrapperServiceImpl.java b/wrapper/src/main/java/org/apache/karaf/wrapper/internal/WrapperServiceImpl.java
new file mode 100644
index 0000000..ad4aa4a
--- /dev/null
+++ b/wrapper/src/main/java/org/apache/karaf/wrapper/internal/WrapperServiceImpl.java
@@ -0,0 +1,450 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.karaf.wrapper.internal;
+
+import org.apache.karaf.wrapper.WrapperService;
+import org.fusesource.jansi.Ansi;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.*;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Scanner;
+import java.util.jar.JarOutputStream;
+import java.util.zip.ZipEntry;
+
+/**
+ * Default implementation of the wrapper service.
+ */
+public class WrapperServiceImpl implements WrapperService {
+
+    private final static Logger LOGGER = LoggerFactory.getLogger(WrapperServiceImpl.class);
+
+    public void install() throws Exception {
+        install("karaf", "karaf", "", "AUTO_START");
+    }
+
+    public File[] install(String name, String displayName, String description, String startType) throws Exception {
+
+        File base = new File(System.getProperty("karaf.base"));
+        File etc = new File(System.getProperty("karaf.etc"));
+        File bin = new File(base, "bin");
+        File lib = new File(base, "lib");
+
+        if (name == null) {
+            name = base.getName();
+        }
+
+        HashMap<String, String> props = new HashMap<String, String>();
+        props.put("${java.home}", System.getenv("JAVA_HOME"));
+        props.put("${karaf.home}", System.getProperty("karaf.home"));
+        props.put("${karaf.base}", base.getPath());
+        props.put("${karaf.data}", System.getProperty("karaf.data"));
+        props.put("${karaf.etc}", System.getProperty("karaf.etc"));
+        props.put("${name}", name);
+        props.put("${displayName}", displayName);
+        props.put("${description}", description);
+        props.put("${startType}", startType);
+
+        String os = System.getProperty("os.name", "Unknown");
+        File serviceFile = null;
+        File wrapperConf = null;
+        if (os.startsWith("Win")) {
+            String arch = System.getProperty("os.arch");
+            if (arch.equalsIgnoreCase("amd64") || arch.equalsIgnoreCase("x86_64")) {
+                mkdir(bin);
+
+                copyResourceTo(new File(bin, name + "-wrapper.exe"), "windows64/karaf-wrapper.exe", false);
+
+                serviceFile = new File(bin, name + "-service.bat");
+                wrapperConf = new File(etc, name + "-wrapper.conf");
+
+                copyFilteredResourceTo(wrapperConf, "windows64/karaf-wrapper.conf", props);
+                copyFilteredResourceTo(serviceFile, "windows64/karaf-service.bat", props);
+
+                mkdir(lib);
+                copyResourceTo(new File(lib, "wrapper.dll"), "windows64/wrapper.dll", false);
+            } else {
+                mkdir(bin);
+
+                copyResourceTo(new File(bin, name + "-wrapper.exe"), "windows/karaf-wrapper.exe", false);
+
+                serviceFile = new File(bin, name + "-service.bat");
+                wrapperConf = new File(etc, name + "-wrapper.conf");
+
+                copyFilteredResourceTo(wrapperConf, "windows/karaf-wrapper.conf", props);
+                copyFilteredResourceTo(serviceFile, "windows/karaf-service.bat", props);
+
+                mkdir(lib);
+                copyResourceTo(new File(lib, "wrapper.dll"), "windows/wrapper.dll", false);
+            }
+        } else if (os.startsWith("Mac OS X")) {
+            mkdir(bin);
+
+            File file = new File(bin, name + "-wrapper");
+            copyResourceTo(file, "macosx/karaf-wrapper", false);
+            chmod(file, "a+x");
+
+            serviceFile = new File(bin, name + "-service");
+            copyFilteredResourceTo(serviceFile, "unix/karaf-service", props);
+            chmod(serviceFile, "a+x");
+
+            wrapperConf = new File(etc, name + "-wrapper.conf");
+            copyFilteredResourceTo(wrapperConf, "unix/karaf-wrapper.conf", props);
+
+            File plistConf = new File(bin, "org.apache.karaf."+ name + ".plist");
+            copyFilteredResourceTo(plistConf, "macosx/org.apache.karaf.KARAF.plist", props);
+            
+            mkdir(lib);
+
+            copyResourceTo(new File(lib, "libwrapper.jnilib"), "macosx/libwrapper.jnilib", false);
+        } else if (os.startsWith("Linux")) {
+            String arch = System.getProperty("os.arch");
+            if (arch.equalsIgnoreCase("amd64") || arch.equalsIgnoreCase("x86_64")) {
+                mkdir(bin);
+
+                File file = new File(bin, name + "-wrapper");
+                copyResourceTo(file, "linux64/karaf-wrapper", false);
+                chmod(file, "a+x");
+
+                serviceFile = new File(bin, name + "-service");
+                copyFilteredResourceTo(serviceFile, "unix/karaf-service", props);
+                chmod(serviceFile, "a+x");
+
+                wrapperConf = new File(etc, name + "-wrapper.conf");
+                copyFilteredResourceTo(wrapperConf, "unix/karaf-wrapper.conf", props);
+
+                mkdir(lib);
+                copyResourceTo(new File(lib, "libwrapper.so"), "linux64/libwrapper.so", false);
+            } else {
+                mkdir(bin);
+
+                File file = new File(bin, name + "-wrapper");
+                copyResourceTo(file, "linux/karaf-wrapper", false);
+                chmod(file, "a+x");
+
+                serviceFile = new File(bin, name + "-service");
+                copyFilteredResourceTo(serviceFile, "unix/karaf-service", props);
+                chmod(serviceFile, "a+x");
+
+                wrapperConf = new File(etc, name + "-wrapper.conf");
+                copyFilteredResourceTo(wrapperConf, "unix/karaf-wrapper.conf", props);
+
+                mkdir(lib);
+                copyResourceTo(new File(lib, "libwrapper.so"), "linux/libwrapper.so", false);
+            }
+        } else if (os.startsWith("AIX")) {
+            String arch = System.getProperty("os.arch");
+            if (arch.equalsIgnoreCase("ppc64")) {
+                mkdir(bin);
+
+                File file = new File(bin, name + "-wrapper");
+                copyResourceTo(file, "aix/ppc64/karaf-wrapper", false);
+                chmod(file, "a+x");
+
+                serviceFile = new File(bin, name + "-service");
+                copyFilteredResourceTo(serviceFile, "unix/karaf-service", props);
+                chmod(serviceFile, "a+x");
+
+                wrapperConf = new File(etc, name + "-wrapper.conf");
+                copyFilteredResourceTo(wrapperConf, "unix/karaf-wrapper.conf", props);
+
+                mkdir(lib);
+                copyResourceTo(new File(lib, "libwrapper.a"), "aix/ppc64/libwrapper.a", false);
+            } else {
+                mkdir(bin);
+
+                File file = new File(bin, name + "-wrapper");
+                copyResourceTo(file, "aix/ppc32/karaf-wrapper", false);
+                chmod(file, "a+x");
+
+                serviceFile = new File(bin, name + "-service");
+                copyFilteredResourceTo(serviceFile, "unix/karaf-service", props);
+                chmod(serviceFile, "a+x");
+
+                wrapperConf = new File(etc, name + "-wrapper.conf");
+                copyFilteredResourceTo(wrapperConf, "unix/karaf-wrapper.conf", props);
+
+                mkdir(lib);
+                copyResourceTo(new File(lib, "libwrapper.a"), "aix/ppc32/libwrapper.a", false);
+            }
+        } else if (os.startsWith("Solaris") || os.startsWith("SunOS")) {
+            String arch = System.getProperty("os.arch");
+            if (arch.equalsIgnoreCase("sparc")) {
+                mkdir(bin);
+
+                File file = new File(bin, name + "-wrapper");
+                copyResourceTo(file, "solaris/sparc64/karaf-wrapper", false);
+                chmod(file, "a+x");
+
+                serviceFile = new File(bin, name + "-service");
+                copyFilteredResourceTo(serviceFile, "unix/karaf-service", props);
+                chmod(serviceFile, "a+x");
+
+                wrapperConf = new File(etc, name + "-wrapper.conf");
+                copyFilteredResourceTo(wrapperConf, "unix/karaf-wrapper.conf", props);
+
+                mkdir(lib);
+                copyResourceTo(new File(lib, "libwrapper.so"), "solaris/sparc64/libwrapper.so", false);
+            } else if (arch.equalsIgnoreCase("x86")) {
+                mkdir(bin);
+
+                File file = new File(bin, name + "-wrapper");
+                copyResourceTo(file, "solaris/x86/karaf-wrapper", false);
+                chmod(file, "a+x");
+
+                serviceFile = new File(bin, name + "-service");
+                copyFilteredResourceTo(serviceFile, "unix/karaf-service", props);
+                chmod(serviceFile, "a+x");
+
+                wrapperConf = new File(etc, name + "-wrapper.conf");
+                copyFilteredResourceTo(wrapperConf, "unix/karaf-wrapper.conf", props);
+
+                mkdir(lib);
+                copyResourceTo(new File(lib, "libwrapper.so"), "solaris/x86/libwrapper.so", false);
+            } else if (arch.equalsIgnoreCase("x86_64")) {
+                mkdir(bin);
+
+                File file = new File(bin, name + "-wrapper");
+                copyResourceTo(file, "solaris/x86_64/karaf-wrapper", false);
+                chmod(file, "a+x");
+
+                serviceFile = new File(bin, name + "-service");
+                copyFilteredResourceTo(serviceFile, "unix/karaf-service", props);
+                chmod(serviceFile, "a+x");
+
+                wrapperConf = new File(etc, name + "-wrapper.conf");
+                copyFilteredResourceTo(wrapperConf, "unix/karaf-wrapper.conf", props);
+
+                mkdir(lib);
+                copyResourceTo(new File(lib, "libwrapper.so"), "solaris/x86_64/libwrapper.so", false);
+            } else {
+                mkdir(bin);
+
+                File file = new File(bin, name + "-wrapper");
+                copyResourceTo(file, "solaris/sparc32/karaf-wrapper", false);
+                chmod(file, "a+x");
+
+                serviceFile = new File(bin, name + "-service");
+                copyFilteredResourceTo(serviceFile, "unix/karaf-service", props);
+                chmod(serviceFile, "a+x");
+
+                wrapperConf = new File(etc, name + "-wrapper.conf");
+                copyFilteredResourceTo(wrapperConf, "unix/karaf-wrapper.conf", props);
+
+                mkdir(lib);
+                copyResourceTo(new File(lib, "libwrapper.so"), "solaris/sparc32/libwrapper.so", false);
+            }
+        } else if (os.startsWith("HP-UX") || os.startsWith("HPUX")) {
+            mkdir(bin);
+
+            File file = new File(bin, name + "-wrapper");
+            copyResourceTo(file, "hpux/parisc64/karaf-wrapper", false);
+            chmod(file, "a+x");
+
+            serviceFile = new File(bin, name + "-service");
+            copyFilteredResourceTo(serviceFile, "unix/karaf-service", props);
+            chmod(serviceFile, "a+x");
+
+            wrapperConf = new File(etc, name + "-wrapper.conf");
+            copyFilteredResourceTo(wrapperConf, "unix/karaf-wrapper.conf", props);
+
+            mkdir(lib);
+            copyResourceTo(new File(lib, "libwrapper.sl"), "hpux/parisc64/libwrapper.sl", false);
+        } else {
+            throw new IllegalStateException("Your operating system '" + os + "' is not currently supported.");
+        }
+
+        // install the wrapper jar to the lib directory
+        mkdir(lib);
+        copyResourceTo(new File(lib, "karaf-wrapper.jar"), "all/karaf-wrapper.jar", false);
+        mkdir(etc);
+
+        createJar(new File(lib, "karaf-wrapper-main.jar"), "org/apache/karaf/wrapper/internal/Main.class");
+
+        File[] wrapperPaths = new File[2];
+        wrapperPaths[0] = wrapperConf;
+        wrapperPaths[1] = serviceFile;
+
+        return wrapperPaths;
+    }
+
+    private void mkdir(File file) {
+        if (!file.exists()) {
+            LOGGER.info("Creating missing directory: {}", file.getPath());
+            System.out.println(Ansi.ansi().a("Creating missing directory: ")
+                    .a(Ansi.Attribute.INTENSITY_BOLD).a(file.getPath()).a(Ansi.Attribute.RESET).toString());
+            file.mkdirs();
+        }
+    }
+
+    private void copyResourceTo(File outFile, String resource, boolean text) throws Exception {
+        if (!outFile.exists()) {
+            LOGGER.info("Creating file: {}", outFile.getPath());
+            System.out.println(Ansi.ansi().a("Creating file: ")
+                    .a(Ansi.Attribute.INTENSITY_BOLD).a(outFile.getPath()).a(Ansi.Attribute.RESET).toString());
+            InputStream is = WrapperServiceImpl.class.getResourceAsStream(resource);
+            if (is == null) {
+                throw new IllegalArgumentException("Resource " + resource + " doesn't exist");
+            }
+            try {
+                if (text) {
+                    // read it line at a time so what we can use the platform line ending when we write it out
+                    PrintStream out = new PrintStream(new FileOutputStream(outFile));
+                    try {
+                        Scanner scanner = new Scanner(is);
+                        while (scanner.hasNextLine()) {
+                            String line = scanner.nextLine();
+                            LOGGER.info("writing: {}", line);
+                            out.println(line);
+                        }
+                    } finally {
+                        safeClose(out);
+                    }
+                } else {
+                    // binary resource so just write it out the way it came in
+                    FileOutputStream out = new FileOutputStream(outFile);
+                    try {
+                        int c = 0;
+                        while ((c = is.read()) >= 0) {
+                            out.write(c);
+                        }
+                    } finally {
+                        safeClose(out);
+                    }
+                }
+            } finally {
+                safeClose(is);
+            }
+        } else {
+            LOGGER.warn("File already exists. Move it out of the way if you wish to recreate it: {}", outFile.getPath());
+            System.out.println(Ansi.ansi()
+                    .fg(Ansi.Color.RED).a("File already exists").a(Ansi.Attribute.RESET)
+                    .a(". Move it out of the way if you wish to recreate it: ").a(outFile.getPath()).toString());
+        }
+    }
+
+    private void copyFilteredResourceTo(File outFile, String resource, HashMap<String, String> props) throws Exception {
+        if (!outFile.exists()) {
+            LOGGER.info("Creating file: {}", outFile.getPath());
+            System.out.println(Ansi.ansi().a("Creating file: ")
+                    .a(Ansi.Attribute.INTENSITY_BOLD).a(outFile.getPath()).a(Ansi.Attribute.RESET).toString());
+            InputStream is = WrapperServiceImpl.class.getResourceAsStream(resource);
+            if (is == null) {
+                throw new IllegalArgumentException("Resource " + resource + " doesn't exist");
+            }
+            try {
+                // read it line at a time so that we can use the platform line ending when we write it out
+                PrintStream out = new PrintStream(new FileOutputStream(outFile));
+                try {
+                    Scanner scanner = new Scanner(is);
+                    while (scanner.hasNextLine()) {
+                        String line = scanner.nextLine();
+                        line = filter(line, props);
+                        out.println(line);
+                    }
+                } finally {
+                    safeClose(out);
+                }
+            } finally {
+                safeClose(is);
+            }
+        } else {
+            LOGGER.warn("File already exists. Move it out of the way if you wish to recreate it: {}", outFile.getPath());
+            System.out.println(Ansi.ansi()
+                    .fg(Ansi.Color.RED).a("File already exists").a(Ansi.Attribute.RESET)
+                    .a(". Move it out of the way if you wish to recreate it: ").a(outFile.getPath()).toString());
+        }
+    }
+
+    private void safeClose(InputStream is) throws IOException {
+        if (is == null)
+            return;
+        try {
+            is.close();
+        } catch (Throwable ignore) {
+            // nothing to do
+        }
+    }
+
+    private void safeClose(OutputStream is) throws IOException {
+        if (is == null)
+            return;
+        try {
+            is.close();
+        } catch (Throwable ignore) {
+            // nothing to do
+        }
+    }
+
+    private String filter(String line, HashMap<String, String> props) {
+        for (Map.Entry<String, String> i : props.entrySet()) {
+            int p1 = line.indexOf(i.getKey());
+            if (p1 >= 0) {
+                String l1 = line.substring(0, p1);
+                String l2 = line.substring(p1 + i.getKey().length());
+                line = l1 + i.getValue() + l2;
+            }
+        }
+        return line;
+    }
+
+    private int chmod(File serviceFile, String mode) throws Exception {
+        ProcessBuilder builder = new ProcessBuilder();
+        builder.command("chmod", mode, serviceFile.getCanonicalPath());
+        Process p = builder.start();
+
+        PumpStreamHandler handler = new PumpStreamHandler(System.in, System.out, System.err);
+        handler.attach(p);
+        handler.start();
+        int status = p.waitFor();
+        handler.stop();
+        return status;
+    }
+
+    private void createJar(File outFile, String resource) throws Exception {
+        if (!outFile.exists()) {
+            LOGGER.info("Creating file: {}", outFile.getPath());
+            System.out.println(Ansi.ansi().a("Creating file: ")
+                    .a(Ansi.Attribute.INTENSITY_BOLD).a(outFile.getPath()).a(Ansi.Attribute.RESET).toString());
+            InputStream is = getClass().getClassLoader().getResourceAsStream(resource);
+            if (is == null) {
+                throw new IllegalStateException("Resource " + resource + " not found!");
+            }
+            try {
+                JarOutputStream jar = new JarOutputStream(new FileOutputStream(outFile));
+                int idx = resource.indexOf('/');
+                while (idx > 0) {
+                    jar.putNextEntry(new ZipEntry(resource.substring(0, idx)));
+                    jar.closeEntry();
+                    idx = resource.indexOf('/', idx + 1);
+                }
+                jar.putNextEntry(new ZipEntry(resource));
+                int c;
+                while ((c = is.read()) >= 0) {
+                    jar.write(c);
+                }
+                jar.closeEntry();
+                jar.close();
+            } finally {
+                safeClose(is);
+            }
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/4182735c/wrapper/src/main/java/org/apache/karaf/wrapper/internal/osgi/Activator.java
----------------------------------------------------------------------
diff --git a/wrapper/src/main/java/org/apache/karaf/wrapper/internal/osgi/Activator.java b/wrapper/src/main/java/org/apache/karaf/wrapper/internal/osgi/Activator.java
new file mode 100644
index 0000000..0cb8242
--- /dev/null
+++ b/wrapper/src/main/java/org/apache/karaf/wrapper/internal/osgi/Activator.java
@@ -0,0 +1,36 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.karaf.wrapper.internal.osgi;
+
+import org.apache.karaf.util.tracker.BaseActivator;
+import org.apache.karaf.wrapper.WrapperService;
+import org.apache.karaf.wrapper.internal.WrapperServiceImpl;
+import org.apache.karaf.wrapper.management.internal.WrapperMBeanImpl;
+
+public class Activator extends BaseActivator {
+
+    @Override
+    protected void doStart() throws Exception {
+        WrapperService wrapperService = new WrapperServiceImpl();
+        register(WrapperService.class, wrapperService);
+
+        WrapperMBeanImpl wrapperMBean = new WrapperMBeanImpl();
+        wrapperMBean.setWrapperService(wrapperService);
+        registerMBean(wrapperMBean, "type=wrapper");
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/4182735c/wrapper/src/main/java/org/apache/karaf/wrapper/management/WrapperMBean.java
----------------------------------------------------------------------
diff --git a/wrapper/src/main/java/org/apache/karaf/wrapper/management/WrapperMBean.java b/wrapper/src/main/java/org/apache/karaf/wrapper/management/WrapperMBean.java
new file mode 100644
index 0000000..937bfe2
--- /dev/null
+++ b/wrapper/src/main/java/org/apache/karaf/wrapper/management/WrapperMBean.java
@@ -0,0 +1,46 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.karaf.wrapper.management;
+
+import javax.management.MBeanException;
+import java.io.File;
+
+/**
+ * Describe the WrapperMBean.
+ */
+public interface WrapperMBean {
+
+    /**
+     * Install the service wrapper.
+     *
+     * @throws MBeanException in case of installation failure.
+     */
+    void install() throws MBeanException;
+
+    /**
+     * Install the service wrapper.
+     *
+     * @param name the service name.
+     * @param displayName the service display name.
+     * @param description the service description.
+     * @param startType the start type.
+     * @return the wrapper configuration (index 0) and service files (index 1).
+     * @throws MBeanException in case of installation failure.
+     */
+    File[] install(String name, String displayName, String description, String startType) throws MBeanException;
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/4182735c/wrapper/src/main/java/org/apache/karaf/wrapper/management/internal/WrapperMBeanImpl.java
----------------------------------------------------------------------
diff --git a/wrapper/src/main/java/org/apache/karaf/wrapper/management/internal/WrapperMBeanImpl.java b/wrapper/src/main/java/org/apache/karaf/wrapper/management/internal/WrapperMBeanImpl.java
new file mode 100644
index 0000000..1523015
--- /dev/null
+++ b/wrapper/src/main/java/org/apache/karaf/wrapper/management/internal/WrapperMBeanImpl.java
@@ -0,0 +1,62 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.karaf.wrapper.management.internal;
+
+import org.apache.karaf.wrapper.WrapperService;
+import org.apache.karaf.wrapper.management.WrapperMBean;
+
+import javax.management.MBeanException;
+import javax.management.NotCompliantMBeanException;
+import javax.management.StandardMBean;
+import java.io.File;
+
+/**
+ * Implementation of the wrapper MBean.
+ */
+public class WrapperMBeanImpl extends StandardMBean implements WrapperMBean {
+
+    private WrapperService wrapperService;
+
+    public WrapperMBeanImpl() throws NotCompliantMBeanException {
+        super(WrapperMBean.class);
+    }
+
+    public void setWrapperService(WrapperService wrapperService) {
+        this.wrapperService = wrapperService;
+    }
+
+    public WrapperService getWrapperService() {
+        return this.wrapperService;
+    }
+
+    public void install() throws MBeanException {
+        try {
+            wrapperService.install();
+        } catch (Exception e) {
+            throw new MBeanException(null, e.getMessage());
+        }
+    }
+
+    public File[] install(String name, String displayName, String description, String startType) throws MBeanException {
+        try {
+            return wrapperService.install(name, displayName, description, startType);
+        } catch (Exception e) {
+            throw new MBeanException(null, e.getMessage());
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/4182735c/wrapper/src/main/resources/META-INF/services/org/apache/karaf/shell/commands
----------------------------------------------------------------------
diff --git a/wrapper/src/main/resources/META-INF/services/org/apache/karaf/shell/commands b/wrapper/src/main/resources/META-INF/services/org/apache/karaf/shell/commands
new file mode 100644
index 0000000..73b329d
--- /dev/null
+++ b/wrapper/src/main/resources/META-INF/services/org/apache/karaf/shell/commands
@@ -0,0 +1,18 @@
+##---------------------------------------------------------------------------
+##  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.
+##---------------------------------------------------------------------------
+org.apache.karaf.wrapper.internal.WrapperServiceImpl
+org.apache.karaf.wrapper.commands.Install
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/karaf/blob/4182735c/wrapper/src/main/resources/OSGI-INF/bundle.info
----------------------------------------------------------------------
diff --git a/wrapper/src/main/resources/OSGI-INF/bundle.info b/wrapper/src/main/resources/OSGI-INF/bundle.info
new file mode 100644
index 0000000..8462cc5
--- /dev/null
+++ b/wrapper/src/main/resources/OSGI-INF/bundle.info
@@ -0,0 +1,16 @@
+h1. Synopsis
+
+${project.name}
+
+${project.description}
+
+Maven URL:
+[mvn:${project.groupId}/${project.artifactId}/${project.version}]
+
+h1. Description
+
+This bundle provides support of the service wrapper, which allows for starting/stopping Karaf as a system service.
+
+h1. See also
+
+Service Wrapper - section of the Karaf User Guide

http://git-wip-us.apache.org/repos/asf/karaf/blob/4182735c/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/aix/ppc32/karaf-wrapper
----------------------------------------------------------------------
diff --git a/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/aix/ppc32/karaf-wrapper b/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/aix/ppc32/karaf-wrapper
new file mode 100755
index 0000000..5215c2e
Binary files /dev/null and b/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/aix/ppc32/karaf-wrapper differ

http://git-wip-us.apache.org/repos/asf/karaf/blob/4182735c/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/aix/ppc32/libwrapper.a
----------------------------------------------------------------------
diff --git a/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/aix/ppc32/libwrapper.a b/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/aix/ppc32/libwrapper.a
new file mode 100755
index 0000000..4bcc342
Binary files /dev/null and b/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/aix/ppc32/libwrapper.a differ

http://git-wip-us.apache.org/repos/asf/karaf/blob/4182735c/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/aix/ppc64/karaf-wrapper
----------------------------------------------------------------------
diff --git a/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/aix/ppc64/karaf-wrapper b/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/aix/ppc64/karaf-wrapper
new file mode 100755
index 0000000..6ba0351
Binary files /dev/null and b/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/aix/ppc64/karaf-wrapper differ

http://git-wip-us.apache.org/repos/asf/karaf/blob/4182735c/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/aix/ppc64/libwrapper.a
----------------------------------------------------------------------
diff --git a/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/aix/ppc64/libwrapper.a b/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/aix/ppc64/libwrapper.a
new file mode 100755
index 0000000..b569e3f
Binary files /dev/null and b/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/aix/ppc64/libwrapper.a differ

http://git-wip-us.apache.org/repos/asf/karaf/blob/4182735c/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/all/karaf-wrapper.jar
----------------------------------------------------------------------
diff --git a/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/all/karaf-wrapper.jar b/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/all/karaf-wrapper.jar
new file mode 100644
index 0000000..4db355b
Binary files /dev/null and b/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/all/karaf-wrapper.jar differ

http://git-wip-us.apache.org/repos/asf/karaf/blob/4182735c/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/hpux/parisc64/karaf-wrapper
----------------------------------------------------------------------
diff --git a/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/hpux/parisc64/karaf-wrapper b/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/hpux/parisc64/karaf-wrapper
new file mode 100755
index 0000000..ad883d7
Binary files /dev/null and b/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/hpux/parisc64/karaf-wrapper differ

http://git-wip-us.apache.org/repos/asf/karaf/blob/4182735c/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/hpux/parisc64/libwrapper.sl
----------------------------------------------------------------------
diff --git a/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/hpux/parisc64/libwrapper.sl b/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/hpux/parisc64/libwrapper.sl
new file mode 100755
index 0000000..08adc52
Binary files /dev/null and b/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/hpux/parisc64/libwrapper.sl differ

http://git-wip-us.apache.org/repos/asf/karaf/blob/4182735c/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/linux/karaf-wrapper
----------------------------------------------------------------------
diff --git a/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/linux/karaf-wrapper b/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/linux/karaf-wrapper
new file mode 100644
index 0000000..7e00645
Binary files /dev/null and b/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/linux/karaf-wrapper differ

http://git-wip-us.apache.org/repos/asf/karaf/blob/4182735c/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/linux/libwrapper.so
----------------------------------------------------------------------
diff --git a/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/linux/libwrapper.so b/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/linux/libwrapper.so
new file mode 100644
index 0000000..2cc4ab3
Binary files /dev/null and b/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/linux/libwrapper.so differ

http://git-wip-us.apache.org/repos/asf/karaf/blob/4182735c/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/linux64/karaf-wrapper
----------------------------------------------------------------------
diff --git a/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/linux64/karaf-wrapper b/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/linux64/karaf-wrapper
new file mode 100644
index 0000000..3128b95
Binary files /dev/null and b/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/linux64/karaf-wrapper differ

http://git-wip-us.apache.org/repos/asf/karaf/blob/4182735c/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/linux64/libwrapper.so
----------------------------------------------------------------------
diff --git a/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/linux64/libwrapper.so b/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/linux64/libwrapper.so
new file mode 100644
index 0000000..24197bf
Binary files /dev/null and b/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/linux64/libwrapper.so differ

http://git-wip-us.apache.org/repos/asf/karaf/blob/4182735c/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/macosx/karaf-wrapper
----------------------------------------------------------------------
diff --git a/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/macosx/karaf-wrapper b/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/macosx/karaf-wrapper
new file mode 100644
index 0000000..0165db0
Binary files /dev/null and b/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/macosx/karaf-wrapper differ

http://git-wip-us.apache.org/repos/asf/karaf/blob/4182735c/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/macosx/libwrapper.jnilib
----------------------------------------------------------------------
diff --git a/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/macosx/libwrapper.jnilib b/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/macosx/libwrapper.jnilib
new file mode 100644
index 0000000..6356705
Binary files /dev/null and b/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/macosx/libwrapper.jnilib differ

http://git-wip-us.apache.org/repos/asf/karaf/blob/4182735c/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/macosx/org.apache.karaf.KARAF.plist
----------------------------------------------------------------------
diff --git a/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/macosx/org.apache.karaf.KARAF.plist b/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/macosx/org.apache.karaf.KARAF.plist
new file mode 100644
index 0000000..1c18918
--- /dev/null
+++ b/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/macosx/org.apache.karaf.KARAF.plist
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    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.
+    -->
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>ProcessType</key>
+	<string>Background</string>
+	<key>KeepAlive</key>
+	<false/>
+	<key>Label</key>
+	<string>org.apache.karaf.KARAF</string>
+	<key>ProgramArguments</key>
+	<array>
+		<!-- path to your KARAF-service wrapper -->
+		<string>${karaf.home}/bin/${name}-service</string>
+		<string>console</string>
+	</array>
+	<key>RunAtLoad</key>
+	<true/>
+</dict>
+</plist>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/karaf/blob/4182735c/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/solaris/sparc32/karaf-wrapper
----------------------------------------------------------------------
diff --git a/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/solaris/sparc32/karaf-wrapper b/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/solaris/sparc32/karaf-wrapper
new file mode 100755
index 0000000..7cac208
Binary files /dev/null and b/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/solaris/sparc32/karaf-wrapper differ

http://git-wip-us.apache.org/repos/asf/karaf/blob/4182735c/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/solaris/sparc32/libwrapper.so
----------------------------------------------------------------------
diff --git a/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/solaris/sparc32/libwrapper.so b/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/solaris/sparc32/libwrapper.so
new file mode 100755
index 0000000..4093262
Binary files /dev/null and b/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/solaris/sparc32/libwrapper.so differ

http://git-wip-us.apache.org/repos/asf/karaf/blob/4182735c/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/solaris/sparc64/karaf-wrapper
----------------------------------------------------------------------
diff --git a/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/solaris/sparc64/karaf-wrapper b/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/solaris/sparc64/karaf-wrapper
new file mode 100755
index 0000000..91257c6
Binary files /dev/null and b/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/solaris/sparc64/karaf-wrapper differ

http://git-wip-us.apache.org/repos/asf/karaf/blob/4182735c/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/solaris/sparc64/libwrapper.so
----------------------------------------------------------------------
diff --git a/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/solaris/sparc64/libwrapper.so b/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/solaris/sparc64/libwrapper.so
new file mode 100755
index 0000000..008bef6
Binary files /dev/null and b/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/solaris/sparc64/libwrapper.so differ

http://git-wip-us.apache.org/repos/asf/karaf/blob/4182735c/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/solaris/x86/karaf-wrapper
----------------------------------------------------------------------
diff --git a/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/solaris/x86/karaf-wrapper b/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/solaris/x86/karaf-wrapper
new file mode 100755
index 0000000..bdec254
Binary files /dev/null and b/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/solaris/x86/karaf-wrapper differ

http://git-wip-us.apache.org/repos/asf/karaf/blob/4182735c/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/solaris/x86/libwrapper.so
----------------------------------------------------------------------
diff --git a/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/solaris/x86/libwrapper.so b/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/solaris/x86/libwrapper.so
new file mode 100755
index 0000000..963ff49
Binary files /dev/null and b/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/solaris/x86/libwrapper.so differ

http://git-wip-us.apache.org/repos/asf/karaf/blob/4182735c/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/solaris/x86_64/karaf-wrapper
----------------------------------------------------------------------
diff --git a/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/solaris/x86_64/karaf-wrapper b/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/solaris/x86_64/karaf-wrapper
new file mode 100755
index 0000000..6bd165e
Binary files /dev/null and b/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/solaris/x86_64/karaf-wrapper differ

http://git-wip-us.apache.org/repos/asf/karaf/blob/4182735c/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/solaris/x86_64/libwrapper.so
----------------------------------------------------------------------
diff --git a/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/solaris/x86_64/libwrapper.so b/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/solaris/x86_64/libwrapper.so
new file mode 100755
index 0000000..0d52ffa
Binary files /dev/null and b/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/solaris/x86_64/libwrapper.so differ

http://git-wip-us.apache.org/repos/asf/karaf/blob/4182735c/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/unix/karaf-service
----------------------------------------------------------------------
diff --git a/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/unix/karaf-service b/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/unix/karaf-service
new file mode 100644
index 0000000..a7ca8bb
--- /dev/null
+++ b/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/unix/karaf-service
@@ -0,0 +1,557 @@
+#! /bin/sh
+
+# ------------------------------------------------------------------------
+# 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.
+# ------------------------------------------------------------------------
+
+# If require, set the JAVA_HOME to launch the wrapper
+#
+#JAVA_HOME=
+#
+
+# Application
+APP_NAME="${name}"
+APP_LONG_NAME="${displayName}"
+
+# Wrapper
+WRAPPER_CMD="${karaf.base}/bin/${APP_NAME}-wrapper"
+WRAPPER_CONF="${karaf.etc}/${APP_NAME}-wrapper.conf"
+
+# Priority at which to run the wrapper.  See "man nice" for valid priorities.
+#  nice is only used if a priority is specified.
+PRIORITY=
+
+# Location of the data folder.
+DATADIR="${karaf.data}"
+
+# Location of the pid file.
+PIDDIR="${karaf.data}"
+
+# If uncommented, causes the Wrapper to be shutdown using an anchor file.
+#  When launched with the 'start' command, it will also ignore all INT and
+#  TERM signals.
+#IGNORE_SIGNALS=true
+
+# If specified, the Wrapper will be run as the specified user.
+# IMPORTANT - Make sure that the user has the required privileges to write
+#  the PID file and wrapper.log files.  Failure to be able to write the log
+#  file will cause the Wrapper to exit without any way to write out an error
+#  message.
+# NOTE - This will set the user which is used to run the Wrapper as well as
+#  the JVM and is not useful in situations where a privileged resource or
+#  port needs to be allocated prior to the user being changed.
+#RUN_AS_USER=
+
+# The following two lines are used by the chkconfig command. Change as is
+#  appropriate for your application.  They should remain commented.
+# chkconfig: 2345 20 80
+# description: ${displayName}
+
+# Do not modify anything beyond this point
+#-----------------------------------------------------------------------------
+
+# Get the fully qualified path to the script
+case $0 in
+    /*)
+        SCRIPT="$0"
+        ;;
+    *)
+        PWD=`pwd`
+        SCRIPT="$PWD/$0"
+        ;;
+esac
+
+# Resolve the true real path without any sym links.
+CHANGED=true
+while [ "X$CHANGED" != "X" ]
+do
+    # Change spaces to ":" so the tokens can be parsed.
+    SCRIPT=`echo $SCRIPT | sed -e 's; ;:;g'`
+    # Get the real path to this script, resolving any symbolic links
+    TOKENS=`echo $SCRIPT | sed -e 's;/; ;g'`
+    REALPATH=
+    for C in $TOKENS; do
+        REALPATH="$REALPATH/$C"
+        while [ -h "$REALPATH" ] ; do
+            LS="`ls -ld "$REALPATH"`"
+            LINK="`expr "$LS" : '.*-> \(.*\)$'`"
+            if expr "$LINK" : '/.*' > /dev/null; then
+                REALPATH="$LINK"
+            else
+                REALPATH="`dirname "$REALPATH"`""/$LINK"
+            fi
+        done
+    done
+    # Change ":" chars back to spaces.
+    REALPATH=`echo $REALPATH | sed -e 's;:; ;g'`
+
+    if [ "$REALPATH" = "$SCRIPT" ]
+    then
+        CHANGED=""
+    else
+        SCRIPT="$REALPATH"
+    fi
+done
+
+# Change the current directory to the location of the script
+cd "`dirname "$REALPATH"`"
+REALDIR=`pwd`
+
+# If the PIDDIR is relative, set its value relative to the full REALPATH to avoid problems if
+#  the working directory is later changed.
+FIRST_CHAR=`echo $PIDDIR | cut -c1,1`
+if [ "$FIRST_CHAR" != "/" ]
+then
+    PIDDIR=$REALDIR/$PIDDIR
+fi
+# Same test for WRAPPER_CMD
+FIRST_CHAR=`echo $WRAPPER_CMD | cut -c1,1`
+if [ "$FIRST_CHAR" != "/" ]
+then
+    WRAPPER_CMD=$REALDIR/$WRAPPER_CMD
+fi
+# Same test for WRAPPER_CONF
+FIRST_CHAR=`echo $WRAPPER_CONF | cut -c1,1`
+if [ "$FIRST_CHAR" != "/" ]
+then
+    WRAPPER_CONF=$REALDIR/$WRAPPER_CONF
+fi
+
+# Process ID
+ANCHORFILE="$PIDDIR/$APP_NAME.anchor"
+PIDFILE="$PIDDIR/$APP_NAME.pid"
+LOCKDIR="/var/lock/subsys"
+LOCKFILE="$LOCKDIR/$APP_NAME"
+pid=""
+
+# Resolve the location of the 'ps' command
+PSEXE="/usr/bin/ps"
+if [ ! -x $PSEXE ]
+then
+    PSEXE="/bin/ps"
+    if [ ! -x $PSEXE ]
+    then
+        echo "Unable to locate 'ps'."
+        echo "Please report this message along with the location of the command on your system."
+        exit 1
+    fi
+fi
+
+# Resolve the os
+DIST_OS=`uname -s | tr [:upper:] [:lower:] | tr -d [:blank:]`
+case "$DIST_OS" in
+    'sunos')
+        DIST_OS="solaris"
+        ;;
+    'hp-ux' | 'hp-ux64')
+        DIST_OS="hpux"
+        ;;
+    'darwin')
+        DIST_OS="macosx"
+        ;;
+    'unix_sv')
+        DIST_OS="unixware"
+        ;;
+esac
+
+# Resolve the architecture
+DIST_ARCH=`uname -p | tr [:upper:] [:lower:] | tr -d [:blank:]`
+if [ "$DIST_ARCH" = "unknown" ]
+then
+    DIST_ARCH=`uname -m | tr [:upper:] [:lower:] | tr -d [:blank:]`
+fi
+case "$DIST_ARCH" in
+    'amd64' | 'ia32' | 'ia64' | 'i386' | 'i486' | 'i586' | 'i686' | 'x86_64')
+        DIST_ARCH="x86"
+        ;;
+    'ip27')
+        DIST_ARCH="mips"
+        ;;
+    'power' | 'powerpc' | 'power_pc' | 'ppc64')
+        DIST_ARCH="ppc"
+        ;;
+    'pa_risc' | 'pa-risc')
+        DIST_ARCH="parisc"
+        ;;
+    'sun4u' | 'sparcv9')
+        DIST_ARCH="sparc"
+        ;;
+    '9000/800')
+        DIST_ARCH="parisc"
+        ;;
+esac
+
+# Decide on the wrapper binary to use.
+# If a 32-bit wrapper binary exists then it will work on 32 or 64 bit
+#  platforms, if the 64-bit binary exists then the distribution most
+#  likely wants to use long names.  Otherwise, look for the default.
+# For macosx, we also want to look for universal binaries.
+WRAPPER_TEST_CMD="$WRAPPER_CMD-$DIST_OS-$DIST_ARCH-32"
+if [ -x $WRAPPER_TEST_CMD ]
+then
+    WRAPPER_CMD="$WRAPPER_TEST_CMD"
+else
+    if [ "$DIST_OS" = "macosx" ]
+    then
+        WRAPPER_TEST_CMD="$WRAPPER_CMD-$DIST_OS-universal-32"
+        if [ -x $WRAPPER_TEST_CMD ]
+        then
+            WRAPPER_CMD="$WRAPPER_TEST_CMD"
+        else
+            WRAPPER_TEST_CMD="$WRAPPER_CMD-$DIST_OS-$DIST_ARCH-64"
+            if [ -x $WRAPPER_TEST_CMD ]
+            then
+                WRAPPER_CMD="$WRAPPER_TEST_CMD"
+            else
+                WRAPPER_TEST_CMD="$WRAPPER_CMD-$DIST_OS-universal-64"
+                if [ -x $WRAPPER_TEST_CMD ]
+                then
+                    WRAPPER_CMD="$WRAPPER_TEST_CMD"
+                else
+                    if [ ! -x $WRAPPER_CMD ]
+                    then
+                        echo "Unable to locate any of the following binaries:"
+                        echo "  $WRAPPER_CMD-$DIST_OS-$DIST_ARCH-32"
+                        echo "  $WRAPPER_CMD-$DIST_OS-universal-32"
+                        echo "  $WRAPPER_CMD-$DIST_OS-$DIST_ARCH-64"
+                        echo "  $WRAPPER_CMD-$DIST_OS-universal-64"
+                        echo "  $WRAPPER_CMD"
+                        exit 1
+                    fi
+                fi
+            fi
+        fi
+    else
+        WRAPPER_TEST_CMD="$WRAPPER_CMD-$DIST_OS-$DIST_ARCH-64"
+        if [ -x $WRAPPER_TEST_CMD ]
+        then
+            WRAPPER_CMD="$WRAPPER_TEST_CMD"
+        else
+            if [ ! -x $WRAPPER_CMD ]
+            then
+                echo "Unable to locate any of the following binaries:"
+                echo "  $WRAPPER_CMD-$DIST_OS-$DIST_ARCH-32"
+                echo "  $WRAPPER_CMD-$DIST_OS-$DIST_ARCH-64"
+                echo "  $WRAPPER_CMD"
+                exit 1
+            fi
+        fi
+    fi
+fi
+
+# Build the nice clause
+if [ "X$PRIORITY" = "X" ]
+then
+    CMDNICE=""
+else
+    CMDNICE="nice -$PRIORITY"
+fi
+
+# Build the anchor file clause.
+if [ "X$IGNORE_SIGNALS" = "X" ]
+then
+   ANCHORPROP=
+   IGNOREPROP=
+else
+   ANCHORPROP=wrapper.anchorfile=$ANCHORFILE
+   IGNOREPROP=wrapper.ignore_signals=TRUE
+fi
+
+# Build the lock file clause.  Only create a lock file if the lock directory exists on this platform.
+if [ -d $LOCKDIR ]
+then
+    LOCKPROP=wrapper.lockfile=$LOCKFILE
+else
+    LOCKPROP=
+fi
+
+checkUser() {
+    # Check the configured user.  If necessary rerun this script as the desired user.
+    if [ "X$RUN_AS_USER" != "X" ]
+    then
+        # Resolve the location of the 'id' command
+        IDEXE="/usr/xpg4/bin/id"
+        if [ ! -x $IDEXE ]
+        then
+            IDEXE="/usr/bin/id"
+            if [ ! -x $IDEXE ]
+            then
+                echo "Unable to locate 'id'."
+                echo "Please report this message along with the location of the command on your system."
+                exit 1
+            fi
+        fi
+
+        if [ "`$IDEXE -u -n`" = "$RUN_AS_USER" ]
+        then
+            # Already running as the configured user.  Avoid password prompts by not calling su.
+            RUN_AS_USER=""
+        fi
+    fi
+    if [ "X$RUN_AS_USER" != "X" ]
+    then
+        # If LOCKPROP and $RUN_AS_USER are defined then the new user will most likely not be
+        # able to create the lock file.  The Wrapper will be able to update this file once it
+        # is created but will not be able to delete it on shutdown.  If $2 is defined then
+        # the lock file should be created for the current command
+        if [ "X$LOCKPROP" != "X" ]
+        then
+            if [ "X$2" != "X" ]
+            then
+                # Resolve the primary group
+                RUN_AS_GROUP=`groups $RUN_AS_USER | awk '{print $3}' | tail -1`
+                if [ "X$RUN_AS_GROUP" = "X" ]
+                then
+                    RUN_AS_GROUP=$RUN_AS_USER
+                fi
+                touch $LOCKFILE
+                chown $RUN_AS_USER:$RUN_AS_GROUP $LOCKFILE
+            fi
+        fi
+
+        # Still want to change users, recurse.  This means that the user will only be
+        #  prompted for a password once.
+        su -m $RUN_AS_USER -s /bin/sh -c "$REALPATH $1"
+        RETVAL=$?
+
+        # Now that we are the original user again, we may need to clean up the lock file.
+        if [ "X$LOCKPROP" != "X" ]
+        then
+            getpid
+            if [ "X$pid" = "X" ]
+            then
+                # Wrapper is not running so make sure the lock file is deleted.
+                if [ -f $LOCKFILE ]
+                then
+                    rm $LOCKFILE
+                fi
+            fi
+        fi
+
+        exit $RETVAL
+    fi
+}
+
+getpid() {
+    if [ -f $PIDFILE ]
+    then
+        if [ -r $PIDFILE ]
+        then
+            pid=`cat $PIDFILE`
+            if [ "X$pid" != "X" ]
+            then
+                # It is possible that 'a' process with the pid exists but that it is not the
+                #  correct process.  This can happen in a number of cases, but the most
+                #  common is during system startup after an unclean shutdown.
+                # The ps statement below looks for the specific wrapper command running as
+                #  the pid.  If it is not found then the pid file is considered to be stale.
+                if [ "$DIST_OS" = "solaris" ]
+                then
+                    pidtest=`$PSEXE -p $pid -o comm | grep $WRAPPER_CMD | tail -1`
+                else
+                    pidtest=`$PSEXE -p $pid -o command | grep $WRAPPER_CMD | tail -1`
+                fi
+                if [ "X$pidtest" = "X" ]
+                then
+                    # This is a stale pid file.
+                    rm -f $PIDFILE
+                    echo "Removed stale pid file: $PIDFILE"
+                    pid=""
+                fi
+            fi
+        else
+            echo "Cannot read $PIDFILE."
+            exit 1
+        fi
+    fi
+}
+
+testpid() {
+    pid=`$PSEXE -p $pid | grep $pid | grep -v grep | awk '{print $1}' | tail -1`
+    if [ "X$pid" = "X" ]
+    then
+        # Process is gone so remove the pid file.
+        rm -f $PIDFILE
+        pid=""
+    fi
+}
+
+console() {
+    echo "Running $APP_LONG_NAME..."
+    getpid
+    if [ "X$pid" = "X" ]
+    then
+        COMMAND_LINE="$CMDNICE $WRAPPER_CMD $WRAPPER_CONF wrapper.syslog.ident=$APP_NAME wrapper.pidfile=$PIDFILE $ANCHORPROP $LOCKPROP"
+        exec $COMMAND_LINE
+    else
+        echo "$APP_LONG_NAME is already running."
+        exit 1
+    fi
+}
+
+start() {
+    echo "Starting $APP_LONG_NAME..."
+    getpid
+    if [ "X$pid" = "X" ]
+    then
+        if [ ! -d $DATADIR ]; then
+            mkdir $DATADIR
+        fi
+        if [ ! -d $DATADIR/log ]; then
+            mkdir $DATADIR/log
+        fi
+        COMMAND_LINE="$CMDNICE $WRAPPER_CMD $WRAPPER_CONF wrapper.syslog.ident=$APP_NAME wrapper.pidfile=$PIDFILE wrapper.daemonize=TRUE $ANCHORPROP $IGNOREPROP $LOCKPROP"
+        exec $COMMAND_LINE
+    else
+        echo "$APP_LONG_NAME is already running."
+        exit 1
+    fi
+}
+
+stopit() {
+    echo "Stopping $APP_LONG_NAME..."
+    getpid
+    if [ "X$pid" = "X" ]
+    then
+        echo "$APP_LONG_NAME was not running."
+    else
+        if [ "X$IGNORE_SIGNALS" = "X" ]
+        then
+            # Running so try to stop it.
+            kill $pid
+            if [ $? -ne 0 ]
+            then
+                # An explanation for the failure should have been given
+                echo "Unable to stop $APP_LONG_NAME."
+                exit 1
+            fi
+        else
+            rm -f $ANCHORFILE
+            if [ -f $ANCHORFILE ]
+            then
+                # An explanation for the failure should have been given
+                echo "Unable to stop $APP_LONG_NAME."
+                exit 1
+            fi
+        fi
+
+        # We can not predict how long it will take for the wrapper to
+        #  actually stop as it depends on settings in wrapper.conf.
+        #  Loop until it does.
+        savepid=$pid
+        CNT=0
+        TOTCNT=0
+        while [ "X$pid" != "X" ]
+        do
+            # Show a waiting message every 5 seconds.
+            if [ "$CNT" -lt "5" ]
+            then
+                CNT=`expr $CNT + 1`
+            else
+                echo "Waiting for $APP_LONG_NAME to exit..."
+                CNT=0
+            fi
+            TOTCNT=`expr $TOTCNT + 1`
+
+            sleep 1
+
+            testpid
+        done
+
+        pid=$savepid
+        testpid
+        if [ "X$pid" != "X" ]
+        then
+            echo "Failed to stop $APP_LONG_NAME."
+            exit 1
+        else
+            echo "Stopped $APP_LONG_NAME."
+        fi
+    fi
+}
+
+status() {
+    getpid
+    if [ "X$pid" = "X" ]
+    then
+        echo "$APP_LONG_NAME is not running."
+        exit 1
+    else
+        echo "$APP_LONG_NAME is running ($pid)."
+        exit 0
+    fi
+}
+
+dump() {
+    echo "Dumping $APP_LONG_NAME..."
+    getpid
+    if [ "X$pid" = "X" ]
+    then
+        echo "$APP_LONG_NAME was not running."
+
+    else
+        kill -3 $pid
+
+        if [ $? -ne 0 ]
+        then
+            echo "Failed to dump $APP_LONG_NAME."
+            exit 1
+        else
+            echo "Dumped $APP_LONG_NAME."
+        fi
+    fi
+}
+
+case "$1" in
+
+    'console')
+        checkUser $1 touchlock
+        console
+        ;;
+
+    'start')
+        checkUser $1 touchlock
+        start
+        ;;
+
+    'stop')
+        checkUser $1
+        stopit
+        ;;
+
+    'restart')
+        checkUser $1 touchlock
+        stopit
+        start
+        ;;
+
+    'status')
+        checkUser $1
+        status
+        ;;
+
+    'dump')
+        checkUser $1
+        dump
+        ;;
+
+    *)
+        echo "Usage: $0 { console | start | stop | restart | status | dump }"
+        exit 1
+        ;;
+esac
+
+exit 0

http://git-wip-us.apache.org/repos/asf/karaf/blob/4182735c/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/unix/karaf-wrapper.conf
----------------------------------------------------------------------
diff --git a/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/unix/karaf-wrapper.conf b/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/unix/karaf-wrapper.conf
new file mode 100644
index 0000000..a3f98a5
--- /dev/null
+++ b/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/unix/karaf-wrapper.conf
@@ -0,0 +1,135 @@
+# ------------------------------------------------------------------------
+# 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.
+# ------------------------------------------------------------------------
+
+#********************************************************************
+# Wrapper Properties
+#********************************************************************
+set.default.JAVA_HOME=${java.home}
+set.default.KARAF_HOME=${karaf.home}
+set.default.KARAF_BASE=${karaf.base}
+set.default.KARAF_DATA=${karaf.data}
+set.default.KARAF_ETC=${karaf.etc}
+
+# Java Application
+wrapper.working.dir=%KARAF_BASE%
+wrapper.java.command=%JAVA_HOME%/bin/java
+wrapper.java.mainclass=org.apache.karaf.wrapper.internal.Main
+wrapper.java.classpath.1=%KARAF_HOME%/lib/karaf-wrapper.jar
+wrapper.java.classpath.2=%KARAF_HOME%/lib/karaf.jar
+wrapper.java.classpath.3=%KARAF_HOME%/lib/karaf-jmx-boot.jar
+wrapper.java.classpath.4=%KARAF_HOME%/lib/karaf-jaas-boot.jar
+wrapper.java.classpath.5=%KARAF_HOME%/lib/karaf-wrapper-main.jar
+wrapper.java.classpath.6=%KARAF_HOME%/lib/karaf-org.osgi.core.jar
+wrapper.java.library.path.1=%KARAF_HOME%/lib/
+
+# Application Parameters.  Add parameters as needed starting from 1
+#wrapper.app.parameter.1=
+
+# JVM Parameters            
+# note that n is the parameter number starting from 1.
+wrapper.java.additional.1=-Dkaraf.home=%KARAF_HOME%
+wrapper.java.additional.2=-Dkaraf.base=%KARAF_BASE%
+wrapper.java.additional.3=-Dkaraf.data=%KARAF_DATA%
+wrapper.java.additional.4=-Dkaraf.etc=%KARAF_ETC%
+wrapper.java.additional.5=-Dcom.sun.management.jmxremote
+wrapper.java.additional.6=-Djavax.management.builder.initial=org.apache.karaf.management.boot.KarafMBeanServerBuilder
+wrapper.java.additional.7=-Dkaraf.startLocalConsole=false
+wrapper.java.additional.8=-Dkaraf.startRemoteShell=true
+wrapper.java.additional.9=-Djava.endorsed.dirs=%JAVA_HOME%/jre/lib/endorsed:%JAVA_HOME%/lib/endorsed:%KARAF_HOME%/lib/endorsed
+wrapper.java.additional.10=-Djava.ext.dirs=%JAVA_HOME%/jre/lib/ext:%JAVA_HOME%/lib/ext:%KARAF_HOME%/lib/ext
+
+# Uncomment to enable jmx
+#wrapper.java.additional.n=-Dcom.sun.management.jmxremote.port=1616
+#wrapper.java.additional.n=-Dcom.sun.management.jmxremote.authenticate=false
+#wrapper.java.additional.n=-Dcom.sun.management.jmxremote.ssl=false
+
+# Uncomment to enable YourKit profiling
+#wrapper.java.additional.n=-Xrunyjpagent
+
+# Uncomment to enable remote debugging
+#wrapper.java.additional.n=-Xdebug -Xnoagent -Djava.compiler=NONE
+#wrapper.java.additional.n=-Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=5005
+
+# Initial Java Heap Size (in MB)
+#wrapper.java.initmemory=3
+
+# Maximum Java Heap Size (in MB)
+wrapper.java.maxmemory=512
+
+
+#********************************************************************
+# Wrapper Logging Properties
+#********************************************************************
+# Format of output for the console.  (See docs for formats)
+wrapper.console.format=PM
+
+# Log Level for console output.  (See docs for log levels)
+wrapper.console.loglevel=INFO
+
+# Log file to use for wrapper output logging.
+wrapper.logfile=%KARAF_DATA%/log/wrapper.log
+
+# Format of output for the log file.  (See docs for formats)
+wrapper.logfile.format=LPTM
+
+# Log Level for log file output.  (See docs for log levels)
+wrapper.logfile.loglevel=INFO
+
+# Maximum size that the log file will be allowed to grow to before
+#  the log is rolled. Size is specified in bytes.  The default value
+#  of 0, disables log rolling.  May abbreviate with the 'k' (kb) or
+#  'm' (mb) suffix.  For example: 10m = 10 megabytes.
+wrapper.logfile.maxsize=10m
+
+# Maximum number of rolled log files which will be allowed before old
+#  files are deleted.  The default value of 0 implies no limit.
+wrapper.logfile.maxfiles=5
+
+# Log Level for sys/event log output.  (See docs for log levels)
+wrapper.syslog.loglevel=NONE
+
+#********************************************************************
+# Wrapper Windows Properties
+#********************************************************************
+# Title to use when running as a console
+wrapper.console.title=${name}
+
+#********************************************************************
+# Wrapper Windows NT/2000/XP Service Properties
+#********************************************************************
+# WARNING - Do not modify any of these properties when an application
+#  using this configuration file has been installed as a service.
+#  Please uninstall the service before modifying this section.  The
+#  service can then be reinstalled.
+
+# Name of the service
+wrapper.ntservice.name=${name}
+
+# Display name of the service
+wrapper.ntservice.displayname=${displayName}
+
+# Description of the service
+wrapper.ntservice.description=${description}
+
+# Service dependencies.  Add dependencies as needed starting from 1
+wrapper.ntservice.dependency.1=
+
+# Mode in which the service is installed.  AUTO_START or DEMAND_START
+wrapper.ntservice.starttype=${startType}
+
+# Allow the service to interact with the desktop.
+wrapper.ntservice.interactive=false

http://git-wip-us.apache.org/repos/asf/karaf/blob/4182735c/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/windows/karaf-service.bat
----------------------------------------------------------------------
diff --git a/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/windows/karaf-service.bat b/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/windows/karaf-service.bat
new file mode 100644
index 0000000..0dd0474
--- /dev/null
+++ b/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/windows/karaf-service.bat
@@ -0,0 +1,51 @@
+@echo off
+
+REM ------------------------------------------------------------------------
+REM Licensed to the Apache Software Foundation (ASF) under one or more
+REM contributor license agreements.  See the NOTICE file distributed with
+REM this work for additional information regarding copyright ownership.
+REM The ASF licenses this file to You under the Apache License, Version 2.0
+REM (the "License"); you may not use this file except in compliance with
+REM the License.  You may obtain a copy of the License at
+REM
+REM http://www.apache.org/licenses/LICENSE-2.0
+REM
+REM Unless required by applicable law or agreed to in writing, software
+REM distributed under the License is distributed on an "AS IS" BASIS,
+REM WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+REM See the License for the specific language governing permissions and
+REM limitations under the License.
+REM ------------------------------------------------------------------------
+
+setlocal
+
+set APP_NAME=${name}
+set APP_LONG_NAME=${displayName}
+set APP_BASE=${karaf.base}
+set APP_ETC=${karaf.etc}
+
+if ""%1"" == ""run"" goto doRun
+if ""%1"" == ""install"" goto doInstall
+if ""%1"" == ""remove"" goto doRemove
+
+echo Usage:  karaf-service ( commands ... )
+echo commands:
+echo   run               Start %APP_NAME% in the current console
+echo   install           Install %APP_NAME% as a Windows service
+echo   remove            Remove the %APP_NAME% Windows service
+goto end
+
+:doRun
+"%APP_BASE%\bin\%APP_NAME%-wrapper.exe" -c "%APP_ETC%\%APP_NAME%-wrapper.conf"
+goto end
+
+:doInstall
+"%APP_BASE%\bin\%APP_NAME%-wrapper.exe" -i "%APP_ETC%\%APP_NAME%-wrapper.conf"
+goto end
+
+:doRemove
+"%APP_BASE%\bin\%APP_NAME%-wrapper.exe" -r "%APP_ETC%\%APP_NAME%-wrapper.conf"
+goto end
+
+:end
+if not "%PAUSE%" == "" pause

http://git-wip-us.apache.org/repos/asf/karaf/blob/4182735c/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/windows/karaf-wrapper.conf
----------------------------------------------------------------------
diff --git a/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/windows/karaf-wrapper.conf b/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/windows/karaf-wrapper.conf
new file mode 100644
index 0000000..def40f7
--- /dev/null
+++ b/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/windows/karaf-wrapper.conf
@@ -0,0 +1,135 @@
+# ------------------------------------------------------------------------
+# 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.
+# ------------------------------------------------------------------------
+
+#********************************************************************
+# Wrapper Properties
+#********************************************************************
+set.default.JAVA_HOME=${java.home}
+set.default.KARAF_HOME=${karaf.home}
+set.default.KARAF_BASE=${karaf.base}
+set.default.KARAF_DATA=${karaf.data}
+set.default.KARAF_ETC=${karaf.etc}
+
+# Java Application
+wrapper.working.dir=%KARAF_BASE%
+wrapper.java.command=%JAVA_HOME%/bin/java
+wrapper.java.mainclass=org.apache.karaf.wrapper.internal.Main
+wrapper.java.classpath.1=%KARAF_HOME%/lib/karaf-wrapper.jar
+wrapper.java.classpath.2=%KARAF_HOME%/lib/karaf.jar
+wrapper.java.classpath.3=%KARAF_HOME%/lib/karaf-jmx-boot.jar
+wrapper.java.classpath.4=%KARAF_HOME%/lib/karaf-jaas-boot.jar
+wrapper.java.classpath.5=%KARAF_HOME%/lib/karaf-wrapper-main.jar
+wrapper.java.classpath.6=%KARAF_HOME%/lib/karaf-org.osgi.core.jar
+wrapper.java.library.path.1=%KARAF_HOME%/lib/
+
+# Application Parameters.  Add parameters as needed starting from 1
+#wrapper.app.parameter.1=
+
+# JVM Parameters
+# note that n is the parameter number starting from 1.
+wrapper.java.additional.1=-Dkaraf.home="%KARAF_HOME%"
+wrapper.java.additional.2=-Dkaraf.base="%KARAF_BASE%"
+wrapper.java.additional.3=-Dkaraf.data="%KARAF_DATA%"
+wrapper.java.additional.4=-Dkaraf.etc="%KARAF_ETC%"
+wrapper.java.additional.5=-Dcom.sun.management.jmxremote
+wrapper.java.additional.6=-Djavax.management.builder.initial=org.apache.karaf.management.boot.KarafMBeanServerBuilder
+wrapper.java.additional.7=-Dkaraf.startLocalConsole=false
+wrapper.java.additional.8=-Dkaraf.startRemoteShell=true
+wrapper.java.additional.9=-Djava.endorsed.dirs="%JAVA_HOME%/jre/lib/endorsed;%JAVA_HOME%/lib/endorsed;%KARAF_HOME%/lib/endorsed"
+wrapper.java.additional.10=-Djava.ext.dirs="%JAVA_HOME%/jre/lib/ext;%JAVA_HOME%/lib/ext;%KARAF_HOME%/lib/ext"
+
+# Uncomment to enable jmx
+#wrapper.java.additional.n=-Dcom.sun.management.jmxremote.port=1616
+#wrapper.java.additional.n=-Dcom.sun.management.jmxremote.authenticate=false
+#wrapper.java.additional.n=-Dcom.sun.management.jmxremote.ssl=false
+
+# Uncomment to enable YourKit profiling
+#wrapper.java.additional.n=-Xrunyjpagent
+
+# Uncomment to enable remote debugging
+#wrapper.java.additional.n=-Xdebug -Xnoagent -Djava.compiler=NONE
+#wrapper.java.additional.n=-Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=5005
+
+# Initial Java Heap Size (in MB)
+#wrapper.java.initmemory=3
+
+# Maximum Java Heap Size (in MB)
+wrapper.java.maxmemory=512
+
+
+#********************************************************************
+# Wrapper Logging Properties
+#********************************************************************
+# Format of output for the console.  (See docs for formats)
+wrapper.console.format=PM
+
+# Log Level for console output.  (See docs for log levels)
+wrapper.console.loglevel=INFO
+
+# Log file to use for wrapper output logging.
+wrapper.logfile=%KARAF_DATA%/log/wrapper.log
+
+# Format of output for the log file.  (See docs for formats)
+wrapper.logfile.format=LPTM
+
+# Log Level for log file output.  (See docs for log levels)
+wrapper.logfile.loglevel=INFO
+
+# Maximum size that the log file will be allowed to grow to before
+#  the log is rolled. Size is specified in bytes.  The default value
+#  of 0, disables log rolling.  May abbreviate with the 'k' (kb) or
+#  'm' (mb) suffix.  For example: 10m = 10 megabytes.
+wrapper.logfile.maxsize=10m
+
+# Maximum number of rolled log files which will be allowed before old
+#  files are deleted.  The default value of 0 implies no limit.
+wrapper.logfile.maxfiles=5
+
+# Log Level for sys/event log output.  (See docs for log levels)
+wrapper.syslog.loglevel=NONE
+
+#********************************************************************
+# Wrapper Windows Properties
+#********************************************************************
+# Title to use when running as a console
+wrapper.console.title=${name}
+
+#********************************************************************
+# Wrapper Windows NT/2000/XP Service Properties
+#********************************************************************
+# WARNING - Do not modify any of these properties when an application
+#  using this configuration file has been installed as a service.
+#  Please uninstall the service before modifying this section.  The
+#  service can then be reinstalled.
+
+# Name of the service
+wrapper.ntservice.name=${name}
+
+# Display name of the service
+wrapper.ntservice.displayname=${displayName}
+
+# Description of the service
+wrapper.ntservice.description=${description}
+
+# Service dependencies.  Add dependencies as needed starting from 1
+wrapper.ntservice.dependency.1=
+
+# Mode in which the service is installed.  AUTO_START or DEMAND_START
+wrapper.ntservice.starttype=${startType}
+
+# Allow the service to interact with the desktop.
+wrapper.ntservice.interactive=false

http://git-wip-us.apache.org/repos/asf/karaf/blob/4182735c/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/windows/karaf-wrapper.exe
----------------------------------------------------------------------
diff --git a/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/windows/karaf-wrapper.exe b/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/windows/karaf-wrapper.exe
new file mode 100644
index 0000000..b4cfc55
Binary files /dev/null and b/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/windows/karaf-wrapper.exe differ