[KARAF-3205] Refactor create-dump to be more low level

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

Branch: refs/heads/master
Commit: e55fd0a05e651ebfe8dac26f1de56e356afe034f
Parents: 9ec4442
Author: Guillaume Nodet <[email protected]>
Authored: Tue Sep 9 18:43:49 2014 +0200
Committer: Guillaume Nodet <[email protected]>
Committed: Tue Sep 9 18:43:57 2014 +0200

----------------------------------------------------------------------
 assemblies/features/framework/pom.xml           |  10 +
 .../resources/etc/config.properties             |   1 +
 diagnostic/NOTICE                               |  71 -----
 diagnostic/boot/NOTICE                          |  71 +++++
 diagnostic/boot/pom.xml                         |  73 +++++
 .../org/apache/karaf/diagnostic/core/Dump.java  |  85 ++++++
 .../karaf/diagnostic/core/DumpDestination.java  |  42 +++
 .../karaf/diagnostic/core/DumpProvider.java     |  29 ++
 .../common/ClosingEntryOutputStreamWrapper.java |  75 +++++
 .../core/common/DirectoryDumpDestination.java   |  59 ++++
 .../core/common/TextDumpProvider.java           |  66 +++++
 .../core/common/ZipDumpDestination.java         |  85 ++++++
 .../diagnostic/core/internal/Activator.java     |  54 ++++
 .../core/providers/BundleDumpProvider.java      |  85 ++++++
 .../core/providers/EnvironmentDumpProvider.java | 290 ++++++++++++++++++
 .../core/providers/HeapDumpProvider.java        |  68 +++++
 .../core/providers/MemoryDumpProvider.java      |  54 ++++
 .../core/providers/ThreadDumpProvider.java      | 118 ++++++++
 .../src/main/resources/OSGI-INF/bundle.info     |  16 +
 diagnostic/core/NOTICE                          |  71 +++++
 diagnostic/core/pom.xml                         | 134 +++++++++
 .../karaf/diagnostic/command/DumpCommand.java   |  86 ++++++
 .../diagnostic/common/FeaturesDumpProvider.java |  78 +++++
 .../diagnostic/common/LogDumpProvider.java      |  81 ++++++
 .../diagnostic/common/TextDumpProvider.java     |  66 +++++
 .../karaf/diagnostic/internal/Activator.java    | 100 +++++++
 .../management/DiagnosticDumpMBean.java         |  42 +++
 .../internal/DiagnosticDumpMBeanImpl.java       |  76 +++++
 .../src/main/resources/OSGI-INF/bundle.info     |  16 +
 diagnostic/pom.xml                              | 104 +------
 .../karaf/diagnostic/command/DumpCommand.java   |  97 -------
 .../diagnostic/core/DiagnosticDumpMBean.java    |  42 ---
 .../karaf/diagnostic/core/DumpDestination.java  |  42 ---
 .../karaf/diagnostic/core/DumpProvider.java     |  29 --
 .../common/ClosingEntryOutputStreamWrapper.java |  75 -----
 .../core/common/DirectoryDumpDestination.java   |  55 ----
 .../core/common/TextDumpProvider.java           |  66 -----
 .../core/common/ZipDumpDestination.java         |  79 -----
 .../core/internal/BundleDumpProvider.java       |  85 ------
 .../core/internal/DiagnosticDumpMBeanImpl.java  |  89 ------
 .../core/internal/EnvironmentDumpProvider.java  | 291 -------------------
 .../core/internal/FeaturesDumpProvider.java     |  79 -----
 .../core/internal/HeapDumpProvider.java         |  59 ----
 .../core/internal/LogDumpProvider.java          |  83 ------
 .../core/internal/MemoryDumpProvider.java       |  54 ----
 .../core/internal/ThreadDumpProvider.java       | 118 --------
 .../core/internal/osgi/Activator.java           | 131 ---------
 .../src/main/resources/OSGI-INF/bundle.info     |  18 --
 pom.xml                                         |   6 +
 49 files changed, 2045 insertions(+), 1659 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/karaf/blob/e55fd0a0/assemblies/features/framework/pom.xml
----------------------------------------------------------------------
diff --git a/assemblies/features/framework/pom.xml 
b/assemblies/features/framework/pom.xml
index 2652bdc..52aaffd 100644
--- a/assemblies/features/framework/pom.xml
+++ b/assemblies/features/framework/pom.xml
@@ -60,6 +60,11 @@
             <scope>runtime</scope>
         </dependency>
         <dependency>
+            <groupId>org.apache.karaf.diagnostic</groupId>
+            <artifactId>org.apache.karaf.diagnostic.boot</artifactId>
+            <scope>runtime</scope>
+        </dependency>
+        <dependency>
             <groupId>org.eclipse</groupId>
             <artifactId>osgi</artifactId>
             <scope>runtime</scope>
@@ -236,6 +241,11 @@
                                     
<destFileName>karaf-jmx-boot.jar</destFileName>
                                 </artifactItem>
                                 <artifactItem>
+                                    
<groupId>org.apache.karaf.diagnostic</groupId>
+                                    
<artifactId>org.apache.karaf.diagnostic.boot</artifactId>
+                                    
<outputDirectory>target/classes/resources/lib</outputDirectory>
+                                </artifactItem>
+                                <artifactItem>
                                     <groupId>org.apache.karaf</groupId>
                                     
<artifactId>org.apache.karaf.exception</artifactId>
                                     
<outputDirectory>target/classes/resources/lib/endorsed</outputDirectory>

http://git-wip-us.apache.org/repos/asf/karaf/blob/e55fd0a0/assemblies/features/framework/src/main/filtered-resources/resources/etc/config.properties
----------------------------------------------------------------------
diff --git 
a/assemblies/features/framework/src/main/filtered-resources/resources/etc/config.properties
 
b/assemblies/features/framework/src/main/filtered-resources/resources/etc/config.properties
index b0978da..93d6c54 100644
--- 
a/assemblies/features/framework/src/main/filtered-resources/resources/etc/config.properties
+++ 
b/assemblies/features/framework/src/main/filtered-resources/resources/etc/config.properties
@@ -74,6 +74,7 @@ org.osgi.framework.system.packages= \
  org.apache.karaf.jaas.boot;version="${karaf.osgi.version}", \
  org.apache.karaf.jaas.boot.principal;version="${karaf.osgi.version}", \
  org.apache.karaf.management.boot;version="${karaf.osgi.version}", \
+ org.apache.karaf.diagnostic.core;version="${karaf.osgi.version}", \
  org.apache.karaf.version;version="${karaf.osgi.version}", \
  ${jre-${java.specification.version}}
 

http://git-wip-us.apache.org/repos/asf/karaf/blob/e55fd0a0/diagnostic/NOTICE
----------------------------------------------------------------------
diff --git a/diagnostic/NOTICE b/diagnostic/NOTICE
deleted file mode 100644
index b70f1f9..0000000
--- a/diagnostic/NOTICE
+++ /dev/null
@@ -1,71 +0,0 @@
-Apache Karaf
-Copyright 2010-2014 The Apache Software Foundation
-
-
-I. Included Software
-
-This product includes software developed at
-The Apache Software Foundation (http://www.apache.org/).
-Licensed under the Apache License 2.0.
-
-This product uses software developed at
-The OSGi Alliance (http://www.osgi.org/).
-Copyright (c) OSGi Alliance (2000, 2010).
-Licensed under the Apache License 2.0.
-
-This product includes software developed at
-OW2 (http://www.ow2.org/).
-Licensed under the BSD License.
-
-This product includes software developed at
-OPS4J (http://www.ops4j.org/).
-Licensed under the Apache License 2.0.
-
-This product includes software developed at
-Eclipse Foundation (http://www.eclipse.org/).
-Licensed under the EPL.
-
-This product includes software written by
-Antony Lesuisse.
-Licensed under Public Domain.
-
-
-II. Used Software
-
-This product uses software developed at
-FUSE Source (http://www.fusesource.org/).
-Licensed under the Apache License 2.0.
-
-This product uses software developed at
-AOP Alliance (http://aopalliance.sourceforge.net/).
-Licensed under the Public Domain.
-
-This product uses software developed at
-Tanuki Software (http://www.tanukisoftware.com/).
-Licensed under the Apache License 2.0.
-
-This product uses software developed at
-Jasypt (http://jasypt.sourceforge.net/).
-Licensed under the Apache License 2.0.
-
-This product uses software developed at
-JLine (http://jline.sourceforge.net).
-Licensed under the BSD License.
-
-This product uses software developed at
-SLF4J (http://www.slf4j.org/).
-Licensed under the MIT License.
-
-This product uses software developed at
-SpringSource (http://www.springsource.org/).
-Licensed under the Apache License 2.0.
-
-This product includes software from http://www.json.org.
-Copyright (c) 2002 JSON.org
-
-
-III. License Summary
-- Apache License 2.0
-- BSD License
-- EPL License
-- MIT License

http://git-wip-us.apache.org/repos/asf/karaf/blob/e55fd0a0/diagnostic/boot/NOTICE
----------------------------------------------------------------------
diff --git a/diagnostic/boot/NOTICE b/diagnostic/boot/NOTICE
new file mode 100644
index 0000000..b70f1f9
--- /dev/null
+++ b/diagnostic/boot/NOTICE
@@ -0,0 +1,71 @@
+Apache Karaf
+Copyright 2010-2014 The Apache Software Foundation
+
+
+I. Included Software
+
+This product includes software developed at
+The Apache Software Foundation (http://www.apache.org/).
+Licensed under the Apache License 2.0.
+
+This product uses software developed at
+The OSGi Alliance (http://www.osgi.org/).
+Copyright (c) OSGi Alliance (2000, 2010).
+Licensed under the Apache License 2.0.
+
+This product includes software developed at
+OW2 (http://www.ow2.org/).
+Licensed under the BSD License.
+
+This product includes software developed at
+OPS4J (http://www.ops4j.org/).
+Licensed under the Apache License 2.0.
+
+This product includes software developed at
+Eclipse Foundation (http://www.eclipse.org/).
+Licensed under the EPL.
+
+This product includes software written by
+Antony Lesuisse.
+Licensed under Public Domain.
+
+
+II. Used Software
+
+This product uses software developed at
+FUSE Source (http://www.fusesource.org/).
+Licensed under the Apache License 2.0.
+
+This product uses software developed at
+AOP Alliance (http://aopalliance.sourceforge.net/).
+Licensed under the Public Domain.
+
+This product uses software developed at
+Tanuki Software (http://www.tanukisoftware.com/).
+Licensed under the Apache License 2.0.
+
+This product uses software developed at
+Jasypt (http://jasypt.sourceforge.net/).
+Licensed under the Apache License 2.0.
+
+This product uses software developed at
+JLine (http://jline.sourceforge.net).
+Licensed under the BSD License.
+
+This product uses software developed at
+SLF4J (http://www.slf4j.org/).
+Licensed under the MIT License.
+
+This product uses software developed at
+SpringSource (http://www.springsource.org/).
+Licensed under the Apache License 2.0.
+
+This product includes software from http://www.json.org.
+Copyright (c) 2002 JSON.org
+
+
+III. License Summary
+- Apache License 2.0
+- BSD License
+- EPL License
+- MIT License

http://git-wip-us.apache.org/repos/asf/karaf/blob/e55fd0a0/diagnostic/boot/pom.xml
----------------------------------------------------------------------
diff --git a/diagnostic/boot/pom.xml b/diagnostic/boot/pom.xml
new file mode 100644
index 0000000..3f9b882
--- /dev/null
+++ b/diagnostic/boot/pom.xml
@@ -0,0 +1,73 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"; 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"; 
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
http://maven.apache.org/xsd/maven-4.0.0.xsd";>
+
+    <!--
+
+        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.
+    -->
+
+    <modelVersion>4.0.0</modelVersion>
+
+    <parent>
+        <groupId>org.apache.karaf</groupId>
+        <artifactId>karaf</artifactId>
+        <version>4.0.0-SNAPSHOT</version>
+        <relativePath>../pom.xml</relativePath>
+    </parent>
+
+    <groupId>org.apache.karaf.diagnostic</groupId>
+    <artifactId>org.apache.karaf.diagnostic.boot</artifactId>
+    <packaging>bundle</packaging>
+    <name>Apache Karaf :: Diagnostic :: Boot</name>
+    <description>Diagnostic Core implementation</description>
+
+    <properties>
+        
<appendedResourcesDirectory>${basedir}/../../etc/appended-resources</appendedResourcesDirectory>
+    </properties>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.osgi</groupId>
+            <artifactId>org.osgi.core</artifactId>
+            <scope>provided</scope>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.felix</groupId>
+                <artifactId>maven-bundle-plugin</artifactId>
+                <configuration>
+                    <instructions>
+                        <Export-Package>
+                            org.apache.karaf.diagnostic.core
+                        </Export-Package>
+                        <Private-Package>
+                            org.apache.karaf.diagnostic.core.common,
+                            org.apache.karaf.diagnostic.core.internal,
+                            org.apache.karaf.diagnostic.core.providers
+                        </Private-Package>
+                        <Karaf-Activator>
+                            org.apache.karaf.diagnostic.core.internal.Activator
+                        </Karaf-Activator>
+                    </instructions>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+
+</project>

http://git-wip-us.apache.org/repos/asf/karaf/blob/e55fd0a0/diagnostic/boot/src/main/java/org/apache/karaf/diagnostic/core/Dump.java
----------------------------------------------------------------------
diff --git 
a/diagnostic/boot/src/main/java/org/apache/karaf/diagnostic/core/Dump.java 
b/diagnostic/boot/src/main/java/org/apache/karaf/diagnostic/core/Dump.java
new file mode 100644
index 0000000..3a4df0a
--- /dev/null
+++ b/diagnostic/boot/src/main/java/org/apache/karaf/diagnostic/core/Dump.java
@@ -0,0 +1,85 @@
+/*
+ * 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.diagnostic.core;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.karaf.diagnostic.core.common.DirectoryDumpDestination;
+import org.apache.karaf.diagnostic.core.common.ZipDumpDestination;
+import org.apache.karaf.diagnostic.core.providers.BundleDumpProvider;
+import org.apache.karaf.diagnostic.core.providers.EnvironmentDumpProvider;
+import org.apache.karaf.diagnostic.core.providers.HeapDumpProvider;
+import org.apache.karaf.diagnostic.core.providers.MemoryDumpProvider;
+import org.apache.karaf.diagnostic.core.providers.ThreadDumpProvider;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.framework.ServiceReference;
+
+/**
+ * Dump helper
+ */
+public final class Dump {
+
+    public static DumpDestination directory(File file) {
+        return new DirectoryDumpDestination(file);
+    }
+
+    public static DumpDestination zip(File file) {
+        return new ZipDumpDestination(file);
+    }
+
+    public static void dump(BundleContext bundleContext, DumpDestination 
destination) {
+        List<DumpProvider> providers = new ArrayList<DumpProvider>();
+        providers.add(new EnvironmentDumpProvider(bundleContext));
+        providers.add(new MemoryDumpProvider());
+        providers.add(new ThreadDumpProvider());
+        providers.add(new HeapDumpProvider());
+        providers.add(new BundleDumpProvider(bundleContext));
+        for (DumpProvider provider : providers) {
+            try {
+                provider.createDump(destination);
+            } catch (Throwable t) {
+                // Ignore
+            }
+        }
+        try {
+            for (ServiceReference<DumpProvider> ref : 
bundleContext.getServiceReferences(DumpProvider.class, null)) {
+                DumpProvider provider = bundleContext.getService(ref);
+                try {
+                    provider.createDump(destination);
+                } catch (Throwable t) {
+                    // Ignore
+                } finally {
+                    bundleContext.ungetService(ref);
+                }
+            }
+        } catch (InvalidSyntaxException e) {
+            // Ignore
+        }
+        try {
+            destination.save();
+        } catch (Throwable t) {
+            // Ignore
+        }
+        System.out.println("Created dump " + destination.toString());
+    }
+
+    // Private constructor
+    private Dump() { }
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/e55fd0a0/diagnostic/boot/src/main/java/org/apache/karaf/diagnostic/core/DumpDestination.java
----------------------------------------------------------------------
diff --git 
a/diagnostic/boot/src/main/java/org/apache/karaf/diagnostic/core/DumpDestination.java
 
b/diagnostic/boot/src/main/java/org/apache/karaf/diagnostic/core/DumpDestination.java
new file mode 100644
index 0000000..39c4edc
--- /dev/null
+++ 
b/diagnostic/boot/src/main/java/org/apache/karaf/diagnostic/core/DumpDestination.java
@@ -0,0 +1,42 @@
+/*
+ * 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.diagnostic.core;
+
+import java.io.OutputStream;
+
+/**
+ * Destination for created dumps.
+ */
+public interface DumpDestination {
+
+    /**
+     * Creates new entry in dump destination.
+     * 
+     * Destination does not close returned output stream by default, dump
+     * provider should do this after completing write operation.
+     * 
+     * @param name Name of file in destination.
+     * @return Output stream ready to write.
+     * @throws Exception When entry cannot be added.
+     */
+    OutputStream add(String name) throws Exception;
+
+    /**
+     * Complete creation of the dump.
+     */
+    void save() throws Exception;
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/e55fd0a0/diagnostic/boot/src/main/java/org/apache/karaf/diagnostic/core/DumpProvider.java
----------------------------------------------------------------------
diff --git 
a/diagnostic/boot/src/main/java/org/apache/karaf/diagnostic/core/DumpProvider.java
 
b/diagnostic/boot/src/main/java/org/apache/karaf/diagnostic/core/DumpProvider.java
new file mode 100644
index 0000000..ec7724c
--- /dev/null
+++ 
b/diagnostic/boot/src/main/java/org/apache/karaf/diagnostic/core/DumpProvider.java
@@ -0,0 +1,29 @@
+/*
+ * 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.diagnostic.core;
+
+/**
+ * Interface which represents instance of tool which can provide dump
+ * information.
+ */
+public interface DumpProvider {
+
+    /**
+     * Creates dump in given entry.
+     */
+    void createDump(DumpDestination destination) throws Exception;
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/e55fd0a0/diagnostic/boot/src/main/java/org/apache/karaf/diagnostic/core/common/ClosingEntryOutputStreamWrapper.java
----------------------------------------------------------------------
diff --git 
a/diagnostic/boot/src/main/java/org/apache/karaf/diagnostic/core/common/ClosingEntryOutputStreamWrapper.java
 
b/diagnostic/boot/src/main/java/org/apache/karaf/diagnostic/core/common/ClosingEntryOutputStreamWrapper.java
new file mode 100644
index 0000000..0c4f9db
--- /dev/null
+++ 
b/diagnostic/boot/src/main/java/org/apache/karaf/diagnostic/core/common/ClosingEntryOutputStreamWrapper.java
@@ -0,0 +1,75 @@
+/*
+ * 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.diagnostic.core.common;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.zip.ZipOutputStream;
+
+/**
+ * Output stream which closes entry instead closing whole stream.
+ */
+public class ClosingEntryOutputStreamWrapper extends OutputStream {
+
+    /**
+     * Wrapped ZIP output stream. 
+     */
+    private ZipOutputStream outputStream;
+
+    /**
+     * Creates new OutputStream.
+     * 
+     * @param outputStream Wrapped output stream.
+     */
+    public ClosingEntryOutputStreamWrapper(ZipOutputStream outputStream) {
+        this.outputStream = outputStream;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void write(int b) throws IOException {
+        outputStream.write(b);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void write(byte[] b) throws IOException {
+        outputStream.write(b);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void write(byte[] b, int off, int len)
+        throws IOException {
+        outputStream.write(b, off, len);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void close() throws IOException {
+        // close entry instead of closing zip stream.
+        outputStream.closeEntry();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/e55fd0a0/diagnostic/boot/src/main/java/org/apache/karaf/diagnostic/core/common/DirectoryDumpDestination.java
----------------------------------------------------------------------
diff --git 
a/diagnostic/boot/src/main/java/org/apache/karaf/diagnostic/core/common/DirectoryDumpDestination.java
 
b/diagnostic/boot/src/main/java/org/apache/karaf/diagnostic/core/common/DirectoryDumpDestination.java
new file mode 100644
index 0000000..689ab34
--- /dev/null
+++ 
b/diagnostic/boot/src/main/java/org/apache/karaf/diagnostic/core/common/DirectoryDumpDestination.java
@@ -0,0 +1,59 @@
+/*
+ * 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.diagnostic.core.common;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.OutputStream;
+
+import org.apache.karaf.diagnostic.core.DumpDestination;
+
+/**
+ * Class which packages dumps to given directory.
+ */
+public class DirectoryDumpDestination implements DumpDestination {
+
+       /**
+        * Directory where dump files will be created.
+        */
+       private File directory;
+
+       public DirectoryDumpDestination(File file) {
+               this.directory = file;
+
+               if (!file.exists()) {
+                       file.mkdirs();
+               } 
+       }
+
+       public OutputStream add(String name) throws Exception {
+               File destination = new File(directory, name);
+               if (name.contains("/") || name.contains("\\")) {
+                       // if name contains slashes we need to create sub 
directory
+                       destination.getParentFile().mkdirs();
+               }
+               return new FileOutputStream(destination);
+       }
+
+       public void save() throws Exception {
+               // do nothing, all should be written to output streams
+       }
+
+    @Override
+    public String toString() {
+        return "directory: " + directory;
+    }
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/e55fd0a0/diagnostic/boot/src/main/java/org/apache/karaf/diagnostic/core/common/TextDumpProvider.java
----------------------------------------------------------------------
diff --git 
a/diagnostic/boot/src/main/java/org/apache/karaf/diagnostic/core/common/TextDumpProvider.java
 
b/diagnostic/boot/src/main/java/org/apache/karaf/diagnostic/core/common/TextDumpProvider.java
new file mode 100644
index 0000000..0b97d6f
--- /dev/null
+++ 
b/diagnostic/boot/src/main/java/org/apache/karaf/diagnostic/core/common/TextDumpProvider.java
@@ -0,0 +1,66 @@
+/*
+ * 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.diagnostic.core.common;
+
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+
+import org.apache.karaf.diagnostic.core.DumpDestination;
+import org.apache.karaf.diagnostic.core.DumpProvider;
+
+/**
+ * Base class for dump providers which writes text to destination.
+ */
+public abstract class TextDumpProvider implements DumpProvider {
+
+    /**
+     * Name of the file.
+     */
+    private final String name;
+
+    /**
+     * Creates new dump provider.
+     * 
+     * @param name Name of the file.
+     */
+    protected TextDumpProvider(String name) {
+        this.name = name;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public final void createDump(DumpDestination destination) throws Exception 
{
+        OutputStream outputStream = destination.add(name);
+        OutputStreamWriter outputStreamWriter = new 
OutputStreamWriter(outputStream);
+        try {
+            writeDump(outputStreamWriter);
+        } finally {
+            outputStreamWriter.close();
+            outputStream.close();
+        }
+    }
+
+    /**
+     * This method should create output.
+     * 
+     * @param outputStreamWriter Stream which points to file specified in 
constructor.
+     * @throws Exception If any problem occur.
+     */
+    protected abstract void writeDump(OutputStreamWriter outputStreamWriter) 
throws Exception;
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/e55fd0a0/diagnostic/boot/src/main/java/org/apache/karaf/diagnostic/core/common/ZipDumpDestination.java
----------------------------------------------------------------------
diff --git 
a/diagnostic/boot/src/main/java/org/apache/karaf/diagnostic/core/common/ZipDumpDestination.java
 
b/diagnostic/boot/src/main/java/org/apache/karaf/diagnostic/core/common/ZipDumpDestination.java
new file mode 100644
index 0000000..66481fb
--- /dev/null
+++ 
b/diagnostic/boot/src/main/java/org/apache/karaf/diagnostic/core/common/ZipDumpDestination.java
@@ -0,0 +1,85 @@
+/*
+ * 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.diagnostic.core.common;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.OutputStream;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipOutputStream;
+
+import org.apache.karaf.diagnostic.core.DumpDestination;
+
+/**
+ * Class which packages dumps to ZIP archive.
+ */
+public class ZipDumpDestination implements DumpDestination {
+
+    /**
+     * Destination streem.
+     */
+    private ZipOutputStream outputStream;
+    private File file;
+
+    /**
+     * Creates new dump in given directory.
+     * 
+     * @param directory Target directory.
+     * @param name Name of the archive.
+     */
+    public ZipDumpDestination(File directory, String name) {
+        this(new File(directory, name));
+    }
+
+    /**
+     * Creates new dump in given file (zip archive). 
+     * 
+     * @param file Destination file.
+     */
+    public ZipDumpDestination(File file) {
+        try {
+            this.file = file;
+            outputStream = new ZipOutputStream(new FileOutputStream(
+                file));
+        } catch (FileNotFoundException e) {
+            // sometimes this can occur, but we simply re throw and let 
+            // caller handle exception
+            throw new RuntimeException("Unable to create dump destination", e);
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public OutputStream add(String name) throws Exception {
+        ZipEntry zipEntry = new ZipEntry(name);
+        outputStream.putNextEntry(zipEntry);
+        return new ClosingEntryOutputStreamWrapper(outputStream);
+    }
+
+    /**
+     * Closes archive handle.
+     */
+    public void save() throws Exception {
+        outputStream.close();
+    }
+
+    @Override
+    public String toString() {
+        return "zip: " + file;
+    }
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/e55fd0a0/diagnostic/boot/src/main/java/org/apache/karaf/diagnostic/core/internal/Activator.java
----------------------------------------------------------------------
diff --git 
a/diagnostic/boot/src/main/java/org/apache/karaf/diagnostic/core/internal/Activator.java
 
b/diagnostic/boot/src/main/java/org/apache/karaf/diagnostic/core/internal/Activator.java
new file mode 100644
index 0000000..fa6b010
--- /dev/null
+++ 
b/diagnostic/boot/src/main/java/org/apache/karaf/diagnostic/core/internal/Activator.java
@@ -0,0 +1,54 @@
+/*
+ * 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.diagnostic.core.internal;
+
+import java.io.File;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+import org.apache.karaf.diagnostic.core.Dump;
+import org.apache.karaf.diagnostic.core.DumpDestination;
+import org.apache.karaf.diagnostic.core.common.ZipDumpDestination;
+import org.osgi.framework.BundleActivator;
+import org.osgi.framework.BundleContext;
+import sun.misc.Signal;
+import sun.misc.SignalHandler;
+
+public class Activator implements BundleActivator, SignalHandler {
+
+    private static final String SIGNAL = "HUP";
+
+    private BundleContext bundleContext;
+    private SignalHandler previous;
+
+    public void start(BundleContext context) throws Exception {
+        bundleContext = context;
+        previous = Signal.handle(new Signal(SIGNAL), this);
+    }
+
+    public void stop(BundleContext context) throws Exception {
+        Signal.handle(new Signal(SIGNAL), previous);
+    }
+
+    public void handle(Signal signal) {
+        SimpleDateFormat dumpFormat = new 
SimpleDateFormat("yyyy-MM-dd_HHmmss-SSS");
+        String fileName = "dump-" + dumpFormat.format(new Date()) + ".zip";
+        DumpDestination destination = new ZipDumpDestination(new 
File(fileName));
+        Dump.dump(bundleContext, destination);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/e55fd0a0/diagnostic/boot/src/main/java/org/apache/karaf/diagnostic/core/providers/BundleDumpProvider.java
----------------------------------------------------------------------
diff --git 
a/diagnostic/boot/src/main/java/org/apache/karaf/diagnostic/core/providers/BundleDumpProvider.java
 
b/diagnostic/boot/src/main/java/org/apache/karaf/diagnostic/core/providers/BundleDumpProvider.java
new file mode 100644
index 0000000..871097e
--- /dev/null
+++ 
b/diagnostic/boot/src/main/java/org/apache/karaf/diagnostic/core/providers/BundleDumpProvider.java
@@ -0,0 +1,85 @@
+/*
+ * 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.diagnostic.core.providers;
+
+import java.io.IOException;
+import java.io.OutputStreamWriter;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.karaf.diagnostic.core.common.TextDumpProvider;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+
+/**
+ * Dump provider which produces file named bundles.txt with list of
+ * installed bundles and it's state.
+ */
+public class BundleDumpProvider extends TextDumpProvider {
+
+    /**
+     * Static map with state mask to string representation.
+     */
+    private static Map<Integer, String> stateMap = new HashMap<Integer, 
String>();
+
+    /**
+     * Map bundle states to string representation.
+     */
+    static {
+        stateMap.put(0x00000001, "UNINSTALLED");
+        stateMap.put(0x00000002, "INSTALLED");
+        stateMap.put(0x00000004, "RESOLVED");
+        stateMap.put(0x00000008, "STARTING");
+        stateMap.put(0x00000010, "STOPPING");
+        stateMap.put(0x00000020, "ACTIVE");
+    }
+
+    /**
+     * Bundle context.
+     */
+    private BundleContext bundleContext;
+
+    /**
+     * Creates new bundle information file.
+     *  
+     * @param context Bundle context to access framework state.
+     */
+    public BundleDumpProvider(BundleContext context) {
+        super("bundles.txt");
+        this.bundleContext = context;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    protected void writeDump(OutputStreamWriter writer) throws IOException {
+        // get bundle states
+        Bundle[] bundles = bundleContext.getBundles();
+
+        writer.write("Number of installed bundles " + bundles.length + "\n");
+
+        // create file header
+        writer.write("Id\tSymbolic name\tVersion\tState\n");
+        for (Bundle bundle : bundles) {
+            // write row :)
+            writer.write(bundle.getBundleId() + "\t" + 
bundle.getSymbolicName() + '\t' + bundle.getVersion()
+                + "\t" + stateMap.get(bundle.getState()) + "\n");
+        }
+
+        writer.flush();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/e55fd0a0/diagnostic/boot/src/main/java/org/apache/karaf/diagnostic/core/providers/EnvironmentDumpProvider.java
----------------------------------------------------------------------
diff --git 
a/diagnostic/boot/src/main/java/org/apache/karaf/diagnostic/core/providers/EnvironmentDumpProvider.java
 
b/diagnostic/boot/src/main/java/org/apache/karaf/diagnostic/core/providers/EnvironmentDumpProvider.java
new file mode 100644
index 0000000..b86fb8d
--- /dev/null
+++ 
b/diagnostic/boot/src/main/java/org/apache/karaf/diagnostic/core/providers/EnvironmentDumpProvider.java
@@ -0,0 +1,290 @@
+/*
+ * 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.diagnostic.core.providers;
+
+import java.io.OutputStreamWriter;
+import java.io.PrintWriter;
+import java.lang.management.ClassLoadingMXBean;
+import java.lang.management.CompilationMXBean;
+import java.lang.management.GarbageCollectorMXBean;
+import java.lang.management.ManagementFactory;
+import java.lang.management.MemoryMXBean;
+import java.lang.management.MemoryUsage;
+import java.lang.management.OperatingSystemMXBean;
+import java.lang.management.RuntimeMXBean;
+import java.lang.management.ThreadMXBean;
+import java.text.DateFormat;
+import java.text.DecimalFormat;
+import java.text.DecimalFormatSymbols;
+import java.text.NumberFormat;
+import java.util.Date;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Map.Entry;
+
+import org.apache.karaf.diagnostic.core.common.TextDumpProvider;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+
+/**
+ * Provider which dumps runtime environment information to file named 
environment.txt.
+ */
+public class EnvironmentDumpProvider extends TextDumpProvider {
+    
+    private static final String KEY_VALUE_FORMAT = "%1$s\t: %2$s";
+    private static final String INDENT_KEY_VALUE_FORMAT = "    
"+KEY_VALUE_FORMAT;
+    private final BundleContext bundleContext;
+
+    /**
+     * Creates new dump entry which contains information about the runtime 
environment.
+     */
+    public EnvironmentDumpProvider(final BundleContext context) {
+        super("environment.txt");
+        this.bundleContext = context;
+    }
+
+    @Override
+    protected void writeDump(final OutputStreamWriter outputStream) throws 
Exception {
+    if( null == outputStream) {
+        return;
+    }
+    final PrintWriter outPW = new PrintWriter(outputStream);
+    // current date/time
+    final DateFormat dateTimeFormatInstance = 
DateFormat.getDateTimeInstance(DateFormat.FULL, DateFormat.FULL, 
Locale.ENGLISH);
+    outPW.printf(KEY_VALUE_FORMAT,"Dump timestamp", 
dateTimeFormatInstance.format(new Date(System.currentTimeMillis()))).println();
+    outPW.println();
+    // karaf information
+    dumpKarafInformation(outPW);
+    outPW.println();
+    // OSGi information
+    dumpOSGiInformation(outPW);
+    outPW.println();
+    // OS information
+    dumpOSInformation(outPW);
+    outPW.println();
+    // general information about JVM
+    dumpVMInformation(outPW, dateTimeFormatInstance);
+    outPW.println();
+    // threads
+    dumpThreadsInformation(outPW);
+    outPW.println();
+    // classes
+    dumpClassesInformation(outPW);
+    outPW.println();
+    // memory
+    dumpMemoryInformation(outPW);
+    outPW.println();
+    // garbage collector
+    dumpGCInformation(outPW);
+    }
+
+    private void dumpKarafInformation(final PrintWriter outPW) {
+        outPW.printf(KEY_VALUE_FORMAT, "Karaf", 
System.getProperty("karaf.name", "root") + ' ' + 
System.getProperty("karaf.version", "")).println();
+        outPW.printf(INDENT_KEY_VALUE_FORMAT, "home", 
System.getProperty("karaf.home", "")).println();
+        outPW.printf(INDENT_KEY_VALUE_FORMAT, "base", 
System.getProperty("karaf.base", "")).println();
+    }
+
+    private void dumpOSGiInformation(final PrintWriter outPW) {
+        if( null == bundleContext ) {
+            return;
+        }
+        outPW.println("OSGi:");
+        final Bundle[] bundles = bundleContext.getBundles();
+        for (final Bundle bundle : bundles) {
+            if( null == bundle || 
!!!"osgi.core".equals(bundle.getSymbolicName())) {
+                continue;
+            }
+            outPW.printf(INDENT_KEY_VALUE_FORMAT, "version", 
bundle.getVersion()).println();
+            break;
+        }
+        outPW.printf(INDENT_KEY_VALUE_FORMAT, "framework", 
bundleContext.getBundle(0).getSymbolicName() + " - " +
+                bundleContext.getBundle(0).getVersion()).println();
+    }
+
+    private void dumpOSInformation(final PrintWriter outPW) {
+        final OperatingSystemMXBean mxBean = 
ManagementFactory.getOperatingSystemMXBean();
+        if( null == mxBean) {
+            return;
+        }
+        outPW.printf(KEY_VALUE_FORMAT, "Operating System", mxBean.getName() + 
' ' + mxBean.getVersion()).println();
+        outPW.printf(INDENT_KEY_VALUE_FORMAT, "architecture", 
mxBean.getArch()).println();
+        outPW.printf(INDENT_KEY_VALUE_FORMAT, "processors", 
mxBean.getAvailableProcessors()).println();
+//        outPW.printf(INDENT_KEY_VALUE_FORMAT, "current system load average", 
mxBean.getSystemLoadAverage()).println();
+    }
+
+    private void dumpVMInformation(final PrintWriter outPW,
+        final DateFormat dateTimeFormatInstance) {
+        final RuntimeMXBean mxBean = ManagementFactory.getRuntimeMXBean();
+        if( mxBean == null ) {
+            return;
+        }
+        outPW.printf(KEY_VALUE_FORMAT,"Instance name", 
mxBean.getName()).println();
+        outPW.printf(KEY_VALUE_FORMAT,"Start time", 
dateTimeFormatInstance.format(new Date(mxBean.getStartTime()))).println();
+        outPW.printf(KEY_VALUE_FORMAT,"Uptime", 
printDuration(mxBean.getUptime())).println();
+        outPW.println();
+        outPW.printf(KEY_VALUE_FORMAT, "Java VM", mxBean.getVmName() + " " + 
mxBean.getVmVersion()).println();
+        outPW.printf(INDENT_KEY_VALUE_FORMAT, "vendor", 
mxBean.getVmVendor()).println();
+        outPW.printf(INDENT_KEY_VALUE_FORMAT, "version", 
System.getProperty("java.version")).println();
+        outPW.println();
+        outPW.println("Input arguments:");
+        final List<String> inputArguments = mxBean.getInputArguments();
+        for (final String argument : inputArguments) {
+            if( argument != null && argument.contains("=")) {
+                final String[] split = argument.split("=");
+                outPW.printf(INDENT_KEY_VALUE_FORMAT, split[0], 
split[1]).println();
+            } else {
+                outPW.printf(INDENT_KEY_VALUE_FORMAT, argument,"").println();
+            }
+        }
+        outPW.println("Classpath:");
+        outPW.printf(INDENT_KEY_VALUE_FORMAT, "boot classpath", 
mxBean.getBootClassPath()).println();
+        outPW.printf(INDENT_KEY_VALUE_FORMAT, "library path", 
mxBean.getLibraryPath()).println();
+        outPW.printf(INDENT_KEY_VALUE_FORMAT, "classpath", 
mxBean.getClassPath()).println();
+        outPW.println("System properties:");
+        final Map<String, String> systemProperties = 
mxBean.getSystemProperties();
+        for (final Entry<String, String> property : 
systemProperties.entrySet()) {
+            outPW.printf(INDENT_KEY_VALUE_FORMAT, property.getKey(), 
property.getValue()).println();
+        }
+        outPW.println();
+        // JIT information
+        final CompilationMXBean compilationMXBean = 
ManagementFactory.getCompilationMXBean();
+        if( compilationMXBean != null ) {
+            outPW.printf(KEY_VALUE_FORMAT, "JIT compiler", 
compilationMXBean.getName()).println();
+            outPW.printf(INDENT_KEY_VALUE_FORMAT, "total compile time", 
printDuration(compilationMXBean.getTotalCompilationTime())).println();
+        }
+    }
+
+    private void dumpThreadsInformation(final PrintWriter outPW) {
+        final ThreadMXBean mxBean = ManagementFactory.getThreadMXBean();
+        if( null == mxBean) {
+            return;
+        }
+        outPW.println("Threads:");
+        outPW.printf(INDENT_KEY_VALUE_FORMAT, "live", 
formatLong(mxBean.getThreadCount())).println();
+        outPW.printf(INDENT_KEY_VALUE_FORMAT, "daemon", 
formatLong(mxBean.getDaemonThreadCount())).println();
+        outPW.printf(INDENT_KEY_VALUE_FORMAT, "peak", 
formatLong(mxBean.getPeakThreadCount())).println();
+        outPW.printf(INDENT_KEY_VALUE_FORMAT, "total", 
formatLong(mxBean.getTotalStartedThreadCount())).println();
+    }
+
+    private void dumpClassesInformation(final PrintWriter outPW) {
+        final ClassLoadingMXBean mxBean = 
ManagementFactory.getClassLoadingMXBean();
+        if( null == mxBean) {
+            return;
+        }
+        outPW.println("Classes:");
+        outPW.printf(INDENT_KEY_VALUE_FORMAT, "loaded", 
formatLong(mxBean.getLoadedClassCount())).println();
+        outPW.printf(INDENT_KEY_VALUE_FORMAT, "total", 
formatLong(mxBean.getTotalLoadedClassCount())).println();
+        outPW.printf(INDENT_KEY_VALUE_FORMAT, "unloaded", 
formatLong(mxBean.getUnloadedClassCount())).println();
+    }
+
+    private void dumpMemoryInformation(final PrintWriter outPW) {
+        final MemoryMXBean mxBean = ManagementFactory.getMemoryMXBean();
+        if( null == mxBean) {
+            return;
+        }
+        final MemoryUsage heapMemoryUsage = mxBean.getHeapMemoryUsage();
+        final MemoryUsage nonHeapMemoryUsage = mxBean.getNonHeapMemoryUsage();
+        if( heapMemoryUsage != null ) {
+            outPW.println("HEAP Memory:");
+            outPW.printf(INDENT_KEY_VALUE_FORMAT, "commited", 
printMemory(heapMemoryUsage.getCommitted())).println();
+            outPW.printf(INDENT_KEY_VALUE_FORMAT, "init", 
printMemory(heapMemoryUsage.getInit())).println();
+            outPW.printf(INDENT_KEY_VALUE_FORMAT, "used", 
printMemory(heapMemoryUsage.getUsed())).println();
+            outPW.printf(INDENT_KEY_VALUE_FORMAT, "maximal", 
printMemory(heapMemoryUsage.getMax())).println();
+        }
+        if( nonHeapMemoryUsage != null ) {
+            outPW.println("NON-HEAP Memory:");
+            outPW.printf(INDENT_KEY_VALUE_FORMAT, "commited", 
printMemory(nonHeapMemoryUsage.getCommitted())).println();
+            outPW.printf(INDENT_KEY_VALUE_FORMAT, "init", 
printMemory(nonHeapMemoryUsage.getInit())).println();
+            outPW.printf(INDENT_KEY_VALUE_FORMAT, "used", 
printMemory(nonHeapMemoryUsage.getUsed())).println();
+            outPW.printf(INDENT_KEY_VALUE_FORMAT, "maximal", 
printMemory(nonHeapMemoryUsage.getMax())).println();
+        }
+    }
+
+    private void dumpGCInformation(final PrintWriter outPW) {
+        final List<GarbageCollectorMXBean> mxBeans = 
ManagementFactory.getGarbageCollectorMXBeans();
+        if( null == mxBeans || mxBeans.isEmpty()) {
+            return;
+        }
+        final MemoryMXBean memoryMxBean = ManagementFactory.getMemoryMXBean();
+        if( memoryMxBean != null ) {
+            outPW.printf(INDENT_KEY_VALUE_FORMAT, "pending objects", 
formatLong(memoryMxBean.getObjectPendingFinalizationCount())).println();
+        }
+        final String gcFormat ="'%1$s' collections: %2$s\ttime: %3$s";
+        outPW.println();
+        for (final GarbageCollectorMXBean mxBean : mxBeans) {
+            if( null == mxBean) {
+                continue;
+            }
+            outPW.printf(KEY_VALUE_FORMAT, "Garbage Collectors", 
String.format(gcFormat, mxBean.getName(), 
formatLong(mxBean.getCollectionCount()), 
printDuration(mxBean.getCollectionTime()))).println();
+        }
+    }
+
+
+    private String formatLong(final long longValue) {
+        final NumberFormat fmtI = new DecimalFormat("###,###", new 
DecimalFormatSymbols(Locale.ENGLISH));
+        return fmtI.format(longValue);
+    }
+
+    private String printMemory(final long bytes) {
+        if( bytes <= 1024) {
+            return formatLong(bytes)+" bytes";
+        }
+        return formatLong(bytes/1024)+" kbytes";
+    }
+
+    /**
+     * Prints the duration in a human readable format as X days Y hours Z 
minutes etc.
+     *
+     * @param uptime the uptime in millis
+     * @return the time used for displaying on screen or in logs
+     */
+    private String printDuration(double uptime) {
+        // Code based on code taken from Karaf
+        // 
https://svn.apache.org/repos/asf/karaf/trunk/shell/commands/src/main/java/org/apache/karaf/shell/commands/impl/InfoAction.java
+
+        uptime /= 1000;
+        if (uptime < 60) {
+            final NumberFormat fmtD = new DecimalFormat("###,##0.000", new 
DecimalFormatSymbols(Locale.ENGLISH));
+            return fmtD.format(uptime) + " seconds";
+        }
+        uptime /= 60;
+        if (uptime < 60) {
+            final long minutes = (long) uptime;
+            final String s = formatLong(minutes) + (minutes > 1 ? " minutes" : 
" minute");
+            return s;
+        }
+        uptime /= 60;
+        if (uptime < 24) {
+            final long hours = (long) uptime;
+            final long minutes = (long) ((uptime - hours) * 60);
+            String s = formatLong(hours) + (hours > 1 ? " hours" : " hour");
+            if (minutes != 0) {
+                s += " " + formatLong(minutes) + (minutes > 1 ? " minutes" : " 
minute");
+            }
+            return s;
+        }
+        uptime /= 24;
+        final long days = (long) uptime;
+        final long hours = (long) ((uptime - days) * 24);
+        String s = formatLong(days) + (days > 1 ? " days" : " day");
+        if (hours != 0) {
+            s += " " + formatLong(hours) + (hours > 1 ? " hours" : " hour");
+        }
+        return s;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/e55fd0a0/diagnostic/boot/src/main/java/org/apache/karaf/diagnostic/core/providers/HeapDumpProvider.java
----------------------------------------------------------------------
diff --git 
a/diagnostic/boot/src/main/java/org/apache/karaf/diagnostic/core/providers/HeapDumpProvider.java
 
b/diagnostic/boot/src/main/java/org/apache/karaf/diagnostic/core/providers/HeapDumpProvider.java
new file mode 100644
index 0000000..6a6f040
--- /dev/null
+++ 
b/diagnostic/boot/src/main/java/org/apache/karaf/diagnostic/core/providers/HeapDumpProvider.java
@@ -0,0 +1,68 @@
+/*
+ * 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.diagnostic.core.providers;
+
+import com.sun.management.HotSpotDiagnosticMXBean;
+import org.apache.karaf.diagnostic.core.DumpDestination;
+import org.apache.karaf.diagnostic.core.DumpProvider;
+
+import javax.management.MBeanServer;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.OutputStream;
+import java.lang.management.ManagementFactory;
+
+/**
+ * Create a heap dump.
+ */
+public class HeapDumpProvider implements DumpProvider {
+
+    public void createDump(DumpDestination destination) throws Exception {
+        File heapDumpFile = null;
+        FileInputStream in = null;
+        OutputStream out = null;
+        try {
+            MBeanServer mBeanServer = 
ManagementFactory.getPlatformMBeanServer();
+            HotSpotDiagnosticMXBean diagnosticMXBean = 
ManagementFactory.newPlatformMXBeanProxy(mBeanServer,
+                    "com.sun.management:type=HotSpotDiagnostic", 
HotSpotDiagnosticMXBean.class);
+            heapDumpFile = File.createTempFile("heapdump", ".txt");
+            heapDumpFile.delete();
+            diagnosticMXBean.dumpHeap(heapDumpFile.getAbsolutePath(), false);
+            // copy the dump in the destination
+            in = new FileInputStream(heapDumpFile);
+            out = destination.add("heapdump.txt");
+            byte[] buffer = new byte[2048];
+            int l;
+            while (((l = in.read(buffer)) != -1)) {
+                out.write(buffer, 0, l);
+            }
+        } finally {
+            if (in != null) {
+                in.close();
+            }
+            if (out != null) {
+                out.flush();
+                out.close();
+            }
+            // remove the original dump
+            if (heapDumpFile != null && heapDumpFile.exists()) {
+                heapDumpFile.delete();
+            }
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/e55fd0a0/diagnostic/boot/src/main/java/org/apache/karaf/diagnostic/core/providers/MemoryDumpProvider.java
----------------------------------------------------------------------
diff --git 
a/diagnostic/boot/src/main/java/org/apache/karaf/diagnostic/core/providers/MemoryDumpProvider.java
 
b/diagnostic/boot/src/main/java/org/apache/karaf/diagnostic/core/providers/MemoryDumpProvider.java
new file mode 100644
index 0000000..8e99339
--- /dev/null
+++ 
b/diagnostic/boot/src/main/java/org/apache/karaf/diagnostic/core/providers/MemoryDumpProvider.java
@@ -0,0 +1,54 @@
+/*
+ * 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.diagnostic.core.providers;
+
+import java.io.OutputStreamWriter;
+import java.lang.management.ManagementFactory;
+import java.lang.management.MemoryMXBean;
+
+import org.apache.karaf.diagnostic.core.common.TextDumpProvider;
+
+/**
+ * Provider which dump the memory information in the memory.txt file.
+ */
+public class MemoryDumpProvider extends TextDumpProvider {
+
+    public MemoryDumpProvider() {
+        super("memory.txt");
+    }
+
+    @Override
+    protected void writeDump(OutputStreamWriter outputStream) throws Exception 
{
+        MemoryMXBean memoryMXBean = ManagementFactory.getMemoryMXBean();
+
+        outputStream.write("Number of objects waiting finalization: " + 
memoryMXBean.getObjectPendingFinalizationCount() + "\n\n");
+
+        outputStream.write("Heap:\n");
+        outputStream.write("\tInit:      " + 
memoryMXBean.getHeapMemoryUsage().getInit() + "\n");
+        outputStream.write("\tUser:      " + 
memoryMXBean.getHeapMemoryUsage().getUsed() + "\n");
+        outputStream.write("\tCommitted: " + 
memoryMXBean.getHeapMemoryUsage().getCommitted() + "\n");
+        outputStream.write("\tMax:       " + 
memoryMXBean.getHeapMemoryUsage().getMax() + "\n");
+
+        outputStream.write("Non-Heap: \n");
+        outputStream.write("\tInit:      " + 
memoryMXBean.getNonHeapMemoryUsage().getInit() + "\n");
+        outputStream.write("\tUser:      " + 
memoryMXBean.getNonHeapMemoryUsage().getUsed() + "\n");
+        outputStream.write("\tCommitted: " + 
memoryMXBean.getNonHeapMemoryUsage().getCommitted() + "\n");
+        outputStream.write("\tMax:       " + 
memoryMXBean.getNonHeapMemoryUsage().getMax() + "\n");
+
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/e55fd0a0/diagnostic/boot/src/main/java/org/apache/karaf/diagnostic/core/providers/ThreadDumpProvider.java
----------------------------------------------------------------------
diff --git 
a/diagnostic/boot/src/main/java/org/apache/karaf/diagnostic/core/providers/ThreadDumpProvider.java
 
b/diagnostic/boot/src/main/java/org/apache/karaf/diagnostic/core/providers/ThreadDumpProvider.java
new file mode 100644
index 0000000..9f6b25b
--- /dev/null
+++ 
b/diagnostic/boot/src/main/java/org/apache/karaf/diagnostic/core/providers/ThreadDumpProvider.java
@@ -0,0 +1,118 @@
+/*
+ * 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.diagnostic.core.providers;
+
+import java.io.OutputStreamWriter;
+import java.lang.management.LockInfo;
+import java.lang.management.ManagementFactory;
+import java.lang.management.MonitorInfo;
+import java.lang.management.ThreadInfo;
+import java.lang.management.ThreadMXBean;
+
+import org.apache.karaf.diagnostic.core.common.TextDumpProvider;
+
+/**
+ * Provider which dumps thread info to file named threads.txt.
+ */
+public class ThreadDumpProvider extends TextDumpProvider {
+
+    /**
+     * Creates new dump entry which contains information about threads.
+     */
+    public ThreadDumpProvider() {
+        super("threads.txt");
+    }
+
+    @Override
+    protected void writeDump(OutputStreamWriter outputStream) throws Exception 
{
+        ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean();
+
+        outputStream.write("Number of threads: " + 
threadMXBean.getThreadCount() + "\n");
+
+        for (ThreadInfo threadInfo : 
threadMXBean.getThreadInfo(threadMXBean.getAllThreadIds(), Integer.MAX_VALUE)) {
+            outputStream.write(getDumpThreadString(threadInfo) + "\n\n");
+        }
+
+    }
+
+    protected String getDumpThreadString(ThreadInfo threadInfo) {
+        StringBuilder sb = new StringBuilder("\"" + threadInfo.getThreadName() 
+ "\"" + " Id=" + threadInfo.getThreadId() + " "
+                                             + threadInfo.getThreadState());
+        if (threadInfo.getLockName() != null) {
+            sb.append(" on " + threadInfo.getLockName());
+        }
+        if (threadInfo.getLockOwnerName() != null) {
+            sb.append(" owned by \"" + threadInfo.getLockOwnerName() + "\" 
Id=" + threadInfo.getLockOwnerId());
+        }
+        if (threadInfo.isSuspended()) {
+            sb.append(" (suspended)");
+        }
+        if (threadInfo.isInNative()) {
+            sb.append(" (in native)");
+        }
+        sb.append('\n');
+        int i = 0;
+        StackTraceElement[] stackTrace = threadInfo.getStackTrace();
+        for (; i < stackTrace.length; i++) {
+            StackTraceElement ste = stackTrace[i];
+            sb.append("\tat " + ste.toString());
+            sb.append('\n');
+            if (i == 0 && threadInfo.getLockInfo() != null) {
+                Thread.State ts = threadInfo.getThreadState();
+                switch (ts) {
+                case BLOCKED:
+                    sb.append("\t-  blocked on " + threadInfo.getLockInfo());
+                    sb.append('\n');
+                    break;
+                case WAITING:
+                    sb.append("\t-  waiting on " + threadInfo.getLockInfo());
+                    sb.append('\n');
+                    break;
+                case TIMED_WAITING:
+                    sb.append("\t-  waiting on " + threadInfo.getLockInfo());
+                    sb.append('\n');
+                    break;
+                default:
+                }
+            }
+
+            for (MonitorInfo mi : threadInfo.getLockedMonitors()) {
+                if (mi.getLockedStackDepth() == i) {
+                    sb.append("\t-  locked " + mi);
+                    sb.append('\n');
+                }
+            }
+        }
+        if (i < stackTrace.length) {
+            sb.append("\t...");
+            sb.append('\n');
+        }
+
+        LockInfo[] locks = threadInfo.getLockedSynchronizers();
+        if (locks.length > 0) {
+            sb.append("\n\tNumber of locked synchronizers = " + locks.length);
+            sb.append('\n');
+            for (LockInfo li : locks) {
+                sb.append("\t- " + li);
+                sb.append('\n');
+            }
+        }
+        sb.append('\n');
+        return sb.toString();
+    }
+
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/e55fd0a0/diagnostic/boot/src/main/resources/OSGI-INF/bundle.info
----------------------------------------------------------------------
diff --git a/diagnostic/boot/src/main/resources/OSGI-INF/bundle.info 
b/diagnostic/boot/src/main/resources/OSGI-INF/bundle.info
new file mode 100644
index 0000000..6f8f9cb
--- /dev/null
+++ b/diagnostic/boot/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
+
+The diagnostic boot bundle contains the core diagnostic implementation along 
with the signal handler.
+
+h1. See also
+
+Diagnostic - section of the Karaf User Guide.

http://git-wip-us.apache.org/repos/asf/karaf/blob/e55fd0a0/diagnostic/core/NOTICE
----------------------------------------------------------------------
diff --git a/diagnostic/core/NOTICE b/diagnostic/core/NOTICE
new file mode 100644
index 0000000..b70f1f9
--- /dev/null
+++ b/diagnostic/core/NOTICE
@@ -0,0 +1,71 @@
+Apache Karaf
+Copyright 2010-2014 The Apache Software Foundation
+
+
+I. Included Software
+
+This product includes software developed at
+The Apache Software Foundation (http://www.apache.org/).
+Licensed under the Apache License 2.0.
+
+This product uses software developed at
+The OSGi Alliance (http://www.osgi.org/).
+Copyright (c) OSGi Alliance (2000, 2010).
+Licensed under the Apache License 2.0.
+
+This product includes software developed at
+OW2 (http://www.ow2.org/).
+Licensed under the BSD License.
+
+This product includes software developed at
+OPS4J (http://www.ops4j.org/).
+Licensed under the Apache License 2.0.
+
+This product includes software developed at
+Eclipse Foundation (http://www.eclipse.org/).
+Licensed under the EPL.
+
+This product includes software written by
+Antony Lesuisse.
+Licensed under Public Domain.
+
+
+II. Used Software
+
+This product uses software developed at
+FUSE Source (http://www.fusesource.org/).
+Licensed under the Apache License 2.0.
+
+This product uses software developed at
+AOP Alliance (http://aopalliance.sourceforge.net/).
+Licensed under the Public Domain.
+
+This product uses software developed at
+Tanuki Software (http://www.tanukisoftware.com/).
+Licensed under the Apache License 2.0.
+
+This product uses software developed at
+Jasypt (http://jasypt.sourceforge.net/).
+Licensed under the Apache License 2.0.
+
+This product uses software developed at
+JLine (http://jline.sourceforge.net).
+Licensed under the BSD License.
+
+This product uses software developed at
+SLF4J (http://www.slf4j.org/).
+Licensed under the MIT License.
+
+This product uses software developed at
+SpringSource (http://www.springsource.org/).
+Licensed under the Apache License 2.0.
+
+This product includes software from http://www.json.org.
+Copyright (c) 2002 JSON.org
+
+
+III. License Summary
+- Apache License 2.0
+- BSD License
+- EPL License
+- MIT License

http://git-wip-us.apache.org/repos/asf/karaf/blob/e55fd0a0/diagnostic/core/pom.xml
----------------------------------------------------------------------
diff --git a/diagnostic/core/pom.xml b/diagnostic/core/pom.xml
new file mode 100644
index 0000000..c9cdaa1
--- /dev/null
+++ b/diagnostic/core/pom.xml
@@ -0,0 +1,134 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"; 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"; 
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
http://maven.apache.org/xsd/maven-4.0.0.xsd";>
+
+    <!--
+
+        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.
+    -->
+
+    <modelVersion>4.0.0</modelVersion>
+
+    <parent>
+        <groupId>org.apache.karaf</groupId>
+        <artifactId>karaf</artifactId>
+        <version>4.0.0-SNAPSHOT</version>
+        <relativePath>../pom.xml</relativePath>
+    </parent>
+
+    <groupId>org.apache.karaf.diagnostic</groupId>
+    <artifactId>org.apache.karaf.diagnostic.core</artifactId>
+    <packaging>bundle</packaging>
+    <name>Apache Karaf :: Diagnostic :: Core</name>
+    <description>Core implementation using Karaf diagnostic using the 
diagnostic common services</description>
+
+    <properties>
+        
<appendedResourcesDirectory>${basedir}/../../etc/appended-resources</appendedResourcesDirectory>
+    </properties>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.osgi</groupId>
+            <artifactId>org.osgi.core</artifactId>
+            <scope>provided</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>org.osgi</groupId>
+            <artifactId>org.osgi.compendium</artifactId>
+            <scope>provided</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.karaf</groupId>
+            <artifactId>org.apache.karaf.util</artifactId>
+            <scope>provided</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.karaf.features</groupId>
+            <artifactId>org.apache.karaf.features.core</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.karaf.diagnostic</groupId>
+            <artifactId>org.apache.karaf.diagnostic.boot</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.karaf.shell</groupId>
+            <artifactId>org.apache.karaf.shell.core</artifactId>
+            <optional>true</optional>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <resources>
+            <resource>
+                <directory>${project.basedir}/src/main/resources</directory>
+                <includes>
+                    <include>**/*</include>
+                </includes>
+            </resource>
+            <resource>
+                <directory>${project.basedir}/src/main/resources</directory>
+                <filtering>true</filtering>
+                <includes>
+                    <include>**/*.info</include>
+                </includes>
+            </resource>
+        </resources>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.karaf.tooling</groupId>
+                <artifactId>karaf-services-maven-plugin</artifactId>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.felix</groupId>
+                <artifactId>maven-bundle-plugin</artifactId>
+                <configuration>
+                    <instructions>
+                        <Export-Package>
+                            org.apache.karaf.diagnostic.management
+                               </Export-Package>
+                        <Import-Package>
+                            com.sun.management*;resolution:=optional,
+                            *
+                        </Import-Package>
+                        <Private-Package>
+                            org.apache.karaf.diagnostic.command,
+                            org.apache.karaf.diagnostic.common,
+                            org.apache.karaf.diagnostic.internal,
+                            org.apache.karaf.diagnostic.management.internal,
+                            org.apache.karaf.util,
+                            org.apache.karaf.util.tracker
+                        </Private-Package>
+                        <Provide-Capability>
+                            ${capabilities}
+                        </Provide-Capability>
+                        <Require-Capability>
+                            ${requirements}
+                        </Require-Capability>
+                        <Bundle-Activator>
+                            org.apache.karaf.diagnostic.internal.Activator
+                        </Bundle-Activator>
+                        <Karaf-Commands>*</Karaf-Commands>
+                    </instructions>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+
+</project>

http://git-wip-us.apache.org/repos/asf/karaf/blob/e55fd0a0/diagnostic/core/src/main/java/org/apache/karaf/diagnostic/command/DumpCommand.java
----------------------------------------------------------------------
diff --git 
a/diagnostic/core/src/main/java/org/apache/karaf/diagnostic/command/DumpCommand.java
 
b/diagnostic/core/src/main/java/org/apache/karaf/diagnostic/command/DumpCommand.java
new file mode 100644
index 0000000..a7f0694
--- /dev/null
+++ 
b/diagnostic/core/src/main/java/org/apache/karaf/diagnostic/command/DumpCommand.java
@@ -0,0 +1,86 @@
+/*
+ * 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.diagnostic.command;
+
+import java.io.File;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.List;
+
+import org.apache.karaf.diagnostic.core.Dump;
+import org.apache.karaf.diagnostic.core.DumpDestination;
+import org.apache.karaf.shell.api.action.Action;
+import org.apache.karaf.shell.api.action.Argument;
+import org.apache.karaf.shell.api.action.Command;
+import org.apache.karaf.shell.api.action.Option;
+import org.apache.karaf.shell.api.action.lifecycle.Reference;
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+import org.osgi.framework.BundleContext;
+
+/**
+ * Command to create dump from shell.
+ */
+@Command(scope = "dev", name = "dump-create", description = "Creates zip 
archive with diagnostic info.")
+@Service
+public class DumpCommand implements Action {
+
+    /**
+     * Output format of the filename if not defined otherwise
+     */
+    private SimpleDateFormat dumpFormat = new 
SimpleDateFormat("yyyy-MM-dd_HHmmss");
+
+    /**
+     * Directory switch.
+     */
+    @Option(name = "-d", aliases = "--directory", description = "Creates dump 
in a directory in place of a ZIP archive")
+    boolean directory;
+
+    /**
+     * Name of created directory or archive.
+     */
+    @Argument(name = "name", description = "Name of created zip or directory", 
required = false)
+    String fileName;
+
+    @Reference
+    BundleContext bundleContext;
+
+    @Override
+    public Object execute() throws Exception {
+        DumpDestination destination;
+
+        // create default file name if none provided
+        if (fileName == null || fileName.trim().length() == 0) {
+            fileName = dumpFormat.format(new Date());
+            if (!directory) {
+                fileName += ".zip";
+            }
+        }
+        File target = new File(fileName);
+
+        // if directory switch is on, create dump in directory
+        if (directory) {
+            destination = Dump.directory(target);
+        } else {
+            destination = Dump.zip(target);
+        }
+
+        Dump.dump(bundleContext, destination);
+
+        return null;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/e55fd0a0/diagnostic/core/src/main/java/org/apache/karaf/diagnostic/common/FeaturesDumpProvider.java
----------------------------------------------------------------------
diff --git 
a/diagnostic/core/src/main/java/org/apache/karaf/diagnostic/common/FeaturesDumpProvider.java
 
b/diagnostic/core/src/main/java/org/apache/karaf/diagnostic/common/FeaturesDumpProvider.java
new file mode 100644
index 0000000..4d90841
--- /dev/null
+++ 
b/diagnostic/core/src/main/java/org/apache/karaf/diagnostic/common/FeaturesDumpProvider.java
@@ -0,0 +1,78 @@
+/*
+ * 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.diagnostic.common;
+
+import java.io.OutputStreamWriter;
+
+import org.apache.karaf.features.BundleInfo;
+import org.apache.karaf.features.Feature;
+import org.apache.karaf.features.FeaturesService;
+import org.apache.karaf.features.Repository;
+
+/**
+ * Dump provider which add file named features.txt with informations
+ * about installed features and repositories.
+ */
+public class FeaturesDumpProvider extends TextDumpProvider {
+
+    /**
+     * Feature service.
+     */
+    private final FeaturesService features;
+
+    /**
+     * Creates new dump entry witch contains information about
+     * karaf features.
+     * 
+     * @param features Feature service.
+     */
+    public FeaturesDumpProvider(FeaturesService features) {
+        super("features.txt");
+        this.features = features;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    protected void writeDump(OutputStreamWriter outputStreamWriter) throws 
Exception {
+        // creates header
+        outputStreamWriter.write("Repositories:\n");
+
+        // list repositories
+        for (Repository repo : features.listRepositories()) {
+            outputStreamWriter.write(repo.getURI() + " (" + repo.getName() + 
")\n");
+        }
+
+        // list features
+        outputStreamWriter.write("\nfeatures:\n");
+        for (Feature feature : features.listFeatures()) {
+            outputStreamWriter.write(feature.getName() + " " + 
feature.getVersion());
+            outputStreamWriter.write(" installed: " + 
features.isInstalled(feature));
+            outputStreamWriter.write("\nBundles:\n");
+            for (BundleInfo bundle : feature.getBundles()) {
+                outputStreamWriter.write("\t" + bundle.getLocation());
+                if (bundle.getStartLevel() != 0) {
+                    outputStreamWriter.write(" start level " + 
bundle.getStartLevel());
+                }
+                outputStreamWriter.write("\n\n");
+            }
+        }
+
+        // flush & close stream
+        outputStreamWriter.close();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/e55fd0a0/diagnostic/core/src/main/java/org/apache/karaf/diagnostic/common/LogDumpProvider.java
----------------------------------------------------------------------
diff --git 
a/diagnostic/core/src/main/java/org/apache/karaf/diagnostic/common/LogDumpProvider.java
 
b/diagnostic/core/src/main/java/org/apache/karaf/diagnostic/common/LogDumpProvider.java
new file mode 100644
index 0000000..9fcd44a
--- /dev/null
+++ 
b/diagnostic/core/src/main/java/org/apache/karaf/diagnostic/common/LogDumpProvider.java
@@ -0,0 +1,81 @@
+/*
+ * 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.diagnostic.common;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.OutputStream;
+import java.util.Dictionary;
+import java.util.Enumeration;
+
+import org.apache.karaf.diagnostic.core.DumpDestination;
+import org.apache.karaf.diagnostic.core.DumpProvider;
+import org.apache.karaf.util.StreamUtils;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceReference;
+import org.osgi.service.cm.Configuration;
+import org.osgi.service.cm.ConfigurationAdmin;
+
+/**
+ * Dump provider which copies log files from data/log directory to
+ * destination.
+ */
+public class LogDumpProvider implements DumpProvider {
+
+    private final BundleContext bundleContext;
+
+    public LogDumpProvider(BundleContext bundleContext) {
+        this.bundleContext = bundleContext;
+    }
+
+    /**
+     * Attach log entries from directory.
+     */
+    public void createDump(DumpDestination destination) throws Exception {
+        // get the ConfigAdmin service
+        ServiceReference ref = 
bundleContext.getServiceReference(ConfigurationAdmin.class.getName());
+        if (ref == null) {
+            return;
+        }
+
+        // get the PAX Logging configuration
+        ConfigurationAdmin configurationAdmin = (ConfigurationAdmin) 
bundleContext.getService(ref);
+        try {
+            Configuration configuration = 
configurationAdmin.getConfiguration("org.ops4j.pax.logging");
+
+            // get the ".file" Pax Logging properties
+            Dictionary dictionary = configuration.getProperties();
+            for (Enumeration e = dictionary.keys(); e.hasMoreElements(); ) {
+                String property = (String) e.nextElement();
+                if (property.endsWith(".file")) {
+                    // it's a file appender, get the file location
+                    String location = (String) dictionary.get(property);
+                    File file = new File(location);
+                    if (file.exists()) {
+                        FileInputStream inputStream = new 
FileInputStream(file);
+                        OutputStream outputStream = destination.add("log/" + 
file.getName());
+                        StreamUtils.copy(inputStream, outputStream);
+                    }
+                }
+            }
+        } catch (Exception e) {
+            throw e;
+        } finally {
+            bundleContext.ungetService(ref);
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/e55fd0a0/diagnostic/core/src/main/java/org/apache/karaf/diagnostic/common/TextDumpProvider.java
----------------------------------------------------------------------
diff --git 
a/diagnostic/core/src/main/java/org/apache/karaf/diagnostic/common/TextDumpProvider.java
 
b/diagnostic/core/src/main/java/org/apache/karaf/diagnostic/common/TextDumpProvider.java
new file mode 100644
index 0000000..52f2289
--- /dev/null
+++ 
b/diagnostic/core/src/main/java/org/apache/karaf/diagnostic/common/TextDumpProvider.java
@@ -0,0 +1,66 @@
+/*
+ * 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.diagnostic.common;
+
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+
+import org.apache.karaf.diagnostic.core.DumpDestination;
+import org.apache.karaf.diagnostic.core.DumpProvider;
+
+/**
+ * Base class for dump providers which writes text to destination.
+ */
+public abstract class TextDumpProvider implements DumpProvider {
+
+    /**
+     * Name of the file.
+     */
+    private final String name;
+
+    /**
+     * Creates new dump provider.
+     * 
+     * @param name Name of the file.
+     */
+    protected TextDumpProvider(String name) {
+        this.name = name;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public final void createDump(DumpDestination destination) throws Exception 
{
+        OutputStream outputStream = destination.add(name);
+        OutputStreamWriter outputStreamWriter = new 
OutputStreamWriter(outputStream);
+        try {
+            writeDump(outputStreamWriter);
+        } finally {
+            outputStreamWriter.close();
+            outputStream.close();
+        }
+    }
+
+    /**
+     * This method should create output.
+     * 
+     * @param outputStreamWriter Stream which points to file specified in 
constructor.
+     * @throws Exception If any problem occur.
+     */
+    protected abstract void writeDump(OutputStreamWriter outputStreamWriter) 
throws Exception;
+
+}

Reply via email to