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/09/09 17:16:27 UTC

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

Repository: karaf
Updated Branches:
  refs/heads/karaf-2.x 4fd235fd0 -> c3fb61914


http://git-wip-us.apache.org/repos/asf/karaf/blob/c3fb6191/diagnostic/core/src/main/java/org/apache/karaf/diagnostic/core/providers/EnvironmentDumpProvider.java
----------------------------------------------------------------------
diff --git a/diagnostic/core/src/main/java/org/apache/karaf/diagnostic/core/providers/EnvironmentDumpProvider.java b/diagnostic/core/src/main/java/org/apache/karaf/diagnostic/core/providers/EnvironmentDumpProvider.java
new file mode 100644
index 0000000..d6b76af
--- /dev/null
+++ b/diagnostic/core/src/main/java/org/apache/karaf/diagnostic/core/providers/EnvironmentDumpProvider.java
@@ -0,0 +1,291 @@
+/*
+ * 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;
+import org.osgi.framework.Version;
+
+/**
+ * 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/c3fb6191/diagnostic/core/src/main/java/org/apache/karaf/diagnostic/core/providers/HeapDumpProvider.java
----------------------------------------------------------------------
diff --git a/diagnostic/core/src/main/java/org/apache/karaf/diagnostic/core/providers/HeapDumpProvider.java b/diagnostic/core/src/main/java/org/apache/karaf/diagnostic/core/providers/HeapDumpProvider.java
new file mode 100644
index 0000000..6a6f040
--- /dev/null
+++ b/diagnostic/core/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/c3fb6191/diagnostic/core/src/main/java/org/apache/karaf/diagnostic/core/providers/MemoryDumpProvider.java
----------------------------------------------------------------------
diff --git a/diagnostic/core/src/main/java/org/apache/karaf/diagnostic/core/providers/MemoryDumpProvider.java b/diagnostic/core/src/main/java/org/apache/karaf/diagnostic/core/providers/MemoryDumpProvider.java
new file mode 100644
index 0000000..3711630
--- /dev/null
+++ b/diagnostic/core/src/main/java/org/apache/karaf/diagnostic/core/providers/MemoryDumpProvider.java
@@ -0,0 +1,56 @@
+/*
+ * 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 org.apache.karaf.diagnostic.core.common.TextDumpProvider;
+
+import java.io.OutputStreamWriter;
+import java.lang.management.ManagementFactory;
+import java.lang.management.MemoryMXBean;
+
+/**
+ * Provider for memory information in memory.txt.
+ */
+public class MemoryDumpProvider extends TextDumpProvider {
+
+    /**
+     * Create a new dump entry which contains information about memory usage.
+     */
+    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/c3fb6191/diagnostic/core/src/main/java/org/apache/karaf/diagnostic/core/providers/ThreadDumpProvider.java
----------------------------------------------------------------------
diff --git a/diagnostic/core/src/main/java/org/apache/karaf/diagnostic/core/providers/ThreadDumpProvider.java b/diagnostic/core/src/main/java/org/apache/karaf/diagnostic/core/providers/ThreadDumpProvider.java
new file mode 100644
index 0000000..6b5a882
--- /dev/null
+++ b/diagnostic/core/src/main/java/org/apache/karaf/diagnostic/core/providers/ThreadDumpProvider.java
@@ -0,0 +1,117 @@
+/*
+ * 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/c3fb6191/diagnostic/management/src/main/java/org/apache/karaf/diagnostic/management/internal/DiagnosticDumpMBeanImpl.java
----------------------------------------------------------------------
diff --git a/diagnostic/management/src/main/java/org/apache/karaf/diagnostic/management/internal/DiagnosticDumpMBeanImpl.java b/diagnostic/management/src/main/java/org/apache/karaf/diagnostic/management/internal/DiagnosticDumpMBeanImpl.java
index aa850b1..339846b 100644
--- a/diagnostic/management/src/main/java/org/apache/karaf/diagnostic/management/internal/DiagnosticDumpMBeanImpl.java
+++ b/diagnostic/management/src/main/java/org/apache/karaf/diagnostic/management/internal/DiagnosticDumpMBeanImpl.java
@@ -14,16 +14,14 @@
 package org.apache.karaf.diagnostic.management.internal;
 
 import java.io.File;
-import java.util.List;
 
 import javax.management.NotCompliantMBeanException;
 import javax.management.StandardMBean;
 
+import org.apache.karaf.diagnostic.core.Dump;
 import org.apache.karaf.diagnostic.core.DumpDestination;
-import org.apache.karaf.diagnostic.core.DumpProvider;
-import org.apache.karaf.diagnostic.core.common.DirectoryDumpDestination;
-import org.apache.karaf.diagnostic.core.common.ZipDumpDestination;
 import org.apache.karaf.diagnostic.management.DiagnosticDumpMBean;
+import org.osgi.framework.BundleContext;
 
 /**
  * Implementation of diagnostic mbean.
@@ -34,7 +32,7 @@ public class DiagnosticDumpMBeanImpl extends StandardMBean implements
     /**
      * Dump providers.
      */
-    private List<DumpProvider> providers;
+    private BundleContext bundleContext;
 
     /**
      * Creates new diagnostic mbean.
@@ -62,25 +60,18 @@ public class DiagnosticDumpMBeanImpl extends StandardMBean implements
 
         DumpDestination destination;
         if (directory) {
-            destination = new DirectoryDumpDestination(target);
+            destination = Dump.directory(target);
         } else {
-            destination = new ZipDumpDestination(target);
+            destination = Dump.zip(target);
         }
 
-        for (DumpProvider provider : providers) {
-            provider.createDump(destination);
-        }
-
-        destination.save();
+        Dump.dump(bundleContext, destination);
     }
 
     /**
-     * Sets dump providers.
-     * 
-     * @param providers Dump providers. 
+     * Sets the bundle context
      */
-    public void setProviders(List<DumpProvider> providers) {
-        this.providers = providers;
+    public void setBundleContext(BundleContext bundleContext) {
+        this.bundleContext = bundleContext;
     }
-
 }

http://git-wip-us.apache.org/repos/asf/karaf/blob/c3fb6191/diagnostic/management/src/main/resources/OSGI-INF/blueprint/diagnostic-management.xml
----------------------------------------------------------------------
diff --git a/diagnostic/management/src/main/resources/OSGI-INF/blueprint/diagnostic-management.xml b/diagnostic/management/src/main/resources/OSGI-INF/blueprint/diagnostic-management.xml
index 1ff894b..1f1cf13 100644
--- a/diagnostic/management/src/main/resources/OSGI-INF/blueprint/diagnostic-management.xml
+++ b/diagnostic/management/src/main/resources/OSGI-INF/blueprint/diagnostic-management.xml
@@ -19,15 +19,12 @@
 -->
 <blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0" default-activation="eager">
 
-    <reference-list id="providers" availability="optional"
-        interface="org.apache.karaf.diagnostic.core.DumpProvider" />
-
     <reference id="mbeanServer" interface="javax.management.MBeanServer">
         <reference-listener ref="mbeanRegister" bind-method="registerMBeanServer" unbind-method="unregisterMBeanServer" />
     </reference>
 
     <bean id="mbeanImpl" class="org.apache.karaf.diagnostic.management.internal.DiagnosticDumpMBeanImpl">
-        <property name="providers" ref="providers" />
+        <property name="bundleContext" ref="blueprintBundleContext" />
     </bean>
 
     <bean id="mbeanRegister" class="org.apache.karaf.management.MBeanRegistrer" init-method="init" destroy-method="destroy">


[2/2] git commit: [KARAF-3205] Refactor create-dump to be more low level

Posted by gn...@apache.org.
[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/c3fb6191
Tree: http://git-wip-us.apache.org/repos/asf/karaf/tree/c3fb6191
Diff: http://git-wip-us.apache.org/repos/asf/karaf/diff/c3fb6191

Branch: refs/heads/karaf-2.x
Commit: c3fb61914b2147f8607cca8e15b8e7c5016858cc
Parents: 4fd235f
Author: Guillaume Nodet <gn...@gmail.com>
Authored: Tue Sep 9 17:16:13 2014 +0200
Committer: Guillaume Nodet <gn...@gmail.com>
Committed: Tue Sep 9 17:16:13 2014 +0200

----------------------------------------------------------------------
 .../src/main/descriptors/unix-bin-release.xml   |   2 +-
 .../src/main/descriptors/unix-bin-snapshot.xml  |   2 +-
 .../descriptors/unix-minimal-bin-release.xml    |  12 +-
 .../descriptors/unix-minimal-bin-snapshot.xml   |  12 +-
 .../main/descriptors/windows-bin-release.xml    |   2 +-
 .../main/descriptors/windows-bin-snapshot.xml   |   2 +-
 .../descriptors/windows-minimal-bin-release.xml |  12 +-
 .../windows-minimal-bin-snapshot.xml            |  12 +-
 .../filtered-resources/etc/config.properties    |   1 +
 .../etc/org.apache.karaf.features.cfg           |   8 +-
 .../minimal/org.apache.karaf.features.cfg       |   4 +-
 .../standard/src/main/resources/features.xml    |   1 -
 .../karaf/diagnostic/command/DumpCommand.java   |  34 +--
 .../OSGI-INF/blueprint/shell-diagnostic.xml     |   6 +-
 .../diagnostic/common/BundleDumpProvider.java   |  85 ------
 .../common/EnvironmentDumpProvider.java         | 291 -------------------
 .../diagnostic/common/FeaturesDumpProvider.java |  61 ++--
 .../diagnostic/common/HeapDumpProvider.java     |  71 -----
 .../diagnostic/common/LogDumpProvider.java      |   6 +-
 .../diagnostic/common/MemoryDumpProvider.java   |  56 ----
 .../diagnostic/common/TextDumpProvider.java     |  65 +++++
 .../diagnostic/common/ThreadDumpProvider.java   | 117 --------
 .../OSGI-INF/blueprint/diagnostic-services.xml  |  26 +-
 diagnostic/core/pom.xml                         |  18 +-
 .../org/apache/karaf/diagnostic/core/Dump.java  |  85 ++++++
 .../core/common/DirectoryDumpDestination.java   |   6 +-
 .../core/common/ZipDumpDestination.java         |   9 +-
 .../diagnostic/core/internal/Activator.java     |  54 ++++
 .../core/providers/BundleDumpProvider.java      |  85 ++++++
 .../core/providers/EnvironmentDumpProvider.java | 291 +++++++++++++++++++
 .../core/providers/HeapDumpProvider.java        |  68 +++++
 .../core/providers/MemoryDumpProvider.java      |  56 ++++
 .../core/providers/ThreadDumpProvider.java      | 117 ++++++++
 .../internal/DiagnosticDumpMBeanImpl.java       |  27 +-
 .../blueprint/diagnostic-management.xml         |   5 +-
 35 files changed, 965 insertions(+), 744 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/karaf/blob/c3fb6191/assemblies/apache-karaf/src/main/descriptors/unix-bin-release.xml
----------------------------------------------------------------------
diff --git a/assemblies/apache-karaf/src/main/descriptors/unix-bin-release.xml b/assemblies/apache-karaf/src/main/descriptors/unix-bin-release.xml
index dde08b2..f46482f 100644
--- a/assemblies/apache-karaf/src/main/descriptors/unix-bin-release.xml
+++ b/assemblies/apache-karaf/src/main/descriptors/unix-bin-release.xml
@@ -106,6 +106,7 @@
             <includes>
                 <include>org.apache.servicemix.specs:org.apache.servicemix.specs.activator</include>
                 <include>org.apache.servicemix.specs:org.apache.servicemix.specs.locator</include>
+                <include>org.apache.karaf.diagnostic:org.apache.karaf.diagnostic.core</include>
             </includes>
         </dependencySet>
 
@@ -216,7 +217,6 @@
                 org/apache/karaf/diagnostic/${artifact.artifactId}/${artifact.baseVersion}/${artifact.artifactId}-${artifact.baseVersion}${dashClassifier?}.${artifact.extension}
             </outputFileNameMapping>
             <includes>
-                <include>org.apache.karaf.diagnostic:org.apache.karaf.diagnostic.core</include>
                 <include>org.apache.karaf.diagnostic:org.apache.karaf.diagnostic.common</include>
                 <include>org.apache.karaf.diagnostic:org.apache.karaf.diagnostic.command</include>
                 <include>org.apache.karaf.diagnostic:org.apache.karaf.diagnostic.management</include>

http://git-wip-us.apache.org/repos/asf/karaf/blob/c3fb6191/assemblies/apache-karaf/src/main/descriptors/unix-bin-snapshot.xml
----------------------------------------------------------------------
diff --git a/assemblies/apache-karaf/src/main/descriptors/unix-bin-snapshot.xml b/assemblies/apache-karaf/src/main/descriptors/unix-bin-snapshot.xml
index 1213fab..c1a4bfc 100644
--- a/assemblies/apache-karaf/src/main/descriptors/unix-bin-snapshot.xml
+++ b/assemblies/apache-karaf/src/main/descriptors/unix-bin-snapshot.xml
@@ -106,6 +106,7 @@
             <includes>
                 <include>org.apache.servicemix.specs:org.apache.servicemix.specs.activator</include>
                 <include>org.apache.servicemix.specs:org.apache.servicemix.specs.locator</include>
+                <include>org.apache.karaf.diagnostic:org.apache.karaf.diagnostic.core</include>
             </includes>
         </dependencySet>
 
@@ -226,7 +227,6 @@
                 org/apache/karaf/diagnostic/${artifact.artifactId}/${artifact.baseVersion}/${artifact.artifactId}-${artifact.baseVersion}${dashClassifier?}.${artifact.extension}
             </outputFileNameMapping>
             <includes>
-                <include>org.apache.karaf.diagnostic:org.apache.karaf.diagnostic.core</include>
                 <include>org.apache.karaf.diagnostic:org.apache.karaf.diagnostic.common</include>
                 <include>org.apache.karaf.diagnostic:org.apache.karaf.diagnostic.command</include>
                 <include>org.apache.karaf.diagnostic:org.apache.karaf.diagnostic.management</include>

http://git-wip-us.apache.org/repos/asf/karaf/blob/c3fb6191/assemblies/apache-karaf/src/main/descriptors/unix-minimal-bin-release.xml
----------------------------------------------------------------------
diff --git a/assemblies/apache-karaf/src/main/descriptors/unix-minimal-bin-release.xml b/assemblies/apache-karaf/src/main/descriptors/unix-minimal-bin-release.xml
index 8396452..7a1576f 100644
--- a/assemblies/apache-karaf/src/main/descriptors/unix-minimal-bin-release.xml
+++ b/assemblies/apache-karaf/src/main/descriptors/unix-minimal-bin-release.xml
@@ -101,6 +101,17 @@
 
     <dependencySets>
         <dependencySet>
+            <outputDirectory>/lib</outputDirectory>
+            <unpack>false</unpack>
+            <useProjectArtifact>false</useProjectArtifact>
+            <includes>
+                <include>org.apache.servicemix.specs:org.apache.servicemix.specs.activator</include>
+                <include>org.apache.servicemix.specs:org.apache.servicemix.specs.locator</include>
+                <include>org.apache.karaf.diagnostic:org.apache.karaf.diagnostic.core</include>
+            </includes>
+        </dependencySet>
+
+        <dependencySet>
             <outputDirectory>/lib/endorsed</outputDirectory>
             <unpack>false</unpack>
             <useProjectArtifact>false</useProjectArtifact>
@@ -228,7 +239,6 @@
                 org/apache/karaf/diagnostic/${artifact.artifactId}/${artifact.baseVersion}/${artifact.artifactId}-${artifact.baseVersion}${dashClassifier?}.${artifact.extension}
             </outputFileNameMapping>
             <includes>
-                <include>org.apache.karaf.diagnostic:org.apache.karaf.diagnostic.core</include>
                 <include>org.apache.karaf.diagnostic:org.apache.karaf.diagnostic.common</include>
                 <include>org.apache.karaf.diagnostic:org.apache.karaf.diagnostic.command</include>
                 <include>org.apache.karaf.diagnostic:org.apache.karaf.diagnostic.management</include>

http://git-wip-us.apache.org/repos/asf/karaf/blob/c3fb6191/assemblies/apache-karaf/src/main/descriptors/unix-minimal-bin-snapshot.xml
----------------------------------------------------------------------
diff --git a/assemblies/apache-karaf/src/main/descriptors/unix-minimal-bin-snapshot.xml b/assemblies/apache-karaf/src/main/descriptors/unix-minimal-bin-snapshot.xml
index 3e5e7e8..3428108 100644
--- a/assemblies/apache-karaf/src/main/descriptors/unix-minimal-bin-snapshot.xml
+++ b/assemblies/apache-karaf/src/main/descriptors/unix-minimal-bin-snapshot.xml
@@ -101,6 +101,17 @@
 
     <dependencySets>
         <dependencySet>
+            <outputDirectory>/lib</outputDirectory>
+            <unpack>false</unpack>
+            <useProjectArtifact>false</useProjectArtifact>
+            <includes>
+                <include>org.apache.servicemix.specs:org.apache.servicemix.specs.activator</include>
+                <include>org.apache.servicemix.specs:org.apache.servicemix.specs.locator</include>
+                <include>org.apache.karaf.diagnostic:org.apache.karaf.diagnostic.core</include>
+            </includes>
+        </dependencySet>
+
+        <dependencySet>
             <outputDirectory>/lib/endorsed</outputDirectory>
             <unpack>false</unpack>
             <useProjectArtifact>false</useProjectArtifact>
@@ -228,7 +239,6 @@
                 org/apache/karaf/diagnostic/${artifact.artifactId}/${artifact.baseVersion}/${artifact.artifactId}-${artifact.baseVersion}${dashClassifier?}.${artifact.extension}
             </outputFileNameMapping>
             <includes>
-                <include>org.apache.karaf.diagnostic:org.apache.karaf.diagnostic.core</include>
                 <include>org.apache.karaf.diagnostic:org.apache.karaf.diagnostic.common</include>
                 <include>org.apache.karaf.diagnostic:org.apache.karaf.diagnostic.command</include>
                 <include>org.apache.karaf.diagnostic:org.apache.karaf.diagnostic.management</include>

http://git-wip-us.apache.org/repos/asf/karaf/blob/c3fb6191/assemblies/apache-karaf/src/main/descriptors/windows-bin-release.xml
----------------------------------------------------------------------
diff --git a/assemblies/apache-karaf/src/main/descriptors/windows-bin-release.xml b/assemblies/apache-karaf/src/main/descriptors/windows-bin-release.xml
index 52a580e..90a5b34 100644
--- a/assemblies/apache-karaf/src/main/descriptors/windows-bin-release.xml
+++ b/assemblies/apache-karaf/src/main/descriptors/windows-bin-release.xml
@@ -114,6 +114,7 @@
             <includes>
                 <include>org.apache.servicemix.specs:org.apache.servicemix.specs.activator</include>
                 <include>org.apache.servicemix.specs:org.apache.servicemix.specs.locator</include>
+                <include>org.apache.karaf.diagnostic:org.apache.karaf.diagnostic.core</include>
             </includes>
         </dependencySet>
 
@@ -234,7 +235,6 @@
                 org/apache/karaf/diagnostic/${artifact.artifactId}/${artifact.baseVersion}/${artifact.artifactId}-${artifact.baseVersion}${dashClassifier?}.${artifact.extension}
             </outputFileNameMapping>
             <includes>
-                <include>org.apache.karaf.diagnostic:org.apache.karaf.diagnostic.core</include>
                 <include>org.apache.karaf.diagnostic:org.apache.karaf.diagnostic.common</include>
                 <include>org.apache.karaf.diagnostic:org.apache.karaf.diagnostic.command</include>
                 <include>org.apache.karaf.diagnostic:org.apache.karaf.diagnostic.management</include>

http://git-wip-us.apache.org/repos/asf/karaf/blob/c3fb6191/assemblies/apache-karaf/src/main/descriptors/windows-bin-snapshot.xml
----------------------------------------------------------------------
diff --git a/assemblies/apache-karaf/src/main/descriptors/windows-bin-snapshot.xml b/assemblies/apache-karaf/src/main/descriptors/windows-bin-snapshot.xml
index 6635b1b..ae67c2e 100644
--- a/assemblies/apache-karaf/src/main/descriptors/windows-bin-snapshot.xml
+++ b/assemblies/apache-karaf/src/main/descriptors/windows-bin-snapshot.xml
@@ -114,6 +114,7 @@
             <includes>
                 <include>org.apache.servicemix.specs:org.apache.servicemix.specs.activator</include>
                 <include>org.apache.servicemix.specs:org.apache.servicemix.specs.locator</include>
+                <include>org.apache.karaf.diagnostic:org.apache.karaf.diagnostic.core</include>
             </includes>
         </dependencySet>
 
@@ -234,7 +235,6 @@
                 org/apache/karaf/diagnostic/${artifact.artifactId}/${artifact.baseVersion}/${artifact.artifactId}-${artifact.baseVersion}${dashClassifier?}.${artifact.extension}
             </outputFileNameMapping>
             <includes>
-                <include>org.apache.karaf.diagnostic:org.apache.karaf.diagnostic.core</include>
                 <include>org.apache.karaf.diagnostic:org.apache.karaf.diagnostic.common</include>
                 <include>org.apache.karaf.diagnostic:org.apache.karaf.diagnostic.command</include>
                 <include>org.apache.karaf.diagnostic:org.apache.karaf.diagnostic.management</include>

http://git-wip-us.apache.org/repos/asf/karaf/blob/c3fb6191/assemblies/apache-karaf/src/main/descriptors/windows-minimal-bin-release.xml
----------------------------------------------------------------------
diff --git a/assemblies/apache-karaf/src/main/descriptors/windows-minimal-bin-release.xml b/assemblies/apache-karaf/src/main/descriptors/windows-minimal-bin-release.xml
index 9a7d78d..83c419f 100644
--- a/assemblies/apache-karaf/src/main/descriptors/windows-minimal-bin-release.xml
+++ b/assemblies/apache-karaf/src/main/descriptors/windows-minimal-bin-release.xml
@@ -108,6 +108,17 @@
 
     <dependencySets>
         <dependencySet>
+            <outputDirectory>/lib</outputDirectory>
+            <unpack>false</unpack>
+            <useProjectArtifact>false</useProjectArtifact>
+            <includes>
+                <include>org.apache.servicemix.specs:org.apache.servicemix.specs.activator</include>
+                <include>org.apache.servicemix.specs:org.apache.servicemix.specs.locator</include>
+                <include>org.apache.karaf.diagnostic:org.apache.karaf.diagnostic.core</include>
+            </includes>
+        </dependencySet>
+
+        <dependencySet>
             <outputDirectory>/lib/endorsed</outputDirectory>
             <unpack>false</unpack>
             <useProjectArtifact>false</useProjectArtifact>
@@ -218,7 +229,6 @@
                 org/apache/karaf/diagnostic/${artifact.artifactId}/${artifact.baseVersion}/${artifact.artifactId}-${artifact.baseVersion}${dashClassifier?}.${artifact.extension}
             </outputFileNameMapping>
             <includes>
-                <include>org.apache.karaf.diagnostic:org.apache.karaf.diagnostic.core</include>
                 <include>org.apache.karaf.diagnostic:org.apache.karaf.diagnostic.common</include>
                 <include>org.apache.karaf.diagnostic:org.apache.karaf.diagnostic.command</include>
                 <include>org.apache.karaf.diagnostic:org.apache.karaf.diagnostic.management</include>

http://git-wip-us.apache.org/repos/asf/karaf/blob/c3fb6191/assemblies/apache-karaf/src/main/descriptors/windows-minimal-bin-snapshot.xml
----------------------------------------------------------------------
diff --git a/assemblies/apache-karaf/src/main/descriptors/windows-minimal-bin-snapshot.xml b/assemblies/apache-karaf/src/main/descriptors/windows-minimal-bin-snapshot.xml
index 857bcad..e710293 100644
--- a/assemblies/apache-karaf/src/main/descriptors/windows-minimal-bin-snapshot.xml
+++ b/assemblies/apache-karaf/src/main/descriptors/windows-minimal-bin-snapshot.xml
@@ -108,6 +108,17 @@
 
     <dependencySets>
         <dependencySet>
+            <outputDirectory>/lib</outputDirectory>
+            <unpack>false</unpack>
+            <useProjectArtifact>false</useProjectArtifact>
+            <includes>
+                <include>org.apache.servicemix.specs:org.apache.servicemix.specs.activator</include>
+                <include>org.apache.servicemix.specs:org.apache.servicemix.specs.locator</include>
+                <include>org.apache.karaf.diagnostic:org.apache.karaf.diagnostic.core</include>
+            </includes>
+        </dependencySet>
+
+        <dependencySet>
             <outputDirectory>/lib/endorsed</outputDirectory>
             <unpack>false</unpack>
             <useProjectArtifact>false</useProjectArtifact>
@@ -218,7 +229,6 @@
                 org/apache/karaf/diagnostic/${artifact.artifactId}/${artifact.baseVersion}/${artifact.artifactId}-${artifact.baseVersion}${dashClassifier?}.${artifact.extension}
             </outputFileNameMapping>
             <includes>
-                <include>org.apache.karaf.diagnostic:org.apache.karaf.diagnostic.core</include>
                 <include>org.apache.karaf.diagnostic:org.apache.karaf.diagnostic.common</include>
                 <include>org.apache.karaf.diagnostic:org.apache.karaf.diagnostic.command</include>
                 <include>org.apache.karaf.diagnostic:org.apache.karaf.diagnostic.management</include>

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

http://git-wip-us.apache.org/repos/asf/karaf/blob/c3fb6191/assemblies/apache-karaf/src/main/filtered-resources/etc/org.apache.karaf.features.cfg
----------------------------------------------------------------------
diff --git a/assemblies/apache-karaf/src/main/filtered-resources/etc/org.apache.karaf.features.cfg b/assemblies/apache-karaf/src/main/filtered-resources/etc/org.apache.karaf.features.cfg
index cfa3123..349f8d9 100644
--- a/assemblies/apache-karaf/src/main/filtered-resources/etc/org.apache.karaf.features.cfg
+++ b/assemblies/apache-karaf/src/main/filtered-resources/etc/org.apache.karaf.features.cfg
@@ -17,7 +17,11 @@
 #
 ################################################################################
 
-respectStartLvlDuringFeatureStartup = false
+#
+# Defines if the startlvl should be respected during feature startup. The default value is for 3.x is true.
+# The default behavior for 2.x is false (!) for this property
+#
+#respectStartLvlDuringFeatureStartup = false
 
 #
 # Comma separated list of features repositories to register by default
@@ -27,7 +31,7 @@ featuresRepositories = mvn:org.apache.karaf.assemblies.features/standard/${proje
 #
 # Comma separated list of features to install at startup
 #
-featuresBoot = karaf-framework,service-security,admin,config,ssh,management,kar,deployer,diagnostic
+featuresBoot = karaf-framework,shell,features,service-security,admin,config,ssh,management,kar,deployer,diagnostic
 
 #
 # Defines if the boot features are started in asynchronous mode (in a dedicated thread)

http://git-wip-us.apache.org/repos/asf/karaf/blob/c3fb6191/assemblies/apache-karaf/src/main/filtered-resources/minimal/org.apache.karaf.features.cfg
----------------------------------------------------------------------
diff --git a/assemblies/apache-karaf/src/main/filtered-resources/minimal/org.apache.karaf.features.cfg b/assemblies/apache-karaf/src/main/filtered-resources/minimal/org.apache.karaf.features.cfg
index 7916c10..569805b 100644
--- a/assemblies/apache-karaf/src/main/filtered-resources/minimal/org.apache.karaf.features.cfg
+++ b/assemblies/apache-karaf/src/main/filtered-resources/minimal/org.apache.karaf.features.cfg
@@ -27,12 +27,12 @@
 # Comma separated list of features repositories to register by default
 #
 #
-featuresRepositories = mvn:org.apache.karaf.assemblies.features/standard/${project.version}/xml/features,mvn:org.apache.karaf.assemblies.features/enterprise/${project.version}/xml/features
+featuresRepositories = mvn:org.apache.karaf.assemblies.features/standard/${project.version}/xml/features,mvn:org.apache.karaf.assemblies.features/spring/${project.version}/xml/features,mvn:org.apache.karaf.assemblies.features/enterprise/${project.version}/xml/features
 
 #
 # Comma separated list of features to install at startup
 #
-featuresBoot = karaf-framework
+featuresBoot = karaf-framework,shell,features
 
 #
 # Defines if the boot features are started in asynchronous mode (in a dedicated thread)

http://git-wip-us.apache.org/repos/asf/karaf/blob/c3fb6191/assemblies/features/standard/src/main/resources/features.xml
----------------------------------------------------------------------
diff --git a/assemblies/features/standard/src/main/resources/features.xml b/assemblies/features/standard/src/main/resources/features.xml
index f94f165..587bd1d 100644
--- a/assemblies/features/standard/src/main/resources/features.xml
+++ b/assemblies/features/standard/src/main/resources/features.xml
@@ -85,7 +85,6 @@
 
     <feature name="diagnostic" description="Diagnostic support" version="${project.version}">
         <feature>aries-blueprint</feature>
-        <bundle start-level="30">mvn:org.apache.karaf.diagnostic/org.apache.karaf.diagnostic.core/${project.version}</bundle>
         <bundle start-level="30">mvn:org.apache.karaf.diagnostic/org.apache.karaf.diagnostic.common/${project.version}</bundle>
         <conditional>
             <condition>shell</condition>

http://git-wip-us.apache.org/repos/asf/karaf/blob/c3fb6191/diagnostic/command/src/main/java/org/apache/karaf/diagnostic/command/DumpCommand.java
----------------------------------------------------------------------
diff --git a/diagnostic/command/src/main/java/org/apache/karaf/diagnostic/command/DumpCommand.java b/diagnostic/command/src/main/java/org/apache/karaf/diagnostic/command/DumpCommand.java
index 88ec298..75ff321 100644
--- a/diagnostic/command/src/main/java/org/apache/karaf/diagnostic/command/DumpCommand.java
+++ b/diagnostic/command/src/main/java/org/apache/karaf/diagnostic/command/DumpCommand.java
@@ -19,17 +19,14 @@ package org.apache.karaf.diagnostic.command;
 import java.io.File;
 import java.text.SimpleDateFormat;
 import java.util.Date;
-import java.util.LinkedList;
-import java.util.List;
 
 import org.apache.felix.gogo.commands.Argument;
 import org.apache.felix.gogo.commands.Command;
 import org.apache.felix.gogo.commands.Option;
+import org.apache.karaf.diagnostic.core.Dump;
 import org.apache.karaf.diagnostic.core.DumpDestination;
-import org.apache.karaf.diagnostic.core.DumpProvider;
-import org.apache.karaf.diagnostic.core.common.DirectoryDumpDestination;
-import org.apache.karaf.diagnostic.core.common.ZipDumpDestination;
 import org.apache.karaf.shell.console.OsgiCommandSupport;
+import org.osgi.framework.BundleContext;
 
 /**
  * Command to create dump from shell.
@@ -38,9 +35,9 @@ import org.apache.karaf.shell.console.OsgiCommandSupport;
 public class DumpCommand extends OsgiCommandSupport {
 
     /**
-     * Registered dump providers.
+     * Bundle Context
      */
-    private List<DumpProvider> providers = new LinkedList<DumpProvider>();
+    private BundleContext bundleContext;
 
     /**
      * Output format of the filename if not defined otherwise
@@ -63,11 +60,6 @@ public class DumpCommand extends OsgiCommandSupport {
     protected Object doExecute() throws Exception {
         DumpDestination destination;
 
-        if (providers.isEmpty()) {
-            session.getConsole().println("Unable to create dump. No providers were found");
-            return null;
-        }
-
         // create default file name if none provided
         if (fileName == null || fileName.trim().length() == 0) {
             fileName = dumpFormat.format(new Date());
@@ -79,26 +71,18 @@ public class DumpCommand extends OsgiCommandSupport {
 
         // if directory switch is on, create dump in directory
         if (directory) {
-            destination = new DirectoryDumpDestination(target);
+            destination = Dump.directory(target);
         } else {
-            destination = new ZipDumpDestination(target);
+            destination = Dump.zip(target);
         }
 
-        for (DumpProvider provider : providers) {
-            provider.createDump(destination);
-        }
-        destination.save();
+        Dump.dump(bundleContext, destination);
         session.getConsole().println("Diagnostic dump created.");
 
         return null;
     }
 
-    /**
-     * Sets dump providers to use.
-     * 
-     * @param providers Providers.
-     */
-    public void setProviders(List<DumpProvider> providers) {
-        this.providers = providers;
+    public void setBundleContext(BundleContext bundleContext) {
+        this.bundleContext = bundleContext;
     }
 }

http://git-wip-us.apache.org/repos/asf/karaf/blob/c3fb6191/diagnostic/command/src/main/resources/OSGI-INF/blueprint/shell-diagnostic.xml
----------------------------------------------------------------------
diff --git a/diagnostic/command/src/main/resources/OSGI-INF/blueprint/shell-diagnostic.xml b/diagnostic/command/src/main/resources/OSGI-INF/blueprint/shell-diagnostic.xml
index dcb3bb4..4c7a61b 100644
--- a/diagnostic/command/src/main/resources/OSGI-INF/blueprint/shell-diagnostic.xml
+++ b/diagnostic/command/src/main/resources/OSGI-INF/blueprint/shell-diagnostic.xml
@@ -22,13 +22,9 @@
     <command-bundle xmlns="http://karaf.apache.org/xmlns/shell/v1.0.0">
         <command name="dev/create-dump">
             <action class="org.apache.karaf.diagnostic.command.DumpCommand">
-                <property name="providers" ref="providers"/>
+                <property name="bundleContext" ref="blueprintBundleContext"/>
             </action>
         </command>
     </command-bundle>
 
-    <reference-list id="providers" interface="org.apache.karaf.diagnostic.core.DumpProvider"
-        availability="optional">
-    </reference-list>
-
 </blueprint>

http://git-wip-us.apache.org/repos/asf/karaf/blob/c3fb6191/diagnostic/common/src/main/java/org/apache/karaf/diagnostic/common/BundleDumpProvider.java
----------------------------------------------------------------------
diff --git a/diagnostic/common/src/main/java/org/apache/karaf/diagnostic/common/BundleDumpProvider.java b/diagnostic/common/src/main/java/org/apache/karaf/diagnostic/common/BundleDumpProvider.java
deleted file mode 100644
index ccbddd5..0000000
--- a/diagnostic/common/src/main/java/org/apache/karaf/diagnostic/common/BundleDumpProvider.java
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * 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.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/c3fb6191/diagnostic/common/src/main/java/org/apache/karaf/diagnostic/common/EnvironmentDumpProvider.java
----------------------------------------------------------------------
diff --git a/diagnostic/common/src/main/java/org/apache/karaf/diagnostic/common/EnvironmentDumpProvider.java b/diagnostic/common/src/main/java/org/apache/karaf/diagnostic/common/EnvironmentDumpProvider.java
deleted file mode 100644
index c5b3c37..0000000
--- a/diagnostic/common/src/main/java/org/apache/karaf/diagnostic/common/EnvironmentDumpProvider.java
+++ /dev/null
@@ -1,291 +0,0 @@
-/*
- * 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 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;
-import org.osgi.framework.Version;
-
-/**
- * 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/c3fb6191/diagnostic/common/src/main/java/org/apache/karaf/diagnostic/common/FeaturesDumpProvider.java
----------------------------------------------------------------------
diff --git a/diagnostic/common/src/main/java/org/apache/karaf/diagnostic/common/FeaturesDumpProvider.java b/diagnostic/common/src/main/java/org/apache/karaf/diagnostic/common/FeaturesDumpProvider.java
index 408057c..5c8786c 100644
--- a/diagnostic/common/src/main/java/org/apache/karaf/diagnostic/common/FeaturesDumpProvider.java
+++ b/diagnostic/common/src/main/java/org/apache/karaf/diagnostic/common/FeaturesDumpProvider.java
@@ -17,11 +17,12 @@ package org.apache.karaf.diagnostic.common;
 
 import java.io.OutputStreamWriter;
 
-import org.apache.karaf.diagnostic.core.common.TextDumpProvider;
 import org.apache.karaf.features.BundleInfo;
 import org.apache.karaf.features.Feature;
 import org.apache.karaf.features.FeaturesService;
 import org.apache.karaf.features.Repository;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceReference;
 
 /**
  * Dump provider which add file named features.txt with informations
@@ -32,48 +33,56 @@ public class FeaturesDumpProvider extends TextDumpProvider {
     /**
      * Feature service.
      */
-    private final FeaturesService features;
+    private final BundleContext bundleContext;
 
     /**
      * Creates new dump entry witch contains information about
      * karaf features.
-     * 
-     * @param features Feature service.
      */
-    public FeaturesDumpProvider(FeaturesService features) {
+    public FeaturesDumpProvider(BundleContext bundleContext) {
         super("features.txt");
-        this.features = features;
+        this.bundleContext = bundleContext;
     }
 
     /**
      * {@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");
+        ServiceReference ref = bundleContext.getServiceReference(FeaturesService.class.getName());
+        if (ref == null) {
+            return;
         }
 
-        // 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());
+        FeaturesService features = (FeaturesService) bundleContext.getService(ref);
+        try {
+            // 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");
                 }
-                outputStreamWriter.write("\n\n");
             }
-        }
 
-        // flush & close stream
-        outputStreamWriter.close();
+            // flush & close stream
+            outputStreamWriter.close();
+        } finally {
+            bundleContext.ungetService(ref);
+        }
     }
 
 }

http://git-wip-us.apache.org/repos/asf/karaf/blob/c3fb6191/diagnostic/common/src/main/java/org/apache/karaf/diagnostic/common/HeapDumpProvider.java
----------------------------------------------------------------------
diff --git a/diagnostic/common/src/main/java/org/apache/karaf/diagnostic/common/HeapDumpProvider.java b/diagnostic/common/src/main/java/org/apache/karaf/diagnostic/common/HeapDumpProvider.java
deleted file mode 100644
index 3094c5e..0000000
--- a/diagnostic/common/src/main/java/org/apache/karaf/diagnostic/common/HeapDumpProvider.java
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * 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 com.sun.management.HotSpotDiagnosticMXBean;
-import org.apache.karaf.diagnostic.core.DumpDestination;
-import org.apache.karaf.diagnostic.core.DumpProvider;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-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 {
-
-    private final static Logger LOGGER = LoggerFactory.getLogger(HeapDumpProvider.class);
-
-    public void createDump(DumpDestination destination) throws Exception {
-        FileInputStream in = null;
-        OutputStream out = null;
-        try {
-            MBeanServer mBeanServer = ManagementFactory.getPlatformMBeanServer();
-            HotSpotDiagnosticMXBean diagnosticMXBean = ManagementFactory.newPlatformMXBeanProxy(mBeanServer,
-                    "com.sun.management:type=HotSpotDiagnostic", HotSpotDiagnosticMXBean.class);
-            diagnosticMXBean.dumpHeap("heapdump.txt", false);
-            // copy the dump in the destination
-            File heapDumpFile = new File("heapdump.txt");
-            in = new FileInputStream(heapDumpFile);
-            out = destination.add("heapdump.txt");
-            byte[] buffer = new byte[2048];
-            while ((in.read(buffer) != -1)) {
-                out.write(buffer);
-            }
-            // remove the original dump
-            if (heapDumpFile.exists()) {
-                heapDumpFile.delete();
-            }
-        } catch (Exception e) {
-            LOGGER.warn("Can't create heapdump", e);
-        } finally {
-            if (in != null) {
-                in.close();
-            }
-            if (out != null) {
-                out.flush();
-                out.close();
-            }
-        }
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/c3fb6191/diagnostic/common/src/main/java/org/apache/karaf/diagnostic/common/LogDumpProvider.java
----------------------------------------------------------------------
diff --git a/diagnostic/common/src/main/java/org/apache/karaf/diagnostic/common/LogDumpProvider.java b/diagnostic/common/src/main/java/org/apache/karaf/diagnostic/common/LogDumpProvider.java
index 3ce7abe..84adb49 100644
--- a/diagnostic/common/src/main/java/org/apache/karaf/diagnostic/common/LogDumpProvider.java
+++ b/diagnostic/common/src/main/java/org/apache/karaf/diagnostic/common/LogDumpProvider.java
@@ -36,9 +36,9 @@ import org.osgi.service.cm.ConfigurationAdmin;
  */
 public class LogDumpProvider implements DumpProvider {
 
-    private BundleContext bundleContext;
+    private final BundleContext bundleContext;
 
-    public void setBundleContext(BundleContext bundleContext) {
+    public LogDumpProvider(BundleContext bundleContext) {
         this.bundleContext = bundleContext;
     }
 
@@ -72,8 +72,6 @@ public class LogDumpProvider implements DumpProvider {
                     }
                 }
             }
-        } catch (Exception e) {
-            throw e;
         } finally {
             bundleContext.ungetService(ref);
         }

http://git-wip-us.apache.org/repos/asf/karaf/blob/c3fb6191/diagnostic/common/src/main/java/org/apache/karaf/diagnostic/common/MemoryDumpProvider.java
----------------------------------------------------------------------
diff --git a/diagnostic/common/src/main/java/org/apache/karaf/diagnostic/common/MemoryDumpProvider.java b/diagnostic/common/src/main/java/org/apache/karaf/diagnostic/common/MemoryDumpProvider.java
deleted file mode 100644
index 1727b64..0000000
--- a/diagnostic/common/src/main/java/org/apache/karaf/diagnostic/common/MemoryDumpProvider.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * 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 org.apache.karaf.diagnostic.core.common.TextDumpProvider;
-
-import java.io.OutputStreamWriter;
-import java.lang.management.ManagementFactory;
-import java.lang.management.MemoryMXBean;
-
-/**
- * Provider for memory information in memory.txt.
- */
-public class MemoryDumpProvider extends TextDumpProvider {
-
-    /**
-     * Create a new dump entry which contains information about memory usage.
-     */
-    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/c3fb6191/diagnostic/common/src/main/java/org/apache/karaf/diagnostic/common/TextDumpProvider.java
----------------------------------------------------------------------
diff --git a/diagnostic/common/src/main/java/org/apache/karaf/diagnostic/common/TextDumpProvider.java b/diagnostic/common/src/main/java/org/apache/karaf/diagnostic/common/TextDumpProvider.java
new file mode 100644
index 0000000..2470696
--- /dev/null
+++ b/diagnostic/common/src/main/java/org/apache/karaf/diagnostic/common/TextDumpProvider.java
@@ -0,0 +1,65 @@
+/*
+ * 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}
+     */
+    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/c3fb6191/diagnostic/common/src/main/java/org/apache/karaf/diagnostic/common/ThreadDumpProvider.java
----------------------------------------------------------------------
diff --git a/diagnostic/common/src/main/java/org/apache/karaf/diagnostic/common/ThreadDumpProvider.java b/diagnostic/common/src/main/java/org/apache/karaf/diagnostic/common/ThreadDumpProvider.java
deleted file mode 100644
index 34b0238..0000000
--- a/diagnostic/common/src/main/java/org/apache/karaf/diagnostic/common/ThreadDumpProvider.java
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- * 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 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/c3fb6191/diagnostic/common/src/main/resources/OSGI-INF/blueprint/diagnostic-services.xml
----------------------------------------------------------------------
diff --git a/diagnostic/common/src/main/resources/OSGI-INF/blueprint/diagnostic-services.xml b/diagnostic/common/src/main/resources/OSGI-INF/blueprint/diagnostic-services.xml
index c3618c8..5c3a038 100644
--- a/diagnostic/common/src/main/resources/OSGI-INF/blueprint/diagnostic-services.xml
+++ b/diagnostic/common/src/main/resources/OSGI-INF/blueprint/diagnostic-services.xml
@@ -20,35 +20,13 @@
 <blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0" default-activation="lazy">
 
     <bean id="features" class="org.apache.karaf.diagnostic.common.FeaturesDumpProvider">
-        <argument>
-            <reference interface="org.apache.karaf.features.FeaturesService"
-                availability="optional" />
-        </argument>
+        <argument ref="blueprintBundleContext"/>
     </bean>
     <service ref="features" auto-export="interfaces" />
 
     <bean id="logs" class="org.apache.karaf.diagnostic.common.LogDumpProvider">
-        <property name="bundleContext" ref="blueprintBundleContext"/>
+        <argument ref="blueprintBundleContext"/>
     </bean>
     <service ref="logs" auto-export="interfaces" />
 
-    <bean id="bundles" class="org.apache.karaf.diagnostic.common.BundleDumpProvider">
-        <argument ref="blueprintBundleContext" />
-    </bean>
-    <service ref="bundles" auto-export="interfaces" />
-
-    <bean id="threads" class="org.apache.karaf.diagnostic.common.ThreadDumpProvider" />
-    <service ref="threads" auto-export="interfaces" />
-
-    <bean id="heapdump" class="org.apache.karaf.diagnostic.common.HeapDumpProvider" />
-    <service ref="heapdump" auto-export="interfaces" />
-
-    <bean id="memory" class="org.apache.karaf.diagnostic.common.MemoryDumpProvider" />
-    <service ref="memory" auto-export="interfaces" />
-
-    <bean id="environment" class="org.apache.karaf.diagnostic.common.EnvironmentDumpProvider" >
-        <argument ref="blueprintBundleContext" />
-    </bean>
-    <service ref="environment" auto-export="interfaces" />
-
 </blueprint>

http://git-wip-us.apache.org/repos/asf/karaf/blob/c3fb6191/diagnostic/core/pom.xml
----------------------------------------------------------------------
diff --git a/diagnostic/core/pom.xml b/diagnostic/core/pom.xml
index 68c7c99..adbea75 100644
--- a/diagnostic/core/pom.xml
+++ b/diagnostic/core/pom.xml
@@ -37,6 +37,13 @@
         <appendedResourcesDirectory>${basedir}/../../etc/appended-resources</appendedResourcesDirectory>
     </properties>
 
+    <dependencies>
+        <dependency>
+            <groupId>org.osgi</groupId>
+            <artifactId>org.osgi.core</artifactId>
+        </dependency>
+    </dependencies>
+
     <build>
         <resources>
             <resource>
@@ -60,12 +67,19 @@
                 <configuration>
                     <instructions>
                         <Export-Package>
-                        	${project.artifactId};version=${project.version},
-                        	${project.artifactId}.common;version=${project.version};-noimport:=true,
+                        	${project.artifactId};version=${project.version}
                        	</Export-Package>
                         <Import-Package>
                             *
                         </Import-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>

http://git-wip-us.apache.org/repos/asf/karaf/blob/c3fb6191/diagnostic/core/src/main/java/org/apache/karaf/diagnostic/core/Dump.java
----------------------------------------------------------------------
diff --git a/diagnostic/core/src/main/java/org/apache/karaf/diagnostic/core/Dump.java b/diagnostic/core/src/main/java/org/apache/karaf/diagnostic/core/Dump.java
new file mode 100644
index 0000000..3a4df0a
--- /dev/null
+++ b/diagnostic/core/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/c3fb6191/diagnostic/core/src/main/java/org/apache/karaf/diagnostic/core/common/DirectoryDumpDestination.java
----------------------------------------------------------------------
diff --git a/diagnostic/core/src/main/java/org/apache/karaf/diagnostic/core/common/DirectoryDumpDestination.java b/diagnostic/core/src/main/java/org/apache/karaf/diagnostic/core/common/DirectoryDumpDestination.java
index 37ae72e..689ab34 100644
--- a/diagnostic/core/src/main/java/org/apache/karaf/diagnostic/core/common/DirectoryDumpDestination.java
+++ b/diagnostic/core/src/main/java/org/apache/karaf/diagnostic/core/common/DirectoryDumpDestination.java
@@ -51,5 +51,9 @@ public class DirectoryDumpDestination implements DumpDestination {
 	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/c3fb6191/diagnostic/core/src/main/java/org/apache/karaf/diagnostic/core/common/ZipDumpDestination.java
----------------------------------------------------------------------
diff --git a/diagnostic/core/src/main/java/org/apache/karaf/diagnostic/core/common/ZipDumpDestination.java b/diagnostic/core/src/main/java/org/apache/karaf/diagnostic/core/common/ZipDumpDestination.java
index bafd38d..37838c2 100644
--- a/diagnostic/core/src/main/java/org/apache/karaf/diagnostic/core/common/ZipDumpDestination.java
+++ b/diagnostic/core/src/main/java/org/apache/karaf/diagnostic/core/common/ZipDumpDestination.java
@@ -33,6 +33,7 @@ public class ZipDumpDestination implements DumpDestination {
      * Destination streem.
      */
     private ZipOutputStream outputStream;
+    private File file;
 
     /**
      * Creates new dump in given directory.
@@ -51,8 +52,8 @@ public class ZipDumpDestination implements DumpDestination {
      */
     public ZipDumpDestination(File file) {
         try {
-            outputStream = new ZipOutputStream(new FileOutputStream(
-                file));
+            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
@@ -76,4 +77,8 @@ public class ZipDumpDestination implements DumpDestination {
         outputStream.close();
     }
 
+    @Override
+    public String toString() {
+        return "zip: " + file;
+    }
 }

http://git-wip-us.apache.org/repos/asf/karaf/blob/c3fb6191/diagnostic/core/src/main/java/org/apache/karaf/diagnostic/core/internal/Activator.java
----------------------------------------------------------------------
diff --git a/diagnostic/core/src/main/java/org/apache/karaf/diagnostic/core/internal/Activator.java b/diagnostic/core/src/main/java/org/apache/karaf/diagnostic/core/internal/Activator.java
new file mode 100644
index 0000000..232ba0d
--- /dev/null
+++ b/diagnostic/core/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 = sun.misc.Signal.handle(new Signal(SIGNAL), this);
+    }
+
+    public void stop(BundleContext context) throws Exception {
+        sun.misc.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/c3fb6191/diagnostic/core/src/main/java/org/apache/karaf/diagnostic/core/providers/BundleDumpProvider.java
----------------------------------------------------------------------
diff --git a/diagnostic/core/src/main/java/org/apache/karaf/diagnostic/core/providers/BundleDumpProvider.java b/diagnostic/core/src/main/java/org/apache/karaf/diagnostic/core/providers/BundleDumpProvider.java
new file mode 100644
index 0000000..871097e
--- /dev/null
+++ b/diagnostic/core/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();
+    }
+
+}