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

[1/4] git commit: Move JaasHelper into Utils, use StreamUtils wherever possible, and update to jdk7 syntax

Repository: karaf
Updated Branches:
  refs/heads/master dde4a388f -> 06b62c086


Move JaasHelper into Utils, use StreamUtils wherever possible, and update to jdk7 syntax


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

Branch: refs/heads/master
Commit: 06b62c0862ee3e7a8d1579a146736692a8b3621d
Parents: ca651c8
Author: Guillaume Nodet <gn...@gmail.com>
Authored: Mon Apr 28 17:26:55 2014 +0200
Committer: Guillaume Nodet <gn...@gmail.com>
Committed: Mon Apr 28 20:01:25 2014 +0200

----------------------------------------------------------------------
 bundle/core/pom.xml                             |   1 +
 .../apache/karaf/bundle/command/Install.java    |   2 +-
 .../apache/karaf/bundle/command/StartLevel.java |   5 +-
 .../bundle/core/internal/BundleServiceImpl.java |   6 +-
 .../blueprint/BlueprintTransformer.java         |   8 -
 .../deployer/features/FeatureTransformer.java   |  19 +--
 .../deployer/spring/SpringTransformer.java      |   8 -
 diagnostic/pom.xml                              |   1 +
 .../core/internal/HeapDumpProvider.java         |  21 +--
 .../core/internal/LogDumpProvider.java          |  19 +--
 features/core/pom.xml                           |   1 +
 .../service/FeatureConfigInstaller.java         |   8 +-
 .../internal/repository/RepositoryTest.java     |  19 +--
 .../internal/service/OverridesTest.java         |  18 --
 instance/pom.xml                                |   1 +
 .../core/internal/InstanceServiceImpl.java      |  14 +-
 jaas/blueprint/jasypt/pom.xml                   |   6 +
 ...tableConfigAdminPropertyPlaceholderTest.java |  18 +-
 .../EncryptablePropertyPlaceholderTest.java     |  18 +-
 jaas/command/pom.xml                            |   8 +
 .../apache/karaf/jaas/command/SuCommand.java    |   2 +-
 .../apache/karaf/jaas/command/SudoCommand.java  |   2 +-
 .../apache/karaf/jaas/modules/JaasHelper.java   | 166 ------------------
 .../karaf/jdbc/internal/JdbcConnector.java      |   4 +-
 kar/pom.xml                                     |   1 +
 .../java/org/apache/karaf/kar/internal/Kar.java |  14 +-
 .../karaf/kar/internal/KarServiceImpl.java      |   9 +-
 management/server/pom.xml                       |   1 +
 .../karaf/management/KarafMBeanServerGuard.java |  37 +---
 .../management/KarafMBeanServerGuardTest.java   |   9 +-
 service/guard/pom.xml                           |   5 +
 .../service/guard/impl/GuardProxyCatalog.java   |  36 +---
 .../karaf/shell/commands/impl/EditAction.java   |  20 +--
 shell/console/pom.xml                           |   6 +
 .../impl/jline/ConsoleFactoryService.java       |   3 +-
 .../console/impl/jline/LocalConsoleManager.java |   3 +-
 shell/core/pom.xml                              |   4 +-
 .../impl/console/osgi/LocalConsoleManager.java  |   2 +-
 shell/ssh/pom.xml                               |   1 +
 .../apache/karaf/shell/ssh/ShellCommand.java    |  14 +-
 .../karaf/shell/ssh/ShellFactoryImpl.java       |   2 +-
 tooling/karaf-maven-plugin/pom.xml              |   4 +
 .../features/ValidateDescriptorMojo.java        |  38 ++---
 .../apache/karaf/tooling/utils/MojoSupport.java |  28 +---
 util/pom.xml                                    |   4 +
 .../java/org/apache/karaf/util/StreamUtils.java |  29 +++-
 .../org/apache/karaf/util/jaas/JaasHelper.java  | 167 +++++++++++++++++++
 webconsole/console/pom.xml                      |   8 +-
 .../webconsole/internal/KarafOsgiManager.java   |   3 +-
 49 files changed, 343 insertions(+), 480 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/karaf/blob/06b62c08/bundle/core/pom.xml
----------------------------------------------------------------------
diff --git a/bundle/core/pom.xml b/bundle/core/pom.xml
index edea01d..fc99d53 100644
--- a/bundle/core/pom.xml
+++ b/bundle/core/pom.xml
@@ -126,6 +126,7 @@
                             org.apache.karaf.bundle.command*,
                             org.apache.karaf.bundle.core.internal,
                             org.apache.karaf.bundle.core.internal.osgi,
+                            org.apache.karaf.util.jaas,
                             org.apache.karaf.util.maven,
                             org.apache.karaf.util.tracker,
                             org.apache.felix.utils.version,

http://git-wip-us.apache.org/repos/asf/karaf/blob/06b62c08/bundle/core/src/main/java/org/apache/karaf/bundle/command/Install.java
----------------------------------------------------------------------
diff --git a/bundle/core/src/main/java/org/apache/karaf/bundle/command/Install.java b/bundle/core/src/main/java/org/apache/karaf/bundle/command/Install.java
index e501762..017e780 100644
--- a/bundle/core/src/main/java/org/apache/karaf/bundle/command/Install.java
+++ b/bundle/core/src/main/java/org/apache/karaf/bundle/command/Install.java
@@ -20,7 +20,6 @@ import java.util.ArrayList;
 import java.util.List;
 
 import org.apache.karaf.bundle.core.BundleService;
-import org.apache.karaf.jaas.modules.JaasHelper;
 import org.apache.karaf.shell.api.action.Action;
 import org.apache.karaf.shell.api.action.Argument;
 import org.apache.karaf.shell.api.action.Command;
@@ -29,6 +28,7 @@ import org.apache.karaf.shell.api.action.lifecycle.Reference;
 import org.apache.karaf.shell.api.action.lifecycle.Service;
 import org.apache.karaf.shell.api.console.Session;
 import org.apache.karaf.shell.support.MultiException;
+import org.apache.karaf.util.jaas.JaasHelper;
 import org.osgi.framework.Bundle;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.startlevel.BundleStartLevel;

http://git-wip-us.apache.org/repos/asf/karaf/blob/06b62c08/bundle/core/src/main/java/org/apache/karaf/bundle/command/StartLevel.java
----------------------------------------------------------------------
diff --git a/bundle/core/src/main/java/org/apache/karaf/bundle/command/StartLevel.java b/bundle/core/src/main/java/org/apache/karaf/bundle/command/StartLevel.java
index 060f005..80ba326 100644
--- a/bundle/core/src/main/java/org/apache/karaf/bundle/command/StartLevel.java
+++ b/bundle/core/src/main/java/org/apache/karaf/bundle/command/StartLevel.java
@@ -17,13 +17,12 @@
 package org.apache.karaf.bundle.command;
 
 import org.apache.karaf.bundle.core.BundleService;
-import org.apache.karaf.jaas.modules.JaasHelper;
 import org.apache.karaf.shell.api.action.Argument;
 import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.Option;
-import org.apache.karaf.shell.api.console.Session;
 import org.apache.karaf.shell.api.action.lifecycle.Reference;
 import org.apache.karaf.shell.api.action.lifecycle.Service;
+import org.apache.karaf.shell.api.console.Session;
+import org.apache.karaf.util.jaas.JaasHelper;
 import org.osgi.framework.Bundle;
 import org.osgi.framework.startlevel.BundleStartLevel;
 

http://git-wip-us.apache.org/repos/asf/karaf/blob/06b62c08/bundle/core/src/main/java/org/apache/karaf/bundle/core/internal/BundleServiceImpl.java
----------------------------------------------------------------------
diff --git a/bundle/core/src/main/java/org/apache/karaf/bundle/core/internal/BundleServiceImpl.java b/bundle/core/src/main/java/org/apache/karaf/bundle/core/internal/BundleServiceImpl.java
index f2e7012..9336dde 100644
--- a/bundle/core/src/main/java/org/apache/karaf/bundle/core/internal/BundleServiceImpl.java
+++ b/bundle/core/src/main/java/org/apache/karaf/bundle/core/internal/BundleServiceImpl.java
@@ -16,8 +16,6 @@
  */
 package org.apache.karaf.bundle.core.internal;
 
-import static java.lang.String.format;
-
 import java.net.URL;
 import java.util.ArrayList;
 import java.util.Collections;
@@ -32,7 +30,7 @@ import org.apache.karaf.bundle.core.BundleInfo;
 import org.apache.karaf.bundle.core.BundleService;
 import org.apache.karaf.bundle.core.BundleState;
 import org.apache.karaf.bundle.core.BundleStateService;
-import org.apache.karaf.jaas.modules.JaasHelper;
+import org.apache.karaf.util.jaas.JaasHelper;
 import org.osgi.framework.Bundle;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.BundleException;
@@ -47,6 +45,8 @@ import org.osgi.framework.wiring.FrameworkWiring;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import static java.lang.String.format;
+
 public class BundleServiceImpl implements BundleService {
 
     private static Logger LOG = LoggerFactory.getLogger(BundleService.class);

http://git-wip-us.apache.org/repos/asf/karaf/blob/06b62c08/deployer/blueprint/src/main/java/org/apache/karaf/deployer/blueprint/BlueprintTransformer.java
----------------------------------------------------------------------
diff --git a/deployer/blueprint/src/main/java/org/apache/karaf/deployer/blueprint/BlueprintTransformer.java b/deployer/blueprint/src/main/java/org/apache/karaf/deployer/blueprint/BlueprintTransformer.java
index 218110b..94568d3 100644
--- a/deployer/blueprint/src/main/java/org/apache/karaf/deployer/blueprint/BlueprintTransformer.java
+++ b/deployer/blueprint/src/main/java/org/apache/karaf/deployer/blueprint/BlueprintTransformer.java
@@ -182,12 +182,4 @@ public class BlueprintTransformer {
         return url.getPath();
     }
 
-    protected static void copyInputStream(InputStream in, OutputStream out) throws Exception {
-        byte[] buffer = new byte[4096];
-        int len = in.read(buffer);
-        while (len >= 0) {
-            out.write(buffer, 0, len);
-            len = in.read(buffer);
-        }
-    }
 }

http://git-wip-us.apache.org/repos/asf/karaf/blob/06b62c08/deployer/features/src/main/java/org/apache/karaf/deployer/features/FeatureTransformer.java
----------------------------------------------------------------------
diff --git a/deployer/features/src/main/java/org/apache/karaf/deployer/features/FeatureTransformer.java b/deployer/features/src/main/java/org/apache/karaf/deployer/features/FeatureTransformer.java
index ecc8719..784e71f 100644
--- a/deployer/features/src/main/java/org/apache/karaf/deployer/features/FeatureTransformer.java
+++ b/deployer/features/src/main/java/org/apache/karaf/deployer/features/FeatureTransformer.java
@@ -27,6 +27,7 @@ import java.util.jar.Manifest;
 import java.util.zip.ZipEntry;
 
 import org.apache.karaf.util.DeployerUtils;
+import org.apache.karaf.util.StreamUtils;
 import org.osgi.framework.Constants;
 
 /**
@@ -61,11 +62,10 @@ public class FeatureTransformer {
         out.closeEntry();
         e = new ZipEntry("META-INF/" + FeatureDeploymentListener.FEATURE_PATH + "/" + name);
         out.putNextEntry(e);
-        InputStream fis = url.openStream();
-        try {
-            copyInputStream(fis, out);
-        } finally {
-            fis.close();
+        try (
+            InputStream fis = url.openStream()
+        ) {
+            StreamUtils.copy(fis, out);
         }
         out.closeEntry();
         out.close();
@@ -94,13 +94,4 @@ public class FeatureTransformer {
         return url.getPath();
     }
 
-    private static void copyInputStream(InputStream in, OutputStream out) throws IOException {
-        byte[] buffer = new byte[8192];
-        int len = in.read(buffer);
-        while (len >= 0) {
-            out.write(buffer, 0, len);
-            len = in.read(buffer);
-        }
-    }
-
 }

http://git-wip-us.apache.org/repos/asf/karaf/blob/06b62c08/deployer/spring/src/main/java/org/apache/karaf/deployer/spring/SpringTransformer.java
----------------------------------------------------------------------
diff --git a/deployer/spring/src/main/java/org/apache/karaf/deployer/spring/SpringTransformer.java b/deployer/spring/src/main/java/org/apache/karaf/deployer/spring/SpringTransformer.java
index 4ae42f4..74ccc5d 100644
--- a/deployer/spring/src/main/java/org/apache/karaf/deployer/spring/SpringTransformer.java
+++ b/deployer/spring/src/main/java/org/apache/karaf/deployer/spring/SpringTransformer.java
@@ -180,12 +180,4 @@ public class SpringTransformer {
         return url.getPath();
     }
 
-    protected static void copyInputStream(InputStream in, OutputStream out) throws Exception {
-        byte[] buffer = new byte[4096];
-        int len = in.read(buffer);
-        while (len >= 0) {
-            out.write(buffer, 0, len);
-            len = in.read(buffer);
-        }
-    }
 }

http://git-wip-us.apache.org/repos/asf/karaf/blob/06b62c08/diagnostic/pom.xml
----------------------------------------------------------------------
diff --git a/diagnostic/pom.xml b/diagnostic/pom.xml
index db61e04..c89a72d 100644
--- a/diagnostic/pom.xml
+++ b/diagnostic/pom.xml
@@ -103,6 +103,7 @@
                         <Private-Package>
                             org.apache.karaf.diagnostic.core.internal,
                             org.apache.karaf.diagnostic.core.internal.osgi,
+                            org.apache.karaf.util,
                             org.apache.karaf.util.tracker
                         </Private-Package>
                         <Bundle-Activator>

http://git-wip-us.apache.org/repos/asf/karaf/blob/06b62c08/diagnostic/src/main/java/org/apache/karaf/diagnostic/core/internal/HeapDumpProvider.java
----------------------------------------------------------------------
diff --git a/diagnostic/src/main/java/org/apache/karaf/diagnostic/core/internal/HeapDumpProvider.java b/diagnostic/src/main/java/org/apache/karaf/diagnostic/core/internal/HeapDumpProvider.java
index b86f57b..9e6cccd 100644
--- a/diagnostic/src/main/java/org/apache/karaf/diagnostic/core/internal/HeapDumpProvider.java
+++ b/diagnostic/src/main/java/org/apache/karaf/diagnostic/core/internal/HeapDumpProvider.java
@@ -19,6 +19,7 @@ package org.apache.karaf.diagnostic.core.internal;
 import com.sun.management.HotSpotDiagnosticMXBean;
 import org.apache.karaf.diagnostic.core.DumpDestination;
 import org.apache.karaf.diagnostic.core.DumpProvider;
+import org.apache.karaf.util.StreamUtils;
 
 import javax.management.MBeanServer;
 import java.io.File;
@@ -33,8 +34,6 @@ public class HeapDumpProvider implements DumpProvider {
 
     @Override
     public void createDump(DumpDestination destination) throws Exception {
-        FileInputStream in = null;
-        OutputStream out = null;
         try {
             MBeanServer mBeanServer = ManagementFactory.getPlatformMBeanServer();
             HotSpotDiagnosticMXBean diagnosticMXBean = ManagementFactory.newPlatformMXBeanProxy(mBeanServer,
@@ -42,11 +41,11 @@ public class HeapDumpProvider implements DumpProvider {
             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);
+            try (
+                FileInputStream in = new FileInputStream(heapDumpFile);
+                OutputStream out = destination.add("heapdump.txt")
+            ) {
+                StreamUtils.copy(in, out);
             }
             // remove the original dump
             if (heapDumpFile.exists()) {
@@ -54,14 +53,6 @@ public class HeapDumpProvider implements DumpProvider {
             }
         } catch (Exception e) {
             // nothing to do
-        } finally {
-            if (in != null) {
-                in.close();
-            }
-            if (out != null) {
-                out.flush();
-                out.close();
-            }
         }
     }
 

http://git-wip-us.apache.org/repos/asf/karaf/blob/06b62c08/diagnostic/src/main/java/org/apache/karaf/diagnostic/core/internal/LogDumpProvider.java
----------------------------------------------------------------------
diff --git a/diagnostic/src/main/java/org/apache/karaf/diagnostic/core/internal/LogDumpProvider.java b/diagnostic/src/main/java/org/apache/karaf/diagnostic/core/internal/LogDumpProvider.java
index 64b45f1..412977a 100644
--- a/diagnostic/src/main/java/org/apache/karaf/diagnostic/core/internal/LogDumpProvider.java
+++ b/diagnostic/src/main/java/org/apache/karaf/diagnostic/core/internal/LogDumpProvider.java
@@ -25,6 +25,7 @@ import java.util.Enumeration;
 
 import org.apache.karaf.diagnostic.core.DumpDestination;
 import org.apache.karaf.diagnostic.core.DumpProvider;
+import org.apache.karaf.util.StreamUtils;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.ServiceReference;
 import org.osgi.service.cm.Configuration;
@@ -68,7 +69,7 @@ public class LogDumpProvider implements DumpProvider {
                     if (file.exists()) {
                         FileInputStream inputStream = new FileInputStream(file);
                         OutputStream outputStream = destination.add("log/" + file.getName());
-                        copy(inputStream, outputStream);
+                        StreamUtils.copy(inputStream, outputStream);
                     }
                 }
             }
@@ -79,20 +80,4 @@ public class LogDumpProvider implements DumpProvider {
         }
     }
 
-    /**
-     * Rewrites data from input stream to output stream. This code is very common
-     * but we would avoid additional dependencies in diagnostic stuff.
-     *
-     * @param inputStream  Source stream.
-     * @param outputStream Destination stream.
-     * @throws IOException When IO operation fails.
-     */
-    private void copy(InputStream inputStream, OutputStream outputStream) throws IOException {
-        byte[] buffer = new byte[4096];
-        int n = 0;
-        while (-1 != (n = inputStream.read(buffer))) {
-            outputStream.write(buffer, 0, n);
-        }
-    }
-
 }

http://git-wip-us.apache.org/repos/asf/karaf/blob/06b62c08/features/core/pom.xml
----------------------------------------------------------------------
diff --git a/features/core/pom.xml b/features/core/pom.xml
index a6f9d1b..75fdf94 100644
--- a/features/core/pom.xml
+++ b/features/core/pom.xml
@@ -134,6 +134,7 @@
                             org.apache.felix.utils.version,
                             org.apache.felix.utils.properties,
                             org.apache.felix.utils.manifest,
+                            org.apache.karaf.util,
                             org.apache.karaf.util.collections,
                             org.apache.karaf.util.json,
                             org.apache.karaf.util.tracker,

http://git-wip-us.apache.org/repos/asf/karaf/blob/06b62c08/features/core/src/main/java/org/apache/karaf/features/internal/service/FeatureConfigInstaller.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/internal/service/FeatureConfigInstaller.java b/features/core/src/main/java/org/apache/karaf/features/internal/service/FeatureConfigInstaller.java
index a42dab2..7a1fe80 100644
--- a/features/core/src/main/java/org/apache/karaf/features/internal/service/FeatureConfigInstaller.java
+++ b/features/core/src/main/java/org/apache/karaf/features/internal/service/FeatureConfigInstaller.java
@@ -28,6 +28,7 @@ import java.util.Hashtable;
 
 import org.apache.karaf.features.ConfigFileInfo;
 import org.apache.karaf.features.Feature;
+import org.apache.karaf.util.StreamUtils;
 import org.osgi.framework.Constants;
 import org.osgi.framework.InvalidSyntaxException;
 import org.osgi.service.cm.Configuration;
@@ -140,12 +141,7 @@ public class FeatureConfigInstaller {
             try (
                 FileOutputStream fop = new FileOutputStream(file)
             ) {
-                int bytesRead;
-                byte[] buffer = new byte[1024];
-
-                while ((bytesRead = is.read(buffer)) != -1) {
-                    fop.write(buffer, 0, bytesRead);
-                }
+                StreamUtils.copy(is, fop);
             }
         } catch (RuntimeException | MalformedURLException e) {
             LOGGER.error(e.getMessage());

http://git-wip-us.apache.org/repos/asf/karaf/blob/06b62c08/features/core/src/test/java/org/apache/karaf/features/internal/repository/RepositoryTest.java
----------------------------------------------------------------------
diff --git a/features/core/src/test/java/org/apache/karaf/features/internal/repository/RepositoryTest.java b/features/core/src/test/java/org/apache/karaf/features/internal/repository/RepositoryTest.java
index 46e8e04..001c169 100644
--- a/features/core/src/test/java/org/apache/karaf/features/internal/repository/RepositoryTest.java
+++ b/features/core/src/test/java/org/apache/karaf/features/internal/repository/RepositoryTest.java
@@ -27,10 +27,10 @@ import java.io.OutputStream;
 import java.net.URL;
 import java.util.zip.GZIPOutputStream;
 
+import org.apache.karaf.util.StreamUtils;
 import org.junit.Test;
 import org.osgi.resource.Resource;
 
-import static org.apache.karaf.util.StreamUtils.close;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
 import static org.osgi.framework.namespace.BundleNamespace.BUNDLE_NAMESPACE;
@@ -82,18 +82,13 @@ public class RepositoryTest {
 
     private URL gzip(URL url) throws IOException {
         File temp = File.createTempFile("repo", ".tmp");
-        OutputStream os = new GZIPOutputStream(new FileOutputStream(temp));
-        InputStream is = url.openStream();
-        copy(is, os);
-        close(is, os);
+        try (
+            OutputStream os = new GZIPOutputStream(new FileOutputStream(temp));
+            InputStream is = url.openStream()
+        ) {
+            StreamUtils.copy(is, os);
+        }
         return temp.toURI().toURL();
     }
 
-    private void copy(InputStream inputStream, OutputStream outputStream) throws IOException {
-        byte[] buffer = new byte[4096];
-        int n = 0;
-        while (-1 != (n = inputStream.read(buffer))) {
-            outputStream.write(buffer, 0, n);
-        }
-    }
 }

http://git-wip-us.apache.org/repos/asf/karaf/blob/06b62c08/features/core/src/test/java/org/apache/karaf/features/internal/service/OverridesTest.java
----------------------------------------------------------------------
diff --git a/features/core/src/test/java/org/apache/karaf/features/internal/service/OverridesTest.java b/features/core/src/test/java/org/apache/karaf/features/internal/service/OverridesTest.java
index 2d4d4ae..d6e28f8 100644
--- a/features/core/src/test/java/org/apache/karaf/features/internal/service/OverridesTest.java
+++ b/features/core/src/test/java/org/apache/karaf/features/internal/service/OverridesTest.java
@@ -148,24 +148,6 @@ public class OverridesTest {
         assertNotNull("Missing range on admin.core override", karafAdminCore.getAttribute(Overrides.OVERRIDE_RANGE));
     }
 
-    /**
-     * Copies the content of {@link java.io.InputStream} to {@link java.io.OutputStream}.
-     *
-     * @param input
-     * @param output
-     * @throws java.io.IOException
-     */
-    private void copy(final InputStream input, final OutputStream output) throws IOException {
-        byte[] buffer = new byte[1024 * 16];
-        int n;
-        while (-1 != (n = input.read(buffer))) {
-            output.write(buffer, 0, n);
-            output.flush();
-        }
-        input.close();
-        output.close();
-    }
-
     static Builder resource(String uri) {
         return new Builder(uri);
     }

http://git-wip-us.apache.org/repos/asf/karaf/blob/06b62c08/instance/pom.xml
----------------------------------------------------------------------
diff --git a/instance/pom.xml b/instance/pom.xml
index 4d1962b..bd04934 100644
--- a/instance/pom.xml
+++ b/instance/pom.xml
@@ -175,6 +175,7 @@
                             org.apache.karaf.instance.core.internal,
                             org.apache.karaf.instance.core.internal.osgi,
                             org.apache.felix.utils.properties;-split-package:=merge-first,
+                            org.apache.karaf.util,
                             org.apache.karaf.util.locks,
                             org.apache.karaf.util.tracker
                         </Private-Package>

http://git-wip-us.apache.org/repos/asf/karaf/blob/06b62c08/instance/src/main/java/org/apache/karaf/instance/core/internal/InstanceServiceImpl.java
----------------------------------------------------------------------
diff --git a/instance/src/main/java/org/apache/karaf/instance/core/internal/InstanceServiceImpl.java b/instance/src/main/java/org/apache/karaf/instance/core/internal/InstanceServiceImpl.java
index 01a4fa1..ca57c80 100644
--- a/instance/src/main/java/org/apache/karaf/instance/core/internal/InstanceServiceImpl.java
+++ b/instance/src/main/java/org/apache/karaf/instance/core/internal/InstanceServiceImpl.java
@@ -22,6 +22,7 @@ import org.apache.karaf.instance.core.InstanceSettings;
 import org.apache.karaf.jpm.Process;
 import org.apache.karaf.jpm.impl.ProcessBuilderFactoryImpl;
 import org.apache.karaf.jpm.impl.ScriptUtils;
+import org.apache.karaf.util.StreamUtils;
 import org.apache.karaf.util.locks.FileLockUtils;
 import org.fusesource.jansi.Ansi;
 import org.slf4j.Logger;
@@ -1057,15 +1058,12 @@ public class InstanceServiceImpl implements InstanceService {
                     copy(new File(source, child), new File(destination, child));
             }
         } else {
-            InputStream in = new FileInputStream(source);
-            OutputStream out = new FileOutputStream(destination);
-            byte[] buffer = new byte[1024];
-            int length;
-            while ((length = in.read(buffer)) > 0) {
-                out.write(buffer, 0, length);
+            try(
+                InputStream in = new FileInputStream(source);
+                OutputStream out = new FileOutputStream(destination)
+            ) {
+                StreamUtils.copy(in, out);
             }
-            in.close();
-            out.close();
         }
     }
 

http://git-wip-us.apache.org/repos/asf/karaf/blob/06b62c08/jaas/blueprint/jasypt/pom.xml
----------------------------------------------------------------------
diff --git a/jaas/blueprint/jasypt/pom.xml b/jaas/blueprint/jasypt/pom.xml
index 24b6ce0..d27d90c 100644
--- a/jaas/blueprint/jasypt/pom.xml
+++ b/jaas/blueprint/jasypt/pom.xml
@@ -111,6 +111,12 @@
             <version>${slf4j.version}</version>
             <scope>test</scope>
         </dependency>
+
+        <dependency>
+            <groupId>org.apache.karaf</groupId>
+            <artifactId>org.apache.karaf.util</artifactId>
+            <scope>test</scope>
+        </dependency>
     </dependencies>
 
     <build>

http://git-wip-us.apache.org/repos/asf/karaf/blob/06b62c08/jaas/blueprint/jasypt/src/test/java/org/apache/karaf/jaas/blueprint/jasypt/handler/EncryptableConfigAdminPropertyPlaceholderTest.java
----------------------------------------------------------------------
diff --git a/jaas/blueprint/jasypt/src/test/java/org/apache/karaf/jaas/blueprint/jasypt/handler/EncryptableConfigAdminPropertyPlaceholderTest.java b/jaas/blueprint/jasypt/src/test/java/org/apache/karaf/jaas/blueprint/jasypt/handler/EncryptableConfigAdminPropertyPlaceholderTest.java
index db1283f..a821700 100644
--- a/jaas/blueprint/jasypt/src/test/java/org/apache/karaf/jaas/blueprint/jasypt/handler/EncryptableConfigAdminPropertyPlaceholderTest.java
+++ b/jaas/blueprint/jasypt/src/test/java/org/apache/karaf/jaas/blueprint/jasypt/handler/EncryptableConfigAdminPropertyPlaceholderTest.java
@@ -20,6 +20,7 @@ import de.kalpatec.pojosr.framework.launch.ClasspathScanner;
 import de.kalpatec.pojosr.framework.launch.PojoServiceRegistry;
 import de.kalpatec.pojosr.framework.launch.PojoServiceRegistryFactory;
 import junit.framework.TestCase;
+import org.apache.karaf.util.StreamUtils;
 import org.jasypt.encryption.pbe.StandardPBEStringEncryptor;
 import org.jasypt.encryption.pbe.config.EnvironmentStringPBEConfig;
 import org.junit.After;
@@ -86,7 +87,7 @@ public class EncryptableConfigAdminPropertyPlaceholderTest extends TestCase {
     private BundleDescriptor getBundleDescriptor(String path, TinyBundle bundle) throws Exception {
         File file = new File(path);
         FileOutputStream fos = new FileOutputStream(file);
-        copy(bundle.build(), fos);
+        StreamUtils.copy(bundle.build(), fos);
         fos.close();
         JarInputStream jis = new JarInputStream(new FileInputStream(file));
         Map<String, String> headers = new HashMap<String, String>();
@@ -235,21 +236,6 @@ public class EncryptableConfigAdminPropertyPlaceholderTest extends TestCase {
         return result;
     }
 
-    public static long copy(final InputStream input, final OutputStream output) throws IOException {
-        return copy(input, output, 8024);
-    }
-
-    public static long copy(final InputStream input, final OutputStream output, int buffersize) throws IOException {
-        final byte[] buffer = new byte[buffersize];
-        int n;
-        long count = 0;
-        while (-1 != (n = input.read(buffer))) {
-            output.write(buffer, 0, n);
-            count += n;
-        }
-        return count;
-    }
-
     /*
     public void setConfigAdmin(ConfigurationAdmin configAdmin) {
         this.configAdmin = configAdmin;

http://git-wip-us.apache.org/repos/asf/karaf/blob/06b62c08/jaas/blueprint/jasypt/src/test/java/org/apache/karaf/jaas/blueprint/jasypt/handler/EncryptablePropertyPlaceholderTest.java
----------------------------------------------------------------------
diff --git a/jaas/blueprint/jasypt/src/test/java/org/apache/karaf/jaas/blueprint/jasypt/handler/EncryptablePropertyPlaceholderTest.java b/jaas/blueprint/jasypt/src/test/java/org/apache/karaf/jaas/blueprint/jasypt/handler/EncryptablePropertyPlaceholderTest.java
index d3e0f7b..94d6c82 100644
--- a/jaas/blueprint/jasypt/src/test/java/org/apache/karaf/jaas/blueprint/jasypt/handler/EncryptablePropertyPlaceholderTest.java
+++ b/jaas/blueprint/jasypt/src/test/java/org/apache/karaf/jaas/blueprint/jasypt/handler/EncryptablePropertyPlaceholderTest.java
@@ -36,6 +36,7 @@ import de.kalpatec.pojosr.framework.launch.ClasspathScanner;
 import de.kalpatec.pojosr.framework.launch.PojoServiceRegistry;
 import de.kalpatec.pojosr.framework.launch.PojoServiceRegistryFactory;
 import junit.framework.TestCase;
+import org.apache.karaf.util.StreamUtils;
 import org.jasypt.encryption.pbe.StandardPBEStringEncryptor;
 import org.jasypt.encryption.pbe.config.EnvironmentStringPBEConfig;
 import org.junit.After;
@@ -98,7 +99,7 @@ public class EncryptablePropertyPlaceholderTest extends TestCase {
     private BundleDescriptor getBundleDescriptor(String path, TinyBundle bundle) throws Exception {
         File file = new File(path);
         FileOutputStream fos = new FileOutputStream(file);
-        copy(bundle.build(), fos);
+        StreamUtils.copy(bundle.build(), fos);
         fos.close();
         JarInputStream jis = new JarInputStream(new FileInputStream(file));
         Map<String, String> headers = new HashMap<String, String>();
@@ -210,19 +211,4 @@ public class EncryptablePropertyPlaceholderTest extends TestCase {
         return result;
     }
 
-    public static long copy(final InputStream input, final OutputStream output) throws IOException {
-        return copy(input, output, 8024);
-    }
-
-    public static long copy(final InputStream input, final OutputStream output, int buffersize) throws IOException {
-        final byte[] buffer = new byte[buffersize];
-        int n;
-        long count=0;
-        while (-1 != (n = input.read(buffer))) {
-            output.write(buffer, 0, n);
-            count += n;
-        }
-        return count;
-    }
-
 }

http://git-wip-us.apache.org/repos/asf/karaf/blob/06b62c08/jaas/command/pom.xml
----------------------------------------------------------------------
diff --git a/jaas/command/pom.xml b/jaas/command/pom.xml
index 1e5b290..9011f27 100644
--- a/jaas/command/pom.xml
+++ b/jaas/command/pom.xml
@@ -49,6 +49,11 @@
             <artifactId>org.apache.karaf.jaas.config</artifactId>
         </dependency>
         <dependency>
+            <groupId>org.apache.karaf</groupId>
+            <artifactId>org.apache.karaf.util</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
             <groupId>org.apache.karaf.jaas</groupId>
             <artifactId>org.apache.karaf.jaas.boot</artifactId>
             <scope>provided</scope>
@@ -95,6 +100,9 @@
                         <Import-Package>
                             *
                         </Import-Package>
+                        <Private-Package>
+                            org.apache.karaf.util.jaas,
+                        </Private-Package>
                         <Karaf-Commands>
                             org.apache.karaf.jaas.command.*
                         </Karaf-Commands>

http://git-wip-us.apache.org/repos/asf/karaf/blob/06b62c08/jaas/command/src/main/java/org/apache/karaf/jaas/command/SuCommand.java
----------------------------------------------------------------------
diff --git a/jaas/command/src/main/java/org/apache/karaf/jaas/command/SuCommand.java b/jaas/command/src/main/java/org/apache/karaf/jaas/command/SuCommand.java
index 9a1a265..7c6e9da 100644
--- a/jaas/command/src/main/java/org/apache/karaf/jaas/command/SuCommand.java
+++ b/jaas/command/src/main/java/org/apache/karaf/jaas/command/SuCommand.java
@@ -26,7 +26,6 @@ import javax.security.auth.callback.PasswordCallback;
 import javax.security.auth.callback.UnsupportedCallbackException;
 import javax.security.auth.login.LoginContext;
 
-import org.apache.karaf.jaas.modules.JaasHelper;
 import org.apache.karaf.shell.api.action.Action;
 import org.apache.karaf.shell.api.action.Argument;
 import org.apache.karaf.shell.api.action.Command;
@@ -35,6 +34,7 @@ import org.apache.karaf.shell.api.action.lifecycle.Reference;
 import org.apache.karaf.shell.api.action.lifecycle.Service;
 import org.apache.karaf.shell.api.console.Session;
 import org.apache.karaf.shell.support.ShellUtil;
+import org.apache.karaf.util.jaas.JaasHelper;
 
 @Command(scope = "jaas", name = "su", description = "Substitute user identity")
 @Service

http://git-wip-us.apache.org/repos/asf/karaf/blob/06b62c08/jaas/command/src/main/java/org/apache/karaf/jaas/command/SudoCommand.java
----------------------------------------------------------------------
diff --git a/jaas/command/src/main/java/org/apache/karaf/jaas/command/SudoCommand.java b/jaas/command/src/main/java/org/apache/karaf/jaas/command/SudoCommand.java
index ba027c6..fb5e7e7 100644
--- a/jaas/command/src/main/java/org/apache/karaf/jaas/command/SudoCommand.java
+++ b/jaas/command/src/main/java/org/apache/karaf/jaas/command/SudoCommand.java
@@ -27,7 +27,6 @@ import javax.security.auth.callback.PasswordCallback;
 import javax.security.auth.callback.UnsupportedCallbackException;
 import javax.security.auth.login.LoginContext;
 
-import org.apache.karaf.jaas.modules.JaasHelper;
 import org.apache.karaf.shell.api.action.Action;
 import org.apache.karaf.shell.api.action.Argument;
 import org.apache.karaf.shell.api.action.Command;
@@ -35,6 +34,7 @@ import org.apache.karaf.shell.api.action.Option;
 import org.apache.karaf.shell.api.action.lifecycle.Reference;
 import org.apache.karaf.shell.api.action.lifecycle.Service;
 import org.apache.karaf.shell.api.console.Session;
+import org.apache.karaf.util.jaas.JaasHelper;
 
 @Command(scope = "jaas", name = "sudo", description = "Execute a command as another user")
 @Service

http://git-wip-us.apache.org/repos/asf/karaf/blob/06b62c08/jaas/modules/src/main/java/org/apache/karaf/jaas/modules/JaasHelper.java
----------------------------------------------------------------------
diff --git a/jaas/modules/src/main/java/org/apache/karaf/jaas/modules/JaasHelper.java b/jaas/modules/src/main/java/org/apache/karaf/jaas/modules/JaasHelper.java
deleted file mode 100644
index 05489ed..0000000
--- a/jaas/modules/src/main/java/org/apache/karaf/jaas/modules/JaasHelper.java
+++ /dev/null
@@ -1,166 +0,0 @@
-/*
- *  Licensed 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.
- *  under the License.
- */
-package org.apache.karaf.jaas.modules;
-
-import java.security.AccessControlContext;
-import java.security.AccessController;
-import java.security.Permission;
-import java.security.Principal;
-import java.security.PrivilegedAction;
-import java.security.PrivilegedActionException;
-import java.security.PrivilegedExceptionAction;
-import java.security.ProtectionDomain;
-import javax.security.auth.Subject;
-import javax.security.auth.SubjectDomainCombiner;
-
-import org.apache.karaf.jaas.boot.principal.RolePrincipal;
-
-public class JaasHelper {
-
-    public static boolean currentUserHasRole(String requestedRole) {
-        String clazz;
-        String role;
-        int index = requestedRole.indexOf(':');
-        if (index > 0) {
-            clazz = requestedRole.substring(0, index);
-            role = requestedRole.substring(index + 1);
-        } else {
-            clazz = RolePrincipal.class.getName();
-            role = requestedRole;
-        }
-        AccessControlContext acc = AccessController.getContext();
-        if (acc == null) {
-            return false;
-        }
-        Subject subject = Subject.getSubject(acc);
-        if (subject == null) {
-            return false;
-        }
-        for (Principal p : subject.getPrincipals()) {
-            if (clazz.equals(p.getClass().getName()) && role.equals(p.getName())) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    public static <T> T doAs(final Subject subject,
-                             final PrivilegedAction<T> action) {
-        if (action == null) {
-            throw new NullPointerException();
-        }
-        // set up the new Subject-based AccessControlContext for doPrivileged
-        final AccessControlContext currentAcc = AccessController.getContext();
-        final AccessControlContext newAcc = AccessController.doPrivileged
-                (new PrivilegedAction<AccessControlContext>() {
-                    public AccessControlContext run() {
-                        if (subject == null)
-                            return new AccessControlContext(currentAcc, null);
-                        else
-                            return new AccessControlContext(currentAcc, new OsgiSubjectDomainCombiner(subject));
-                    }
-                });
-        // call doPrivileged and push this new context on the stack
-        return AccessController.doPrivileged(action, newAcc);
-    }
-
-    public static <T> T doAs(final Subject subject,
-                             final PrivilegedExceptionAction<T> action) throws PrivilegedActionException {
-        if (action == null) {
-            throw new NullPointerException();
-        }
-        // set up the new Subject-based AccessControlContext for doPrivileged
-        final AccessControlContext currentAcc = AccessController.getContext();
-        final AccessControlContext newAcc = AccessController.doPrivileged
-                (new PrivilegedAction<AccessControlContext>() {
-                    public AccessControlContext run() {
-                        if (subject == null)
-                            return new AccessControlContext(currentAcc, null);
-                        else
-                            return new AccessControlContext(currentAcc, new OsgiSubjectDomainCombiner(subject));
-                    }
-                });
-        // call doPrivileged and push this new context on the stack
-        return AccessController.doPrivileged(action, newAcc);
-    }
-
-    public static class OsgiSubjectDomainCombiner extends SubjectDomainCombiner {
-
-        private final Subject subject;
-
-        public OsgiSubjectDomainCombiner(Subject subject) {
-            super(subject);
-            this.subject = subject;
-        }
-
-        public ProtectionDomain[] combine(ProtectionDomain[] currentDomains,
-                                          ProtectionDomain[] assignedDomains) {
-            int cLen = (currentDomains == null ? 0 : currentDomains.length);
-            int aLen = (assignedDomains == null ? 0 : assignedDomains.length);
-            ProtectionDomain[] newDomains = new ProtectionDomain[cLen + aLen];
-            Principal[] principals = subject.getPrincipals().toArray(new Principal[0]);
-            for (int i = 0; i < cLen; i++) {
-                newDomains[i] = new DelegatingProtectionDomain(currentDomains[i], principals);
-            }
-            for (int i = 0; i < aLen; i++) {
-                newDomains[cLen + i] = assignedDomains[i];
-            }
-            newDomains = optimize(newDomains);
-            return newDomains;
-        }
-
-        private ProtectionDomain[] optimize(ProtectionDomain[] domains) {
-            if (domains == null || domains.length == 0) {
-                return null;
-            }
-            ProtectionDomain[] optimized = new ProtectionDomain[domains.length];
-            ProtectionDomain pd;
-            int num = 0;
-            for (int i = 0; i < domains.length; i++) {
-                if ((pd = domains[i]) != null) {
-                    boolean found = false;
-                    for (int j = 0; j < num && !found; j++) {
-                        found = (optimized[j] == pd);
-                    }
-                    if (!found) {
-                        optimized[num++] = pd;
-                    }
-                }
-            }
-            if (num > 0 && num < domains.length) {
-                ProtectionDomain[] downSize = new ProtectionDomain[num];
-                System.arraycopy(optimized, 0, downSize, 0, downSize.length);
-                optimized = downSize;
-            }
-            return ((num == 0 || optimized.length == 0) ? null : optimized);
-        }
-    }
-
-    public static class DelegatingProtectionDomain extends ProtectionDomain {
-
-        private final ProtectionDomain delegate;
-
-        DelegatingProtectionDomain(ProtectionDomain delegate, Principal[] principals) {
-            super(delegate.getCodeSource(), delegate.getPermissions(), delegate.getClassLoader(), principals);
-            this.delegate = delegate;
-        }
-
-        @Override
-        public boolean implies(Permission permission) {
-            return delegate.implies(permission);
-        }
-
-    }
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/06b62c08/jdbc/src/main/java/org/apache/karaf/jdbc/internal/JdbcConnector.java
----------------------------------------------------------------------
diff --git a/jdbc/src/main/java/org/apache/karaf/jdbc/internal/JdbcConnector.java b/jdbc/src/main/java/org/apache/karaf/jdbc/internal/JdbcConnector.java
index 11c7ca4..875be12 100644
--- a/jdbc/src/main/java/org/apache/karaf/jdbc/internal/JdbcConnector.java
+++ b/jdbc/src/main/java/org/apache/karaf/jdbc/internal/JdbcConnector.java
@@ -42,7 +42,7 @@ public class JdbcConnector implements Closeable {
     public JdbcConnector(BundleContext bundleContext, String datasourceName) {
         this.bundleContext = bundleContext;
         this.datasourceName = datasourceName;
-        this.resources = new LinkedList<Closeable>();
+        this.resources = new LinkedList<>();
     }
     
     public Connection connect() throws SQLException {
@@ -137,7 +137,7 @@ public class JdbcConnector implements Closeable {
 
     @Override
     public void close() {
-        StreamUtils.close(resources.toArray(new Closeable[]{}));
+        StreamUtils.close(resources);
         if (reference != null) {
             bundleContext.ungetService(reference);
         }

http://git-wip-us.apache.org/repos/asf/karaf/blob/06b62c08/kar/pom.xml
----------------------------------------------------------------------
diff --git a/kar/pom.xml b/kar/pom.xml
index 8612252..f32eaf7 100644
--- a/kar/pom.xml
+++ b/kar/pom.xml
@@ -110,6 +110,7 @@
                             org.apache.karaf.kar.command.completers,
                             org.apache.karaf.kar.internal,
                             org.apache.karaf.kar.internal.osgi,
+                            org.apache.karaf.util,
                             org.apache.karaf.util.maven,
                             org.apache.karaf.util.tracker,
                             org.apache.felix.utils.properties

http://git-wip-us.apache.org/repos/asf/karaf/blob/06b62c08/kar/src/main/java/org/apache/karaf/kar/internal/Kar.java
----------------------------------------------------------------------
diff --git a/kar/src/main/java/org/apache/karaf/kar/internal/Kar.java b/kar/src/main/java/org/apache/karaf/kar/internal/Kar.java
index 005cd17..2d9de9e 100644
--- a/kar/src/main/java/org/apache/karaf/kar/internal/Kar.java
+++ b/kar/src/main/java/org/apache/karaf/kar/internal/Kar.java
@@ -30,6 +30,7 @@ import java.util.jar.JarInputStream;
 import java.util.jar.Manifest;
 import java.util.zip.ZipEntry;
 
+import org.apache.karaf.util.StreamUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -151,7 +152,7 @@ public class Kar {
         } else {
             dest.getParentFile().mkdirs();
             FileOutputStream out = new FileOutputStream(dest);
-            copyStream(is, out);
+            StreamUtils.copy(is, out);
             out.close();
         }
         return dest;
@@ -167,17 +168,6 @@ public class Kar {
         }
     }
 
-    static long copyStream(InputStream input, OutputStream output) throws IOException {
-        byte[] buffer = new byte[10000];
-        long count = 0;
-        int n = 0;
-        while (-1 != (n = input.read(buffer))) {
-            output.write(buffer, 0, n);
-            count += n;
-        }
-        return count;
-    }
-
     public String getKarName() {
         try {
             String karName = new File(karUri.toURL().getFile()).getName();

http://git-wip-us.apache.org/repos/asf/karaf/blob/06b62c08/kar/src/main/java/org/apache/karaf/kar/internal/KarServiceImpl.java
----------------------------------------------------------------------
diff --git a/kar/src/main/java/org/apache/karaf/kar/internal/KarServiceImpl.java b/kar/src/main/java/org/apache/karaf/kar/internal/KarServiceImpl.java
index 0f86466..3f760f9 100644
--- a/kar/src/main/java/org/apache/karaf/kar/internal/KarServiceImpl.java
+++ b/kar/src/main/java/org/apache/karaf/kar/internal/KarServiceImpl.java
@@ -49,6 +49,7 @@ import org.apache.karaf.features.Feature;
 import org.apache.karaf.features.FeaturesService;
 import org.apache.karaf.features.Repository;
 import org.apache.karaf.kar.KarService;
+import org.apache.karaf.util.StreamUtils;
 import org.apache.karaf.util.maven.Parser;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -335,11 +336,13 @@ public class KarServiceImpl implements KarService {
         try {
             String noPrefixLocation = location.toString().substring(location.toString().lastIndexOf(":") + 1);
             Parser parser = new Parser(noPrefixLocation);
-            InputStream is = location.toURL().openStream();
             String path = "repository/" + parser.getArtifactPath();
             jos.putNextEntry(new JarEntry(path));
-            Kar.copyStream(is, jos);
-            is.close();
+            try (
+                InputStream is = location.toURL().openStream()
+            ) {
+                StreamUtils.copy(is, jos);
+            }
             locationMap.put(location, 1);
         } catch (Exception e) {
             LOGGER.error("Error adding " + location, e);

http://git-wip-us.apache.org/repos/asf/karaf/blob/06b62c08/management/server/pom.xml
----------------------------------------------------------------------
diff --git a/management/server/pom.xml b/management/server/pom.xml
index f5ad253..1722865 100644
--- a/management/server/pom.xml
+++ b/management/server/pom.xml
@@ -115,6 +115,7 @@
                         <Private-Package>
                             org.apache.karaf.management.internal,
                             org.apache.karaf.service.guard.tools,
+                            org.apache.karaf.util.jaas,
                             org.apache.karaf.util.tracker
                         </Private-Package>
                         <Provide-Capability>

http://git-wip-us.apache.org/repos/asf/karaf/blob/06b62c08/management/server/src/main/java/org/apache/karaf/management/KarafMBeanServerGuard.java
----------------------------------------------------------------------
diff --git a/management/server/src/main/java/org/apache/karaf/management/KarafMBeanServerGuard.java b/management/server/src/main/java/org/apache/karaf/management/KarafMBeanServerGuard.java
index c241ac2..746c35b 100644
--- a/management/server/src/main/java/org/apache/karaf/management/KarafMBeanServerGuard.java
+++ b/management/server/src/main/java/org/apache/karaf/management/KarafMBeanServerGuard.java
@@ -16,9 +16,9 @@
  */
 package org.apache.karaf.management;
 
-import org.apache.karaf.jaas.boot.principal.RolePrincipal;
 import org.apache.karaf.management.boot.KarafMBeanServerBuilder;
 import org.apache.karaf.service.guard.tools.ACLConfigurationParser;
+import org.apache.karaf.util.jaas.JaasHelper;
 import org.osgi.framework.InvalidSyntaxException;
 import org.osgi.service.cm.Configuration;
 import org.osgi.service.cm.ConfigurationAdmin;
@@ -171,7 +171,7 @@ public class KarafMBeanServerGuard implements InvocationHandler {
 
     private boolean canInvoke(ObjectName objectName, String methodName, String[] signature) throws IOException {
         for (String role : getRequiredRoles(objectName, methodName, signature)) {
-            if (currentUserHasRole(role))
+            if (JaasHelper.currentUserHasRole(role))
                 return true;
         }
 
@@ -222,7 +222,7 @@ public class KarafMBeanServerGuard implements InvocationHandler {
 
     void handleInvoke(ObjectName objectName, String operationName, Object[] params, String[] signature) throws IOException {
         for (String role : getRequiredRoles(objectName, operationName, params, signature)) {
-            if (currentUserHasRole(role))
+            if (JaasHelper.currentUserHasRole(role))
                 return;
         }
         throw new SecurityException("Insufficient roles/credentials for operation");
@@ -301,35 +301,4 @@ public class KarafMBeanServerGuard implements InvocationHandler {
         return res;
     }
 
-    static boolean currentUserHasRole(String requestedRole) {
-        String clazz;
-        String role;
-        int index = requestedRole.indexOf(':');
-        if (index > 0) {
-            clazz = requestedRole.substring(0, index);
-            role = requestedRole.substring(index + 1);
-        } else {
-            clazz = RolePrincipal.class.getName();
-            role = requestedRole;
-        }
-
-        AccessControlContext acc = AccessController.getContext();
-        if (acc == null) {
-            return false;
-        }
-        Subject subject = Subject.getSubject(acc);
-
-        if (subject == null) {
-            return false;
-        }
-
-        for (Principal p : subject.getPrincipals()) {
-            if (clazz.equals(p.getClass().getName()) && role.equals(p.getName())) {
-                return true;
-            }
-        }
-
-        return false;
-    }
-
 }

http://git-wip-us.apache.org/repos/asf/karaf/blob/06b62c08/management/server/src/test/java/org/apache/karaf/management/KarafMBeanServerGuardTest.java
----------------------------------------------------------------------
diff --git a/management/server/src/test/java/org/apache/karaf/management/KarafMBeanServerGuardTest.java b/management/server/src/test/java/org/apache/karaf/management/KarafMBeanServerGuardTest.java
index 2650303..8dfb42e 100644
--- a/management/server/src/test/java/org/apache/karaf/management/KarafMBeanServerGuardTest.java
+++ b/management/server/src/test/java/org/apache/karaf/management/KarafMBeanServerGuardTest.java
@@ -18,6 +18,7 @@ package org.apache.karaf.management;
 
 import junit.framework.TestCase;
 import org.apache.karaf.jaas.boot.principal.RolePrincipal;
+import org.apache.karaf.util.jaas.JaasHelper;
 import org.easymock.EasyMock;
 import org.osgi.framework.Constants;
 import org.osgi.framework.InvalidSyntaxException;
@@ -384,8 +385,8 @@ public class KarafMBeanServerGuardTest extends TestCase {
 
         Subject.doAs(subject, new PrivilegedAction<Void>() {
             public Void run() {
-                assertTrue(KarafMBeanServerGuard.currentUserHasRole("test"));
-                assertFalse(KarafMBeanServerGuard.currentUserHasRole("toast"));
+                assertTrue(JaasHelper.currentUserHasRole("test"));
+                assertFalse(JaasHelper.currentUserHasRole("toast"));
                 return null;
             }
         });
@@ -400,8 +401,8 @@ public class KarafMBeanServerGuardTest extends TestCase {
 
         Subject.doAs(subject, new PrivilegedAction<Void>() {
             public Void run() {
-                assertTrue(KarafMBeanServerGuard.currentUserHasRole(TestRolePrincipal.class.getCanonicalName() + ":foo"));
-                assertFalse(KarafMBeanServerGuard.currentUserHasRole("foo"));
+                assertTrue(JaasHelper.currentUserHasRole(TestRolePrincipal.class.getCanonicalName() + ":foo"));
+                assertFalse(JaasHelper.currentUserHasRole("foo"));
                 return null;
             }
         });

http://git-wip-us.apache.org/repos/asf/karaf/blob/06b62c08/service/guard/pom.xml
----------------------------------------------------------------------
diff --git a/service/guard/pom.xml b/service/guard/pom.xml
index dbcd0f7..b49d0f2 100644
--- a/service/guard/pom.xml
+++ b/service/guard/pom.xml
@@ -49,6 +49,11 @@
             <scope>provided</scope>
         </dependency>
         <dependency>
+            <groupId>org.apache.karaf</groupId>
+            <artifactId>org.apache.karaf.util</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
             <groupId>org.osgi</groupId>
             <artifactId>org.osgi.core</artifactId>
             <scope>provided</scope>

http://git-wip-us.apache.org/repos/asf/karaf/blob/06b62c08/service/guard/src/main/java/org/apache/karaf/service/guard/impl/GuardProxyCatalog.java
----------------------------------------------------------------------
diff --git a/service/guard/src/main/java/org/apache/karaf/service/guard/impl/GuardProxyCatalog.java b/service/guard/src/main/java/org/apache/karaf/service/guard/impl/GuardProxyCatalog.java
index 92e0ec6..db22d01 100644
--- a/service/guard/src/main/java/org/apache/karaf/service/guard/impl/GuardProxyCatalog.java
+++ b/service/guard/src/main/java/org/apache/karaf/service/guard/impl/GuardProxyCatalog.java
@@ -19,9 +19,6 @@ package org.apache.karaf.service.guard.impl;
 import java.io.IOException;
 import java.lang.reflect.Method;
 import java.lang.reflect.Modifier;
-import java.security.AccessControlContext;
-import java.security.AccessController;
-import java.security.Principal;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Dictionary;
@@ -38,14 +35,12 @@ import java.util.concurrent.ConcurrentMap;
 import java.util.concurrent.LinkedBlockingQueue;
 import java.util.regex.Pattern;
 
-import javax.security.auth.Subject;
-
 import org.apache.aries.proxy.InvocationListener;
 import org.apache.aries.proxy.ProxyManager;
 import org.apache.aries.proxy.UnableToProxyException;
-import org.apache.karaf.jaas.boot.principal.RolePrincipal;
 import org.apache.karaf.service.guard.tools.ACLConfigurationParser;
 import org.apache.karaf.service.guard.tools.ACLConfigurationParser.Specificity;
+import org.apache.karaf.util.jaas.JaasHelper;
 import org.osgi.framework.Bundle;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.Constants;
@@ -372,34 +367,7 @@ public class GuardProxyCatalog implements ServiceListener {
         if (ROLE_WILDCARD.equals(reqRole)) {
             return true;
         }
-
-        String clazz;
-        String role;
-        int idx = reqRole.indexOf(':');
-        if (idx > 0) {
-            clazz = reqRole.substring(0, idx);
-            role = reqRole.substring(idx + 1);
-        } else {
-            clazz = RolePrincipal.class.getName();
-            role = reqRole;
-        }
-
-        AccessControlContext acc = AccessController.getContext();
-        if (acc == null) {
-            return false;
-        }
-
-        Subject subject = Subject.getSubject(acc);
-        if (subject == null) {
-            return false;
-        }
-
-        for (Principal p : subject.getPrincipals()) {
-            if (clazz.equals(p.getClass().getName()) && role.equals(p.getName())) {
-                return true;
-            }
-        }
-        return false;
+        return JaasHelper.currentUserHasRole(reqRole);
     }
 
     static class ServiceRegistrationHolder {

http://git-wip-us.apache.org/repos/asf/karaf/blob/06b62c08/shell/commands/src/main/java/org/apache/karaf/shell/commands/impl/EditAction.java
----------------------------------------------------------------------
diff --git a/shell/commands/src/main/java/org/apache/karaf/shell/commands/impl/EditAction.java b/shell/commands/src/main/java/org/apache/karaf/shell/commands/impl/EditAction.java
index 77b9a09..f310949 100644
--- a/shell/commands/src/main/java/org/apache/karaf/shell/commands/impl/EditAction.java
+++ b/shell/commands/src/main/java/org/apache/karaf/shell/commands/impl/EditAction.java
@@ -99,7 +99,7 @@ public class EditAction implements Action {
                 }
 
                 fos = new FileOutputStream(f);
-                copy(is, fos);
+                StreamUtils.copy(is, fos);
             } catch (Exception ex) {
                 System.out.println("Failed to copy resource from url:" + sourceUrl + " to tmp file: " + path + "  for editing.");
             } finally {
@@ -128,7 +128,7 @@ public class EditAction implements Action {
         if (!isLocal) {
             FileInputStream fis = new FileInputStream(path);
             try {
-                copy(fis, os);
+                StreamUtils.copy(fis, os);
             } finally {
                 StreamUtils.close(fis);
             }
@@ -169,22 +169,6 @@ public class EditAction implements Action {
         }
     }
 
-    /**
-     * Copies the content of {@link InputStream} to {@link OutputStream}.
-     *
-     * @param input
-     * @param output
-     * @throws IOException
-     */
-    private void copy(final InputStream input, final OutputStream output) throws IOException {
-        byte[] buffer = new byte[1024 * 16];
-        int n = 0;
-        while (-1 != (n = input.read(buffer))) {
-            output.write(buffer, 0, n);
-            output.flush();
-        }
-    }
-
     public EditorFactory getEditorFactory() {
         return editorFactory;
     }

http://git-wip-us.apache.org/repos/asf/karaf/blob/06b62c08/shell/console/pom.xml
----------------------------------------------------------------------
diff --git a/shell/console/pom.xml b/shell/console/pom.xml
index 90cdeb5..28d3e46 100644
--- a/shell/console/pom.xml
+++ b/shell/console/pom.xml
@@ -71,6 +71,11 @@
         </dependency>
 
         <dependency>
+            <groupId>org.apache.karaf</groupId>
+            <artifactId>org.apache.karaf.util</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
             <groupId>org.apache.aries.blueprint</groupId>
             <artifactId>org.apache.aries.blueprint.api</artifactId>
             <scope>provided</scope>
@@ -176,6 +181,7 @@
                         	org.apache.karaf.shell.console.impl*,
                             org.apache.karaf.shell.security.impl*,
                             org.apache.karaf.shell.inject.impl*,
+                            org.apache.karaf.util.jaas
                         </Private-Package>
                         <Main-Class>
                             org.apache.karaf.shell.console.impl.Main

http://git-wip-us.apache.org/repos/asf/karaf/blob/06b62c08/shell/console/src/main/java/org/apache/karaf/shell/console/impl/jline/ConsoleFactoryService.java
----------------------------------------------------------------------
diff --git a/shell/console/src/main/java/org/apache/karaf/shell/console/impl/jline/ConsoleFactoryService.java b/shell/console/src/main/java/org/apache/karaf/shell/console/impl/jline/ConsoleFactoryService.java
index f32328c..02661ea 100644
--- a/shell/console/src/main/java/org/apache/karaf/shell/console/impl/jline/ConsoleFactoryService.java
+++ b/shell/console/src/main/java/org/apache/karaf/shell/console/impl/jline/ConsoleFactoryService.java
@@ -26,15 +26,14 @@ import java.util.List;
 import java.util.Properties;
 
 import jline.Terminal;
-
 import org.apache.felix.service.command.CommandProcessor;
 import org.apache.felix.service.command.CommandSession;
 import org.apache.felix.service.command.Function;
 import org.apache.felix.service.threadio.ThreadIO;
-import org.apache.karaf.jaas.modules.JaasHelper;
 import org.apache.karaf.shell.console.Console;
 import org.apache.karaf.shell.console.factory.ConsoleFactory;
 import org.apache.karaf.shell.util.ShellUtil;
+import org.apache.karaf.util.jaas.JaasHelper;
 import org.osgi.framework.BundleContext;
 
 public class ConsoleFactoryService implements ConsoleFactory {

http://git-wip-us.apache.org/repos/asf/karaf/blob/06b62c08/shell/console/src/main/java/org/apache/karaf/shell/console/impl/jline/LocalConsoleManager.java
----------------------------------------------------------------------
diff --git a/shell/console/src/main/java/org/apache/karaf/shell/console/impl/jline/LocalConsoleManager.java b/shell/console/src/main/java/org/apache/karaf/shell/console/impl/jline/LocalConsoleManager.java
index 906a9ad..d431f61 100644
--- a/shell/console/src/main/java/org/apache/karaf/shell/console/impl/jline/LocalConsoleManager.java
+++ b/shell/console/src/main/java/org/apache/karaf/shell/console/impl/jline/LocalConsoleManager.java
@@ -24,14 +24,13 @@ import java.security.PrivilegedAction;
 import javax.security.auth.Subject;
 
 import jline.Terminal;
-
 import org.apache.felix.service.command.CommandSession;
 import org.apache.karaf.jaas.boot.principal.RolePrincipal;
 import org.apache.karaf.jaas.boot.principal.UserPrincipal;
-import org.apache.karaf.jaas.modules.JaasHelper;
 import org.apache.karaf.shell.console.Console;
 import org.apache.karaf.shell.console.factory.ConsoleFactory;
 import org.apache.karaf.shell.util.ShellUtil;
+import org.apache.karaf.util.jaas.JaasHelper;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.ServiceRegistration;
 

http://git-wip-us.apache.org/repos/asf/karaf/blob/06b62c08/shell/core/pom.xml
----------------------------------------------------------------------
diff --git a/shell/core/pom.xml b/shell/core/pom.xml
index d6af05d..c7089b6 100644
--- a/shell/core/pom.xml
+++ b/shell/core/pom.xml
@@ -145,6 +145,7 @@
                         <Private-Package>
                             org.apache.karaf.service.guard.tools,
                             org.apache.karaf.shell.impl.*,
+                            org.apache.karaf.util.jaas,
                             org.apache.karaf.util.tracker,
                             org.apache.felix.utils.properties,
                             org.apache.felix.utils.extender,
@@ -164,9 +165,6 @@
                         <Main-Class>
                             org.apache.karaf.shell.impl.console.standalone.Main
                         </Main-Class>
-                        <Embed-Dependency>
-                            org.apache.karaf.jaas.modules;inline="org/apache/karaf/jaas/modules/JaasHelper*.class"
-                        </Embed-Dependency>
                     </instructions>
                     <unpackBundle>true</unpackBundle>
                 </configuration>

http://git-wip-us.apache.org/repos/asf/karaf/blob/06b62c08/shell/core/src/main/java/org/apache/karaf/shell/impl/console/osgi/LocalConsoleManager.java
----------------------------------------------------------------------
diff --git a/shell/core/src/main/java/org/apache/karaf/shell/impl/console/osgi/LocalConsoleManager.java b/shell/core/src/main/java/org/apache/karaf/shell/impl/console/osgi/LocalConsoleManager.java
index 14b0c5a..69c4afb 100644
--- a/shell/core/src/main/java/org/apache/karaf/shell/impl/console/osgi/LocalConsoleManager.java
+++ b/shell/core/src/main/java/org/apache/karaf/shell/impl/console/osgi/LocalConsoleManager.java
@@ -25,12 +25,12 @@ import javax.security.auth.Subject;
 
 import org.apache.karaf.jaas.boot.principal.RolePrincipal;
 import org.apache.karaf.jaas.boot.principal.UserPrincipal;
-import org.apache.karaf.jaas.modules.JaasHelper;
 import org.apache.karaf.shell.api.console.Session;
 import org.apache.karaf.shell.api.console.SessionFactory;
 import org.apache.karaf.shell.impl.console.JLineTerminal;
 import org.apache.karaf.shell.impl.console.TerminalFactory;
 import org.apache.karaf.shell.support.ShellUtil;
+import org.apache.karaf.util.jaas.JaasHelper;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.ServiceRegistration;
 

http://git-wip-us.apache.org/repos/asf/karaf/blob/06b62c08/shell/ssh/pom.xml
----------------------------------------------------------------------
diff --git a/shell/ssh/pom.xml b/shell/ssh/pom.xml
index e11b9bc..2c103bf 100644
--- a/shell/ssh/pom.xml
+++ b/shell/ssh/pom.xml
@@ -112,6 +112,7 @@
                         </Import-Package>
                         <Private-Package>
                             org.apache.karaf.util,
+                            org.apache.karaf.util.jaas,
                             org.apache.karaf.util.tracker
                         </Private-Package>
                         <Bundle-Activator>org.apache.karaf.shell.ssh.Activator</Bundle-Activator>

http://git-wip-us.apache.org/repos/asf/karaf/blob/06b62c08/shell/ssh/src/main/java/org/apache/karaf/shell/ssh/ShellCommand.java
----------------------------------------------------------------------
diff --git a/shell/ssh/src/main/java/org/apache/karaf/shell/ssh/ShellCommand.java b/shell/ssh/src/main/java/org/apache/karaf/shell/ssh/ShellCommand.java
index 94ae6ce..b129c20 100644
--- a/shell/ssh/src/main/java/org/apache/karaf/shell/ssh/ShellCommand.java
+++ b/shell/ssh/src/main/java/org/apache/karaf/shell/ssh/ShellCommand.java
@@ -18,18 +18,26 @@
  */
 package org.apache.karaf.shell.ssh;
 
-import java.io.*;
+import java.io.CharArrayWriter;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.io.PrintStream;
+import java.io.Reader;
 import java.security.PrivilegedActionException;
 import java.security.PrivilegedExceptionAction;
 import java.util.Map;
 
 import javax.security.auth.Subject;
 
-import org.apache.karaf.jaas.modules.JaasHelper;
-import org.apache.karaf.util.StreamUtils;
 import org.apache.karaf.shell.api.console.Session;
 import org.apache.karaf.shell.api.console.SessionFactory;
 import org.apache.karaf.shell.support.ShellUtil;
+import org.apache.karaf.util.StreamUtils;
+import org.apache.karaf.util.jaas.JaasHelper;
 import org.apache.sshd.server.Command;
 import org.apache.sshd.server.Environment;
 import org.apache.sshd.server.ExitCallback;

http://git-wip-us.apache.org/repos/asf/karaf/blob/06b62c08/shell/ssh/src/main/java/org/apache/karaf/shell/ssh/ShellFactoryImpl.java
----------------------------------------------------------------------
diff --git a/shell/ssh/src/main/java/org/apache/karaf/shell/ssh/ShellFactoryImpl.java b/shell/ssh/src/main/java/org/apache/karaf/shell/ssh/ShellFactoryImpl.java
index a6defed..2580838 100644
--- a/shell/ssh/src/main/java/org/apache/karaf/shell/ssh/ShellFactoryImpl.java
+++ b/shell/ssh/src/main/java/org/apache/karaf/shell/ssh/ShellFactoryImpl.java
@@ -29,11 +29,11 @@ import java.util.Map;
 
 import javax.security.auth.Subject;
 
-import org.apache.karaf.jaas.modules.JaasHelper;
 import org.apache.karaf.shell.api.console.Session;
 import org.apache.karaf.shell.api.console.SessionFactory;
 import org.apache.karaf.shell.api.console.Terminal;
 import org.apache.karaf.shell.support.ShellUtil;
+import org.apache.karaf.util.jaas.JaasHelper;
 import org.apache.sshd.common.Factory;
 import org.apache.sshd.server.Command;
 import org.apache.sshd.server.Environment;

http://git-wip-us.apache.org/repos/asf/karaf/blob/06b62c08/tooling/karaf-maven-plugin/pom.xml
----------------------------------------------------------------------
diff --git a/tooling/karaf-maven-plugin/pom.xml b/tooling/karaf-maven-plugin/pom.xml
index 9936771..599ca85 100644
--- a/tooling/karaf-maven-plugin/pom.xml
+++ b/tooling/karaf-maven-plugin/pom.xml
@@ -83,6 +83,10 @@
             <artifactId>wagon-http-lightweight</artifactId>
             <version>2.6</version>
         </dependency>
+        <dependency>
+            <groupId>org.apache.karaf</groupId>
+            <artifactId>org.apache.karaf.util</artifactId>
+        </dependency>
 
 
         <dependency>

http://git-wip-us.apache.org/repos/asf/karaf/blob/06b62c08/tooling/karaf-maven-plugin/src/main/java/org/apache/karaf/tooling/features/ValidateDescriptorMojo.java
----------------------------------------------------------------------
diff --git a/tooling/karaf-maven-plugin/src/main/java/org/apache/karaf/tooling/features/ValidateDescriptorMojo.java b/tooling/karaf-maven-plugin/src/main/java/org/apache/karaf/tooling/features/ValidateDescriptorMojo.java
index bbab285..8263454 100644
--- a/tooling/karaf-maven-plugin/src/main/java/org/apache/karaf/tooling/features/ValidateDescriptorMojo.java
+++ b/tooling/karaf-maven-plugin/src/main/java/org/apache/karaf/tooling/features/ValidateDescriptorMojo.java
@@ -47,6 +47,7 @@ import java.net.URL;
 import java.util.*;
 import java.util.jar.JarInputStream;
 import java.util.jar.Manifest;
+import java.util.zip.ZipEntry;
 import java.util.zip.ZipException;
 import java.util.zip.ZipFile;
 
@@ -497,10 +498,6 @@ public class ValidateDescriptorMojo extends MojoSupport {
         } else {
             try {
                 return ManifestUtils.isBundle(getManifest(bundle, artifact));
-            } catch (ZipException e) {
-                getLog().debug("Unable to determine if " + artifact + " is a bundle; defaulting to false", e);
-            } catch (IOException e) {
-                getLog().debug("Unable to determine if " + artifact + " is a bundle; defaulting to false", e);
             } catch (Exception e) {
                 getLog().debug("Unable to determine if " + artifact + " is a bundle; defaulting to false", e);
             }
@@ -512,31 +509,22 @@ public class ValidateDescriptorMojo extends MojoSupport {
      * Extract the META-INF/MANIFEST.MF file from an artifact
      */
     private Manifest getManifest(String bundle, Object artifact) throws ArtifactResolutionException, ArtifactNotFoundException,
-            ZipException, IOException {
+            IOException {
         if (!(artifact instanceof Artifact)) {
             //not resolved as mvn artifact, so it's non-mvn protocol, just use the CustomBundleURLStreamHandlerFactory
             // to open stream
-            InputStream is = null;
-            try {
-                is = new BufferedInputStream(new URL(bundle).openStream());
-            } catch (Exception e) {
-                getLog().warn("Error while opening artifact", e);
-            }
-
-            try {
-                is.mark(256 * 1024);
-                JarInputStream jar = new JarInputStream(is);
+            try (
+                InputStream is = new BufferedInputStream(new URL(bundle).openStream());
+                JarInputStream jar = new JarInputStream(is)
+            ) {
                 Manifest m = jar.getManifest();
                 if (m == null) {
                     throw new IOException("Manifest not present in the first entry of the zip");
                 }
-                silentClose(jar);
                 return m;
-            } finally {
-            	silentClose(is);
             }
         } else {
-        	ZipFile file = null;
+        	ZipFile file;
             Artifact mvnArtifact = (Artifact) artifact;
             File localFile = new File(localRepo.pathOf(mvnArtifact));
             if (localFile.exists()) {
@@ -547,12 +535,20 @@ public class ValidateDescriptorMojo extends MojoSupport {
                 resolver.resolve(mvnArtifact, remoteRepos, localRepo);
                 file = new ZipFile(mvnArtifact.getFile());
             }
+            ZipEntry entry = file.getEntry("META-INF/MANIFEST.MF");
+            if (entry == null) {
+                throw new IOException("Manifest not present in the first entry of the zip");
+            }
             // let's replace syserr for now to hide warnings being issues by the Manifest reading process
             PrintStream original = System.err;
             try {
                 System.setErr(new PrintStream(new ByteArrayOutputStream()));
-                Manifest manifest = new Manifest(file.getInputStream(file.getEntry("META-INF/MANIFEST.MF")));
-                return manifest;
+                try (
+                    InputStream is = file.getInputStream(entry)
+                ) {
+                    Manifest manifest = new Manifest(is);
+                    return manifest;
+                }
             } finally {
                 System.setErr(original);
             }

http://git-wip-us.apache.org/repos/asf/karaf/blob/06b62c08/tooling/karaf-maven-plugin/src/main/java/org/apache/karaf/tooling/utils/MojoSupport.java
----------------------------------------------------------------------
diff --git a/tooling/karaf-maven-plugin/src/main/java/org/apache/karaf/tooling/utils/MojoSupport.java b/tooling/karaf-maven-plugin/src/main/java/org/apache/karaf/tooling/utils/MojoSupport.java
index 21dd7fb..28228e6 100644
--- a/tooling/karaf-maven-plugin/src/main/java/org/apache/karaf/tooling/utils/MojoSupport.java
+++ b/tooling/karaf-maven-plugin/src/main/java/org/apache/karaf/tooling/utils/MojoSupport.java
@@ -31,6 +31,7 @@ import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 
+import org.apache.karaf.util.StreamUtils;
 import org.apache.maven.artifact.Artifact;
 import org.apache.maven.artifact.factory.ArtifactFactory;
 import org.apache.maven.artifact.metadata.ArtifactMetadataSource;
@@ -356,36 +357,19 @@ public abstract class MojoSupport extends AbstractMojo {
         }
     }
 
-    protected void silentClose(Closeable closeable) {
-        if (closeable != null) {
-            try {
-                closeable.close();
-            } catch (IOException e) {
-                // Ignore
-            }
-        }
-    }
-    
     protected void copy(File sourceFile, File destFile) {
         File targetDir = destFile.getParentFile();
         ensureDirExists(targetDir);
 
-        FileInputStream is = null;
-        BufferedOutputStream bos = null;
         try {
-            is = new FileInputStream(sourceFile);
-            bos = new BufferedOutputStream(new FileOutputStream(destFile));
-            int count = 0;
-            byte[] buffer = new byte[8192];
-            while ((count = is.read(buffer)) > 0) {
-                bos.write(buffer, 0, count);
+            try (
+                FileInputStream is = new FileInputStream(sourceFile);
+                FileOutputStream bos = new FileOutputStream(destFile)
+            ) {
+                StreamUtils.copy(is, bos);
             }
-            bos.close();
         } catch (IOException e) {
             throw new RuntimeException(e.getMessage(), e);
-        } finally {
-            silentClose(is);
-            silentClose(bos);
         }
     }
     

http://git-wip-us.apache.org/repos/asf/karaf/blob/06b62c08/util/pom.xml
----------------------------------------------------------------------
diff --git a/util/pom.xml b/util/pom.xml
index b5a7768..741a89d 100644
--- a/util/pom.xml
+++ b/util/pom.xml
@@ -52,6 +52,10 @@
             <groupId>org.slf4j</groupId>
             <artifactId>slf4j-api</artifactId>
         </dependency>
+        <dependency>
+            <groupId>org.apache.karaf.jaas</groupId>
+            <artifactId>org.apache.karaf.jaas.boot</artifactId>
+        </dependency>
     </dependencies>
     
     <properties>

http://git-wip-us.apache.org/repos/asf/karaf/blob/06b62c08/util/src/main/java/org/apache/karaf/util/StreamUtils.java
----------------------------------------------------------------------
diff --git a/util/src/main/java/org/apache/karaf/util/StreamUtils.java b/util/src/main/java/org/apache/karaf/util/StreamUtils.java
index a2e7bf6..7f0f58a 100644
--- a/util/src/main/java/org/apache/karaf/util/StreamUtils.java
+++ b/util/src/main/java/org/apache/karaf/util/StreamUtils.java
@@ -18,6 +18,8 @@ package org.apache.karaf.util;
 
 import java.io.Closeable;
 import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
 
 public class StreamUtils {
     
@@ -27,13 +29,34 @@ public class StreamUtils {
     public static void close(Closeable... closeables) {
         for (Closeable c : closeables) {
             try {
-            	if (c != null) {
-            		c.close();
-            	}
+                if (c != null) {
+                    c.close();
+                }
             } catch (IOException e) {
                 // Ignore
             }
         }
     }
 
+    public static void close(Iterable<Closeable> closeables) {
+        for (Closeable c : closeables) {
+            try {
+                if (c != null) {
+                    c.close();
+                }
+            } catch (IOException e) {
+                // Ignore
+            }
+        }
+    }
+
+    public static void copy(final InputStream input, final OutputStream output) throws IOException {
+        byte[] buffer = new byte[1024 * 16];
+        int n;
+        while ((n = input.read(buffer)) > 0) {
+            output.write(buffer, 0, n);
+        }
+        output.flush();
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/karaf/blob/06b62c08/util/src/main/java/org/apache/karaf/util/jaas/JaasHelper.java
----------------------------------------------------------------------
diff --git a/util/src/main/java/org/apache/karaf/util/jaas/JaasHelper.java b/util/src/main/java/org/apache/karaf/util/jaas/JaasHelper.java
new file mode 100644
index 0000000..194f78a
--- /dev/null
+++ b/util/src/main/java/org/apache/karaf/util/jaas/JaasHelper.java
@@ -0,0 +1,167 @@
+/*
+ *  Licensed 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.
+ *  under the License.
+ */
+package org.apache.karaf.util.jaas;
+
+import java.security.AccessControlContext;
+import java.security.AccessController;
+import java.security.Permission;
+import java.security.Principal;
+import java.security.PrivilegedAction;
+import java.security.PrivilegedActionException;
+import java.security.PrivilegedExceptionAction;
+import java.security.ProtectionDomain;
+
+import javax.security.auth.Subject;
+import javax.security.auth.SubjectDomainCombiner;
+
+import org.apache.karaf.jaas.boot.principal.RolePrincipal;
+
+public class JaasHelper {
+
+    public static boolean currentUserHasRole(String requestedRole) {
+        String clazz;
+        String role;
+        int index = requestedRole.indexOf(':');
+        if (index > 0) {
+            clazz = requestedRole.substring(0, index);
+            role = requestedRole.substring(index + 1);
+        } else {
+            clazz = RolePrincipal.class.getName();
+            role = requestedRole;
+        }
+        AccessControlContext acc = AccessController.getContext();
+        if (acc == null) {
+            return false;
+        }
+        Subject subject = Subject.getSubject(acc);
+        if (subject == null) {
+            return false;
+        }
+        for (Principal p : subject.getPrincipals()) {
+            if (clazz.equals(p.getClass().getName()) && role.equals(p.getName())) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    public static <T> T doAs(final Subject subject,
+                             final PrivilegedAction<T> action) {
+        if (action == null) {
+            throw new NullPointerException();
+        }
+        // set up the new Subject-based AccessControlContext for doPrivileged
+        final AccessControlContext currentAcc = AccessController.getContext();
+        final AccessControlContext newAcc = AccessController.doPrivileged
+                (new PrivilegedAction<AccessControlContext>() {
+                    public AccessControlContext run() {
+                        if (subject == null)
+                            return new AccessControlContext(currentAcc, null);
+                        else
+                            return new AccessControlContext(currentAcc, new OsgiSubjectDomainCombiner(subject));
+                    }
+                });
+        // call doPrivileged and push this new context on the stack
+        return AccessController.doPrivileged(action, newAcc);
+    }
+
+    public static <T> T doAs(final Subject subject,
+                             final PrivilegedExceptionAction<T> action) throws PrivilegedActionException {
+        if (action == null) {
+            throw new NullPointerException();
+        }
+        // set up the new Subject-based AccessControlContext for doPrivileged
+        final AccessControlContext currentAcc = AccessController.getContext();
+        final AccessControlContext newAcc = AccessController.doPrivileged
+                (new PrivilegedAction<AccessControlContext>() {
+                    public AccessControlContext run() {
+                        if (subject == null)
+                            return new AccessControlContext(currentAcc, null);
+                        else
+                            return new AccessControlContext(currentAcc, new OsgiSubjectDomainCombiner(subject));
+                    }
+                });
+        // call doPrivileged and push this new context on the stack
+        return AccessController.doPrivileged(action, newAcc);
+    }
+
+    public static class OsgiSubjectDomainCombiner extends SubjectDomainCombiner {
+
+        private final Subject subject;
+
+        public OsgiSubjectDomainCombiner(Subject subject) {
+            super(subject);
+            this.subject = subject;
+        }
+
+        public ProtectionDomain[] combine(ProtectionDomain[] currentDomains,
+                                          ProtectionDomain[] assignedDomains) {
+            int cLen = (currentDomains == null ? 0 : currentDomains.length);
+            int aLen = (assignedDomains == null ? 0 : assignedDomains.length);
+            ProtectionDomain[] newDomains = new ProtectionDomain[cLen + aLen];
+            Principal[] principals = subject.getPrincipals().toArray(new Principal[0]);
+            for (int i = 0; i < cLen; i++) {
+                newDomains[i] = new DelegatingProtectionDomain(currentDomains[i], principals);
+            }
+            for (int i = 0; i < aLen; i++) {
+                newDomains[cLen + i] = assignedDomains[i];
+            }
+            newDomains = optimize(newDomains);
+            return newDomains;
+        }
+
+        private ProtectionDomain[] optimize(ProtectionDomain[] domains) {
+            if (domains == null || domains.length == 0) {
+                return null;
+            }
+            ProtectionDomain[] optimized = new ProtectionDomain[domains.length];
+            ProtectionDomain pd;
+            int num = 0;
+            for (int i = 0; i < domains.length; i++) {
+                if ((pd = domains[i]) != null) {
+                    boolean found = false;
+                    for (int j = 0; j < num && !found; j++) {
+                        found = (optimized[j] == pd);
+                    }
+                    if (!found) {
+                        optimized[num++] = pd;
+                    }
+                }
+            }
+            if (num > 0 && num < domains.length) {
+                ProtectionDomain[] downSize = new ProtectionDomain[num];
+                System.arraycopy(optimized, 0, downSize, 0, downSize.length);
+                optimized = downSize;
+            }
+            return ((num == 0 || optimized.length == 0) ? null : optimized);
+        }
+    }
+
+    public static class DelegatingProtectionDomain extends ProtectionDomain {
+
+        private final ProtectionDomain delegate;
+
+        DelegatingProtectionDomain(ProtectionDomain delegate, Principal[] principals) {
+            super(delegate.getCodeSource(), delegate.getPermissions(), delegate.getClassLoader(), principals);
+            this.delegate = delegate;
+        }
+
+        @Override
+        public boolean implies(Permission permission) {
+            return delegate.implies(permission);
+        }
+
+    }
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/06b62c08/webconsole/console/pom.xml
----------------------------------------------------------------------
diff --git a/webconsole/console/pom.xml b/webconsole/console/pom.xml
index fbd369b..2269085 100644
--- a/webconsole/console/pom.xml
+++ b/webconsole/console/pom.xml
@@ -52,6 +52,11 @@
           <artifactId>org.osgi.compendium</artifactId>
         </dependency>
         <dependency>
+            <groupId>org.apache.karaf</groupId>
+            <artifactId>org.apache.karaf.util</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
             <groupId>org.apache.felix</groupId>
             <artifactId>org.apache.felix.webconsole</artifactId>
             <scope>provided</scope>
@@ -129,7 +134,8 @@
                         </Export-Package>
                         <Private-Package>
                             !org.apache.felix.webconsole,
-                            org.apache.felix.webconsole.*;-split-package:=merge-first
+                            org.apache.felix.webconsole.*;-split-package:=merge-first,
+                            org.apache.karaf.util.jaas
                         </Private-Package>
                         <Import-Package>
                             org.osgi.service.metatype;resolution:=optional,

http://git-wip-us.apache.org/repos/asf/karaf/blob/06b62c08/webconsole/console/src/main/java/org/apache/felix/webconsole/internal/KarafOsgiManager.java
----------------------------------------------------------------------
diff --git a/webconsole/console/src/main/java/org/apache/felix/webconsole/internal/KarafOsgiManager.java b/webconsole/console/src/main/java/org/apache/felix/webconsole/internal/KarafOsgiManager.java
index 2275c41..1cd8b04 100644
--- a/webconsole/console/src/main/java/org/apache/felix/webconsole/internal/KarafOsgiManager.java
+++ b/webconsole/console/src/main/java/org/apache/felix/webconsole/internal/KarafOsgiManager.java
@@ -21,13 +21,14 @@ package org.apache.felix.webconsole.internal;
 import java.io.IOException;
 import java.security.PrivilegedActionException;
 import java.security.PrivilegedExceptionAction;
+
 import javax.security.auth.Subject;
 import javax.servlet.ServletException;
 import javax.servlet.ServletRequest;
 import javax.servlet.ServletResponse;
 
 import org.apache.felix.webconsole.internal.servlet.OsgiManager;
-import org.apache.karaf.jaas.modules.JaasHelper;
+import org.apache.karaf.util.jaas.JaasHelper;
 import org.osgi.framework.BundleContext;
 
 public class KarafOsgiManager extends OsgiManager {


[2/4] [KARAF-2949] Use a jaas role to allow access to system bundles [KARAF-2923] Enhance bundle commands to support regions

Posted by gn...@apache.org.
http://git-wip-us.apache.org/repos/asf/karaf/blob/ca651c8e/bundle/core/src/main/java/org/apache/karaf/bundle/core/internal/BundleServiceImpl.java
----------------------------------------------------------------------
diff --git a/bundle/core/src/main/java/org/apache/karaf/bundle/core/internal/BundleServiceImpl.java b/bundle/core/src/main/java/org/apache/karaf/bundle/core/internal/BundleServiceImpl.java
index 69861e1..f2e7012 100644
--- a/bundle/core/src/main/java/org/apache/karaf/bundle/core/internal/BundleServiceImpl.java
+++ b/bundle/core/src/main/java/org/apache/karaf/bundle/core/internal/BundleServiceImpl.java
@@ -32,9 +32,11 @@ import org.apache.karaf.bundle.core.BundleInfo;
 import org.apache.karaf.bundle.core.BundleService;
 import org.apache.karaf.bundle.core.BundleState;
 import org.apache.karaf.bundle.core.BundleStateService;
+import org.apache.karaf.jaas.modules.JaasHelper;
 import org.osgi.framework.Bundle;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.BundleException;
+import org.osgi.framework.startlevel.BundleStartLevel;
 import org.osgi.framework.wiring.BundleCapability;
 import org.osgi.framework.wiring.BundleRequirement;
 import org.osgi.framework.wiring.BundleRevision;
@@ -55,7 +57,7 @@ public class BundleServiceImpl implements BundleService {
     private static final String ORIGINAL_WIRES = "Original-Wires";
 
     private final BundleContext bundleContext;
-    private final List<BundleStateService> stateServices = new CopyOnWriteArrayList<BundleStateService>();
+    private final List<BundleStateService> stateServices = new CopyOnWriteArrayList<>();
 
     public BundleServiceImpl(BundleContext bundleContext) {
         this.bundleContext = bundleContext;
@@ -71,19 +73,22 @@ public class BundleServiceImpl implements BundleService {
 
     @Override
     public List<Bundle> selectBundles(List<String> ids, boolean defaultAllBundles) {
-        return new BundleSelectorImpl(bundleContext).selectBundles(ids, defaultAllBundles);
+        return selectBundles(null, ids, defaultAllBundles);
     }
 
     @Override
-    public Bundle getBundle(String id, boolean defaultAllBundles) {
-        List<String> ids = new ArrayList<String>(1);
-        ids.add(id);
-        List<Bundle> bundles = selectBundles(ids, defaultAllBundles);
-        if (bundles.isEmpty()) {            
-            return null;
-        } else {
-            return bundles.get(0);
-        }
+    public List<Bundle> selectBundles(String context, List<String> ids, boolean defaultAllBundles) {
+        return doSelectBundles(doGetBundleContext(context), ids, defaultAllBundles);
+    }
+
+    @Override
+    public Bundle getBundle(String id) {
+        return getBundle(null, id);
+    }
+
+    @Override
+    public Bundle getBundle(String context, String id) {
+        return doGetBundle(doGetBundleContext(context), id);
     }
 
     @Override
@@ -104,13 +109,14 @@ public class BundleServiceImpl implements BundleService {
         for (BundleStateService bundleStateService : stateServices) {
             String part = bundleStateService.getDiag(bundle);
             if (part != null) {
-                message.append(bundleStateService.getName() + "\n");
+                message.append(bundleStateService.getName());
+                message.append("\n");
                 message.append(part);
             }
         }
         if (bundle.getState() == Bundle.INSTALLED) {
             System.out.println("Unsatisfied Requirements:");
-            List<BundleRequirement> reqs = getUnsatisfiedRquirements(bundle, null);
+            List<BundleRequirement> reqs = getUnsatisfiedRequirements(bundle, null);
             for (BundleRequirement req : reqs) {
                 System.out.println(req);
             }
@@ -119,8 +125,8 @@ public class BundleServiceImpl implements BundleService {
     }
     
     @Override
-    public List<BundleRequirement> getUnsatisfiedRquirements(Bundle bundle, String namespace) {
-        List<BundleRequirement> result = new ArrayList<BundleRequirement>();
+    public List<BundleRequirement> getUnsatisfiedRequirements(Bundle bundle, String namespace) {
+        List<BundleRequirement> result = new ArrayList<>();
         BundleRevision rev = bundle.adapt(BundleRevision.class);
         if (rev != null) {
             List<BundleRequirement> reqs = rev.getDeclaredRequirements(namespace);
@@ -132,6 +138,72 @@ public class BundleServiceImpl implements BundleService {
         }
         return result;
     }
+
+    @Override
+    public int getSystemBundleThreshold() {
+        int sbsl = 50;
+        try {
+            final String sbslProp = bundleContext.getProperty("karaf.systemBundlesStartLevel");
+            if (sbslProp != null) {
+                sbsl = Integer.valueOf(sbslProp);
+            }
+        } catch (Exception ignore) {
+            // ignore
+        }
+        return sbsl;
+    }
+
+    private BundleContext doGetBundleContext(String context) {
+        if (context == null || context.trim().isEmpty()) {
+            return bundleContext;
+        } else {
+            List<Bundle> bundles = doSelectBundles(bundleContext, Collections.singletonList(context), false);
+            if (bundles.isEmpty()) {
+                throw new IllegalArgumentException("Context " + context + " does not evaluate to a bundle");
+            } else if (bundles.size() > 1) {
+                throw new IllegalArgumentException("Context " + context + " is ambiguous");
+            }
+            BundleContext bundleContext = bundles.get(0).getBundleContext();
+            if (bundleContext == null) {
+                throw new IllegalArgumentException("Context " + context + " is not resolved");
+            }
+            return bundleContext;
+        }
+    }
+
+    private Bundle doGetBundle(BundleContext bundleContext, String id) {
+        List<Bundle> bundles = doSelectBundles(bundleContext, Collections.singletonList(id), false);
+        if (bundles.isEmpty()) {
+            throw new IllegalArgumentException("Bundle " + id + " does not match any bundle");
+        } else {
+            List<Bundle> filtered = filter(bundles);
+            if (filtered.isEmpty()) {
+                throw new IllegalArgumentException("Access to bundle " + id + " is forbidden");
+            } else if (filtered.size() > 1) {
+                throw new IllegalArgumentException("Multiple bundles matching " + id);
+            }
+            return filtered.get(0);
+        }
+    }
+
+    private List<Bundle> doSelectBundles(BundleContext bundleContext, List<String> ids, boolean defaultAllBundles) {
+        return filter(new BundleSelectorImpl(bundleContext).selectBundles(ids, defaultAllBundles));
+    }
+
+    private List<Bundle> filter(List<Bundle> bundles) {
+        if (JaasHelper.currentUserHasRole(BundleService.SYSTEM_BUNDLES_ROLE)) {
+            return bundles;
+        }
+        int sbsl = getSystemBundleThreshold();
+        List<Bundle> filtered = new ArrayList<>();
+        for (Bundle bundle : bundles) {
+            int level = bundle.adapt(BundleStartLevel.class).getStartLevel();
+            if (level >= sbsl) {
+                filtered.add(bundle);
+            }
+        }
+        return filtered;
+    }
     
     private boolean canBeSatisfied(BundleRequirement req) {
         Bundle[] bundles = bundleContext.getBundles();
@@ -149,11 +221,6 @@ public class BundleServiceImpl implements BundleService {
         return false;
     }
 
-    @Override
-    public List<Bundle> getBundlesByURL(String urlFilter) {
-        return new BundleSelectorImpl(bundleContext).getBundlesByURL(urlFilter);
-    }
-
     /*
      * Enable DynamicImport=* on the bundle
      */
@@ -187,7 +254,7 @@ public class BundleServiceImpl implements BundleService {
      */
     public void disableDynamicImports(Bundle bundle) {
         Set<String> current = getWiredBundles(bundle).keySet();
-        for (String original : bundle.getHeaders().get(ORIGINAL_WIRES).toString().split(",")) {
+        for (String original : bundle.getHeaders().get(ORIGINAL_WIRES).split(",")) {
             current.remove(original);
         }
 
@@ -211,7 +278,7 @@ public class BundleServiceImpl implements BundleService {
      * Explode a set of string values in to a ,-delimited string
      */
     private String explode(Set<String> set) {
-        StringBuffer result = new StringBuffer();
+        StringBuilder result = new StringBuilder();
         Iterator<String> it = set.iterator();
         while (it.hasNext()) {
             result.append(it.next());
@@ -230,7 +297,7 @@ public class BundleServiceImpl implements BundleService {
      */
     public Map<String, Bundle> getWiredBundles(Bundle bundle) {
         // the set of bundles from which the bundle imports packages
-        Map<String, Bundle> exporters = new HashMap<String, Bundle>();
+        Map<String, Bundle> exporters = new HashMap<>();
 
         for (BundleRevision revision : bundle.adapt(BundleRevisions.class).getRevisions()) {
             BundleWiring wiring = revision.getWiring();

http://git-wip-us.apache.org/repos/asf/karaf/blob/ca651c8e/bundle/core/src/main/java/org/apache/karaf/bundle/core/internal/BundleWatcherImpl.java
----------------------------------------------------------------------
diff --git a/bundle/core/src/main/java/org/apache/karaf/bundle/core/internal/BundleWatcherImpl.java b/bundle/core/src/main/java/org/apache/karaf/bundle/core/internal/BundleWatcherImpl.java
index 665dc1b..cb52567 100644
--- a/bundle/core/src/main/java/org/apache/karaf/bundle/core/internal/BundleWatcherImpl.java
+++ b/bundle/core/src/main/java/org/apache/karaf/bundle/core/internal/BundleWatcherImpl.java
@@ -23,6 +23,7 @@ import java.io.IOException;
 import java.io.InputStream;
 import java.net.MalformedURLException;
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
@@ -91,8 +92,12 @@ public class BundleWatcherImpl implements Runnable, BundleListener, BundleWatche
                 oldCounter = counter.get();
                 watchedBundles.clear();
                 for (String bundleURL : watchURLs) {
-                    for (Bundle bundle : bundleService.getBundlesByURL(bundleURL)) {
-                        watchedBundles.add(bundle);
+                    // Transform into regexp
+                    bundleURL = bundleURL.replaceAll("\\*", ".*");
+                    for (Bundle bundle : bundleService.selectBundles(Collections.singletonList(bundleURL), false)) {
+                        if (isMavenSnapshotUrl(bundle.getLocation())) {
+                            watchedBundles.add(bundle);
+                        }
                     }
                 }
             }
@@ -141,6 +146,10 @@ public class BundleWatcherImpl implements Runnable, BundleListener, BundleWatche
         }
     }
 
+    private boolean isMavenSnapshotUrl(String url) {
+        return url.startsWith("mvn:") && url.contains("SNAPSHOT");
+    }
+
     private void updateBundleIfNecessary(File localRepository, List<Bundle> updated, Bundle bundle)
         throws FileNotFoundException, BundleException, IOException {
         File location = getBundleExternalLocation(localRepository, bundle);
@@ -248,7 +257,8 @@ public class BundleWatcherImpl implements Runnable, BundleListener, BundleWatche
 
 	@Override
 	public List<Bundle> getBundlesByURL(String urlFilter) {
-		return bundleService.getBundlesByURL(urlFilter);
+        urlFilter = urlFilter.replaceAll("\\*", ".*");
+		return bundleService.selectBundles(Collections.singletonList(urlFilter), false);
 	}
 
 }

http://git-wip-us.apache.org/repos/asf/karaf/blob/ca651c8e/bundle/core/src/test/java/org/apache/karaf/bundle/command/ListServicesTest.java
----------------------------------------------------------------------
diff --git a/bundle/core/src/test/java/org/apache/karaf/bundle/command/ListServicesTest.java b/bundle/core/src/test/java/org/apache/karaf/bundle/command/ListServicesTest.java
index 876f605..c4413b9 100644
--- a/bundle/core/src/test/java/org/apache/karaf/bundle/command/ListServicesTest.java
+++ b/bundle/core/src/test/java/org/apache/karaf/bundle/command/ListServicesTest.java
@@ -17,7 +17,6 @@
 package org.apache.karaf.bundle.command;
 
 import java.util.Arrays;
-import java.util.Collections;
 
 import org.apache.karaf.bundle.core.internal.BundleServiceImpl;
 import org.junit.Test;
@@ -25,12 +24,14 @@ import org.osgi.framework.BundleContext;
 
 public class ListServicesTest {
 
-    private ListBundleServices listServices;
+    private BundleContext bundleContext;
+    private Services listServices;
 
     @SuppressWarnings("unchecked")
     public ListServicesTest() {
-        listServices = new ListBundleServices();
-        BundleContext bundleContext = new TestBundleFactory().createBundleContext();
+        listServices = new Services();
+        bundleContext = new TestBundleFactory().createBundleContext();
+        listServices.context = null;
         listServices.setBundleContext(bundleContext);
         listServices.setBundleService(new BundleServiceImpl(bundleContext));
     }

http://git-wip-us.apache.org/repos/asf/karaf/blob/ca651c8e/bundle/core/src/test/java/org/apache/karaf/bundle/command/TestBundleFactory.java
----------------------------------------------------------------------
diff --git a/bundle/core/src/test/java/org/apache/karaf/bundle/command/TestBundleFactory.java b/bundle/core/src/test/java/org/apache/karaf/bundle/command/TestBundleFactory.java
index 27e4a63..6912c41 100644
--- a/bundle/core/src/test/java/org/apache/karaf/bundle/command/TestBundleFactory.java
+++ b/bundle/core/src/test/java/org/apache/karaf/bundle/command/TestBundleFactory.java
@@ -28,6 +28,7 @@ import org.osgi.framework.Bundle;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.Constants;
 import org.osgi.framework.ServiceReference;
+import org.osgi.framework.startlevel.BundleStartLevel;
 
 public class TestBundleFactory {
     ServiceReference<?> createServiceRef(Object ... keyProp) {
@@ -61,6 +62,8 @@ public class TestBundleFactory {
         Bundle bundle2 = createBundle(2, "Bundle B");
         Bundle bundle3 = createBundle(3, "Bundle C");
 
+        BundleStartLevel bsl = createMock(BundleStartLevel.class);
+
         ServiceReference<?> ref1 = createServiceRef(Constants.OBJECTCLASS, new String[]{"org.example.MyService"},
             "key1", "value1");
         ServiceReference<?> ref2 = createServiceRef(Constants.OBJECTCLASS, new String[]{"org.example.OtherService"}, "key2", 1);
@@ -76,7 +79,13 @@ public class TestBundleFactory {
         expect(ref1.getUsingBundles()).andReturn(new Bundle[]{bundle2, bundle3}).anyTimes();
         expect(ref2.getUsingBundles()).andReturn(new Bundle[]{bundle3}).anyTimes();
 
-        replay(bundle1, bundle2, bundle3, ref1, ref2);
+        expect(bundle1.adapt(BundleStartLevel.class)).andReturn(bsl).anyTimes();
+        expect(bundle2.adapt(BundleStartLevel.class)).andReturn(bsl).anyTimes();
+        expect(bundle3.adapt(BundleStartLevel.class)).andReturn(bsl).anyTimes();
+
+        expect(bsl.getStartLevel()).andReturn(80).anyTimes();
+
+        replay(bundle1, bundle2, bundle3, ref1, ref2, bsl);
         return new Bundle[] { bundle1, bundle2, bundle3 };
     }
     
@@ -94,6 +103,7 @@ public class TestBundleFactory {
     public BundleContext createBundleContext() {
         BundleContext bundleContext = createMock(BundleContext.class);
         Bundle[] bundles = createBundles();
+        expect(bundleContext.getProperty("karaf.systemBundlesStartLevel")).andReturn(Integer.toString(50)).anyTimes();
         expect(bundleContext.getBundles()).andReturn(bundles).anyTimes();
         expect(bundleContext.getBundle(0)).andReturn(null).anyTimes();
         expect(bundleContext.getBundle(1)).andReturn(bundles[0]).anyTimes();

http://git-wip-us.apache.org/repos/asf/karaf/blob/ca651c8e/jaas/modules/src/main/java/org/apache/karaf/jaas/modules/JaasHelper.java
----------------------------------------------------------------------
diff --git a/jaas/modules/src/main/java/org/apache/karaf/jaas/modules/JaasHelper.java b/jaas/modules/src/main/java/org/apache/karaf/jaas/modules/JaasHelper.java
index 111df95..05489ed 100644
--- a/jaas/modules/src/main/java/org/apache/karaf/jaas/modules/JaasHelper.java
+++ b/jaas/modules/src/main/java/org/apache/karaf/jaas/modules/JaasHelper.java
@@ -25,8 +25,37 @@ import java.security.ProtectionDomain;
 import javax.security.auth.Subject;
 import javax.security.auth.SubjectDomainCombiner;
 
+import org.apache.karaf.jaas.boot.principal.RolePrincipal;
+
 public class JaasHelper {
 
+    public static boolean currentUserHasRole(String requestedRole) {
+        String clazz;
+        String role;
+        int index = requestedRole.indexOf(':');
+        if (index > 0) {
+            clazz = requestedRole.substring(0, index);
+            role = requestedRole.substring(index + 1);
+        } else {
+            clazz = RolePrincipal.class.getName();
+            role = requestedRole;
+        }
+        AccessControlContext acc = AccessController.getContext();
+        if (acc == null) {
+            return false;
+        }
+        Subject subject = Subject.getSubject(acc);
+        if (subject == null) {
+            return false;
+        }
+        for (Principal p : subject.getPrincipals()) {
+            if (clazz.equals(p.getClass().getName()) && role.equals(p.getName())) {
+                return true;
+            }
+        }
+        return false;
+    }
+
     public static <T> T doAs(final Subject subject,
                              final PrivilegedAction<T> action) {
         if (action == null) {


[3/4] git commit: [KARAF-2949] Use a jaas role to allow access to system bundles [KARAF-2923] Enhance bundle commands to support regions

Posted by gn...@apache.org.
[KARAF-2949] Use a jaas role to allow access to system bundles
[KARAF-2923] Enhance bundle commands to support regions


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

Branch: refs/heads/master
Commit: ca651c8e678e98d78be49b576f0d98bbf37b1fe2
Parents: c10dde0
Author: Guillaume Nodet <gn...@gmail.com>
Authored: Mon Apr 28 16:02:04 2014 +0200
Committer: Guillaume Nodet <gn...@gmail.com>
Committed: Mon Apr 28 20:01:25 2014 +0200

----------------------------------------------------------------------
 .../resources/resources/etc/users.properties    |   2 +-
 bundle/core/pom.xml                             |   9 +
 .../karaf/bundle/command/BundleCommand.java     |  32 ++--
 .../command/BundleCommandWithConfirmation.java  |  37 ----
 .../karaf/bundle/command/BundlesCommand.java    |  54 +++---
 .../command/BundlesCommandWithConfirmation.java |  62 -------
 .../karaf/bundle/command/Capabilities.java      |  12 +-
 .../apache/karaf/bundle/command/Classes.java    |  13 +-
 .../org/apache/karaf/bundle/command/Diag.java   |  27 ++-
 .../karaf/bundle/command/DynamicImport.java     |   7 +-
 .../apache/karaf/bundle/command/Headers.java    |  13 +-
 .../org/apache/karaf/bundle/command/Id.java     |  44 +----
 .../org/apache/karaf/bundle/command/Info.java   |  27 +--
 .../apache/karaf/bundle/command/Install.java    |  53 +++---
 .../org/apache/karaf/bundle/command/List.java   | 161 +++++++++++++++++
 .../bundle/command/ListBundleServices.java      | 116 ------------
 .../karaf/bundle/command/ListBundles.java       | 176 -------------------
 .../apache/karaf/bundle/command/Refresh.java    |   7 +-
 .../karaf/bundle/command/Requirements.java      |   9 +-
 .../apache/karaf/bundle/command/Resolve.java    |  11 +-
 .../apache/karaf/bundle/command/Restart.java    |  12 +-
 .../apache/karaf/bundle/command/Services.java   | 110 ++++++++++++
 .../karaf/bundle/command/ShowBundleTree.java    |   7 +-
 .../org/apache/karaf/bundle/command/Start.java  |  13 +-
 .../apache/karaf/bundle/command/StartLevel.java |  32 ++--
 .../org/apache/karaf/bundle/command/Stop.java   |  11 +-
 .../apache/karaf/bundle/command/Uninstall.java  |   5 +-
 .../org/apache/karaf/bundle/command/Update.java |  13 +-
 .../apache/karaf/bundle/core/BundleService.java |  16 +-
 .../core/internal/BundleSelectorImpl.java       |  82 ++++-----
 .../bundle/core/internal/BundleServiceImpl.java | 113 +++++++++---
 .../bundle/core/internal/BundleWatcherImpl.java |  16 +-
 .../karaf/bundle/command/ListServicesTest.java  |   9 +-
 .../karaf/bundle/command/TestBundleFactory.java |  12 +-
 .../apache/karaf/jaas/modules/JaasHelper.java   |  29 +++
 35 files changed, 629 insertions(+), 723 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/karaf/blob/ca651c8e/assemblies/features/framework/src/main/resources/resources/etc/users.properties
----------------------------------------------------------------------
diff --git a/assemblies/features/framework/src/main/resources/resources/etc/users.properties b/assemblies/features/framework/src/main/resources/resources/etc/users.properties
index 0ff30c8..8ff1161 100644
--- a/assemblies/features/framework/src/main/resources/resources/etc/users.properties
+++ b/assemblies/features/framework/src/main/resources/resources/etc/users.properties
@@ -30,4 +30,4 @@
 # with the name "karaf".
 #
 karaf = karaf,_g_:admingroup
-_g_\:admingroup = group,admin,manager,viewer
+_g_\:admingroup = group,admin,manager,viewer,systembundles

http://git-wip-us.apache.org/repos/asf/karaf/blob/ca651c8e/bundle/core/pom.xml
----------------------------------------------------------------------
diff --git a/bundle/core/pom.xml b/bundle/core/pom.xml
index b698d48..edea01d 100644
--- a/bundle/core/pom.xml
+++ b/bundle/core/pom.xml
@@ -85,6 +85,12 @@
         </dependency>
 
         <dependency>
+            <groupId>org.apache.karaf.jaas</groupId>
+            <artifactId>org.apache.karaf.jaas.modules</artifactId>
+            <scope>provided</scope>
+        </dependency>
+
+        <dependency>
             <groupId>org.slf4j</groupId>
             <artifactId>slf4j-jdk14</artifactId>
             <scope>test</scope>
@@ -125,6 +131,9 @@
                             org.apache.felix.utils.version,
                             org.apache.felix.utils.manifest
                         </Private-Package>
+                        <Embed-Dependency>
+                            org.apache.karaf.jaas.modules;inline="org/apache/karaf/jaas/modules/JaasHelper*.class"
+                        </Embed-Dependency>
                         <Bundle-Activator>
                             org.apache.karaf.bundle.core.internal.osgi.Activator
                         </Bundle-Activator>

http://git-wip-us.apache.org/repos/asf/karaf/blob/ca651c8e/bundle/core/src/main/java/org/apache/karaf/bundle/command/BundleCommand.java
----------------------------------------------------------------------
diff --git a/bundle/core/src/main/java/org/apache/karaf/bundle/command/BundleCommand.java b/bundle/core/src/main/java/org/apache/karaf/bundle/command/BundleCommand.java
index e7ce42a..99582fa 100644
--- a/bundle/core/src/main/java/org/apache/karaf/bundle/command/BundleCommand.java
+++ b/bundle/core/src/main/java/org/apache/karaf/bundle/command/BundleCommand.java
@@ -16,9 +16,13 @@
  */
 package org.apache.karaf.bundle.command;
 
+import java.util.Collections;
+import java.util.List;
+
 import org.apache.karaf.bundle.core.BundleService;
 import org.apache.karaf.shell.api.action.Action;
 import org.apache.karaf.shell.api.action.Argument;
+import org.apache.karaf.shell.api.action.Option;
 import org.apache.karaf.shell.api.action.lifecycle.Reference;
 import org.apache.karaf.shell.support.ShellUtil;
 import org.osgi.framework.Bundle;
@@ -29,40 +33,24 @@ import org.osgi.framework.BundleContext;
  */
 public abstract class BundleCommand implements Action {
 
+    @Option(name = "--context", description = "Use the given bundle context")
+    String context = "0";
+
     @Argument(index = 0, name = "id", description = "The bundle ID or name or name/version", required = true, multiValued = false)
     String id;
 
-    boolean defaultAllBundles = true;
-
     @Reference
     BundleService bundleService;
 
     @Reference
     BundleContext bundleContext;
 
-    public BundleCommand(boolean defaultAllBundles) {
-        this.defaultAllBundles = defaultAllBundles;
-    }
-
     public Object execute() throws Exception {
-        return doExecute(true);
-    }
-
-    protected Object doExecute(boolean force) throws Exception {
-        Bundle bundle = bundleService.getBundle(id, defaultAllBundles);
-        if (bundle != null) {
-            if (force || !ShellUtil.isASystemBundle(bundleContext, bundle)) {
-                doExecute(bundle);
-            } else {
-                System.err.println("Access to system bundle " + id + " is discouraged. You may override with -f");
-            }
-        } else {
-            System.err.println("Bundle " + id + " is not found");
-        }
-        return null;
+        Bundle bundle = bundleService.getBundle(id);
+        return doExecute(bundle);
     }
 
-    protected abstract void doExecute(Bundle bundle) throws Exception;
+    protected abstract Object doExecute(Bundle bundle) throws Exception;
 
     public void setBundleService(BundleService bundleService) {
         this.bundleService = bundleService;

http://git-wip-us.apache.org/repos/asf/karaf/blob/ca651c8e/bundle/core/src/main/java/org/apache/karaf/bundle/command/BundleCommandWithConfirmation.java
----------------------------------------------------------------------
diff --git a/bundle/core/src/main/java/org/apache/karaf/bundle/command/BundleCommandWithConfirmation.java b/bundle/core/src/main/java/org/apache/karaf/bundle/command/BundleCommandWithConfirmation.java
deleted file mode 100644
index c07a357..0000000
--- a/bundle/core/src/main/java/org/apache/karaf/bundle/command/BundleCommandWithConfirmation.java
+++ /dev/null
@@ -1,37 +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.bundle.command;
-
-import org.apache.karaf.shell.api.action.Option;
-
-/**
- * Unique bundle command with confirmation while accessing system bundle.
- */
-public abstract class BundleCommandWithConfirmation extends BundleCommand {
-
-    @Option(name = "--force", aliases = {"-f"}, description = "Forces the command to execute", required = false, multiValued = false)
-    boolean force;
-
-    public BundleCommandWithConfirmation() {
-        super(true);
-    }
-
-    public Object execute() throws Exception {
-        return doExecute(force);
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/ca651c8e/bundle/core/src/main/java/org/apache/karaf/bundle/command/BundlesCommand.java
----------------------------------------------------------------------
diff --git a/bundle/core/src/main/java/org/apache/karaf/bundle/command/BundlesCommand.java b/bundle/core/src/main/java/org/apache/karaf/bundle/command/BundlesCommand.java
index ff4dd53..25a2125 100644
--- a/bundle/core/src/main/java/org/apache/karaf/bundle/command/BundlesCommand.java
+++ b/bundle/core/src/main/java/org/apache/karaf/bundle/command/BundlesCommand.java
@@ -16,64 +16,68 @@
  */
 package org.apache.karaf.bundle.command;
 
+import java.util.ArrayList;
 import java.util.List;
 
 import org.apache.karaf.bundle.core.BundleService;
+import org.apache.karaf.bundle.core.internal.BundleSelectorImpl;
 import org.apache.karaf.shell.api.action.Action;
 import org.apache.karaf.shell.api.action.Argument;
+import org.apache.karaf.shell.api.action.Option;
 import org.apache.karaf.shell.api.action.lifecycle.Reference;
+import org.apache.karaf.shell.support.MultiException;
 import org.apache.karaf.shell.support.ShellUtil;
 import org.osgi.framework.Bundle;
 import org.osgi.framework.BundleContext;
 
 public abstract class BundlesCommand implements Action {
 
+    @Option(name = "--context", aliases = {"-c"}, description = "Use the given bundle context")
+    String context = "0";
+
     @Argument(index = 0, name = "ids", description = "The list of bundle (identified by IDs or name or name/version) separated by whitespaces", required = false, multiValued = true)
     List<String> ids;
     
-    boolean defaultAllBundles = true;
-
     @Reference
     BundleContext bundleContext;
 
     @Reference
     BundleService bundleService;
-    
-    public BundlesCommand(boolean defaultAllBundles) {
-        this.defaultAllBundles = defaultAllBundles;
-    }
 
-    public void setBundleContext(BundleContext bundleContext) {
-        this.bundleContext = bundleContext;
-    }
+    protected boolean defaultAllBundles = true;
+
+    protected String errorMessage = "Unable to execute command on bundle ";
 
     @Override
     public Object execute() throws Exception {
-        doExecute(true);
-        return null;
-    }
-
-    protected Object doExecute(boolean force) throws Exception {
-        List<Bundle> bundles = bundleService.selectBundles(ids, defaultAllBundles);
-        if (!force) {
-            assertNoSystemBundles(bundles);
-        }
-        doExecute(bundles);
-        return null;
+        List<Bundle> bundles =  bundleService.selectBundles(context, ids, defaultAllBundles);
+        return doExecute(bundles);
     }
     
-    private void assertNoSystemBundles(List<Bundle> bundles) {
+    protected Object doExecute(List<Bundle> bundles) throws Exception {
+        if (bundles.isEmpty()) {
+            throw new IllegalArgumentException("No matching bundles");
+        }
+        List<Exception> exceptions = new ArrayList<Exception>();
         for (Bundle bundle : bundles) {
-            if (ShellUtil.isASystemBundle(bundleContext, bundle)) {
-                throw new RuntimeException("Access to system bundle " + bundle.getBundleId() + " denied. You can override with -f");
+            try {
+                executeOnBundle(bundle);
+            } catch (Exception e) {
+                exceptions.add(new Exception(errorMessage + bundle.getBundleId() + ": " + e.getMessage(), e));
             }
         }
+        MultiException.throwIf("Error executing command on bundles", exceptions);
+        return null;
     }
-      
-    protected abstract void doExecute(List<Bundle> bundles) throws Exception;
+
+    protected abstract void executeOnBundle(Bundle bundle) throws Exception;
 
     public void setBundleService(BundleService bundleService) {
         this.bundleService = bundleService;
     }
 
+    public void setBundleContext(BundleContext bundleContext) {
+        this.bundleContext = bundleContext;
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/karaf/blob/ca651c8e/bundle/core/src/main/java/org/apache/karaf/bundle/command/BundlesCommandWithConfirmation.java
----------------------------------------------------------------------
diff --git a/bundle/core/src/main/java/org/apache/karaf/bundle/command/BundlesCommandWithConfirmation.java b/bundle/core/src/main/java/org/apache/karaf/bundle/command/BundlesCommandWithConfirmation.java
deleted file mode 100644
index 271fc42..0000000
--- a/bundle/core/src/main/java/org/apache/karaf/bundle/command/BundlesCommandWithConfirmation.java
+++ /dev/null
@@ -1,62 +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.bundle.command;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import org.apache.karaf.shell.api.action.Option;
-import org.apache.karaf.shell.support.MultiException;
-import org.osgi.framework.Bundle;
-
-/**
- * Command related to bundles requiring read-write access to the bundle (including system bundle).
- */
-public abstract class BundlesCommandWithConfirmation extends BundlesCommand {
-
-    @Option(name = "--force", aliases = {"-f"}, description = "Forces the command to execute", required = false, multiValued = false)
-    boolean force;
-    
-    protected String errorMessage = "Unable to execute command on bundle ";
-    
-    public BundlesCommandWithConfirmation() {
-        super(false);
-    }
-
-    protected Object doExecute() throws Exception {
-        doExecute(force);
-        return null;
-    }
-
-    protected void doExecute(List<Bundle> bundles) throws Exception {
-        if (bundles.isEmpty()) {
-            System.err.println("No bundles specified.");
-            return;
-        }
-        List<Exception> exceptions = new ArrayList<Exception>();
-        for (Bundle bundle : bundles) {
-            try {
-                executeOnBundle(bundle);
-            } catch (Exception e) {
-                exceptions.add(new Exception(errorMessage + bundle.getBundleId() + ": " + e.getMessage(), e));
-            }
-        }
-        MultiException.throwIf("Error executing command on bundles", exceptions);
-    }
-    
-    protected abstract void executeOnBundle(Bundle bundle) throws Exception;
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/ca651c8e/bundle/core/src/main/java/org/apache/karaf/bundle/command/Capabilities.java
----------------------------------------------------------------------
diff --git a/bundle/core/src/main/java/org/apache/karaf/bundle/command/Capabilities.java b/bundle/core/src/main/java/org/apache/karaf/bundle/command/Capabilities.java
index de83a1d..e952aa6 100644
--- a/bundle/core/src/main/java/org/apache/karaf/bundle/command/Capabilities.java
+++ b/bundle/core/src/main/java/org/apache/karaf/bundle/command/Capabilities.java
@@ -36,6 +36,7 @@ import org.osgi.framework.wiring.BundleWiring;
 @Command(scope = "bundle", name = "capabilities", description = "Displays OSGi capabilities of a given bundles.")
 @Service
 public class Capabilities extends BundlesCommand {
+
     public static final String NONSTANDARD_SERVICE_NAMESPACE = "service";
 
     private static final String EMPTY_MESSAGE = "[EMPTY]";
@@ -44,12 +45,8 @@ public class Capabilities extends BundlesCommand {
     @Option(name = "--namespace")
     String namespace = "*";
 
-    public Capabilities() {
-        super(true);
-    }
-    
     @Override
-    protected void doExecute(List<Bundle> bundles) throws Exception {
+    protected Object doExecute(List<Bundle> bundles) throws Exception {
         boolean separatorNeeded = false;
         Pattern ns = Pattern.compile(namespace.replaceAll("\\.", "\\\\.").replaceAll("\\*", ".*"));
         for (Bundle b : bundles)
@@ -90,6 +87,11 @@ public class Capabilities extends BundlesCommand {
             }
             separatorNeeded = true;
         }
+        return null;
+    }
+
+    @Override
+    protected void executeOnBundle(Bundle bundle) throws Exception {
     }
 
     private static boolean printMatchingCapabilities(BundleWiring wiring, Pattern namespace)

http://git-wip-us.apache.org/repos/asf/karaf/blob/ca651c8e/bundle/core/src/main/java/org/apache/karaf/bundle/command/Classes.java
----------------------------------------------------------------------
diff --git a/bundle/core/src/main/java/org/apache/karaf/bundle/command/Classes.java b/bundle/core/src/main/java/org/apache/karaf/bundle/command/Classes.java
index b0f80ff..670fac1 100644
--- a/bundle/core/src/main/java/org/apache/karaf/bundle/command/Classes.java
+++ b/bundle/core/src/main/java/org/apache/karaf/bundle/command/Classes.java
@@ -32,17 +32,8 @@ public class Classes extends BundlesCommand {
     @Option(name = "-a", aliases={"--display-all-files"}, description="List all classes and files in the bundle", required = false, multiValued = false)
     boolean displayAllFiles;
 
-    public Classes() {
-        super(true);
-    }
-
-    protected void doExecute(List<Bundle> bundles) throws Exception {
-        for (Bundle bundle : bundles) {
-            printResources(bundle);
-        }
-    }
-
-    protected void printResources(Bundle bundle) {
+    @Override
+    protected void executeOnBundle(Bundle bundle) throws Exception {
         BundleWiring wiring = bundle.adapt(BundleWiring.class);
         if (wiring != null){
             Collection<String> resources;

http://git-wip-us.apache.org/repos/asf/karaf/blob/ca651c8e/bundle/core/src/main/java/org/apache/karaf/bundle/command/Diag.java
----------------------------------------------------------------------
diff --git a/bundle/core/src/main/java/org/apache/karaf/bundle/command/Diag.java b/bundle/core/src/main/java/org/apache/karaf/bundle/command/Diag.java
index 1e8e11b..4a1d6d7 100644
--- a/bundle/core/src/main/java/org/apache/karaf/bundle/command/Diag.java
+++ b/bundle/core/src/main/java/org/apache/karaf/bundle/command/Diag.java
@@ -29,22 +29,17 @@ import org.osgi.framework.Bundle;
 @Service
 public class Diag extends BundlesCommand {
 
-    public Diag() {
-        super(true);
-    }
-
-    protected void doExecute(List<Bundle> bundles) throws Exception {
-        for (Bundle bundle : bundles) {
-            BundleInfo info = bundleService.getInfo(bundle);
-            if (info.getState() == BundleState.Failure || info.getState() == BundleState.Waiting
-                || info.getState() == BundleState.GracePeriod || info.getState() == BundleState.Installed) {
-                String title = ShellUtil.getBundleName(bundle);
-                System.out.println(title);
-                System.out.println(ShellUtil.getUnderlineString(title));
-                System.out.println("Status: " + info.getState().toString());
-                System.out.println(this.bundleService.getDiag(bundle));
-                System.out.println();
-            }
+    @Override
+    protected void executeOnBundle(Bundle bundle) throws Exception {
+        BundleInfo info = bundleService.getInfo(bundle);
+        if (info.getState() == BundleState.Failure || info.getState() == BundleState.Waiting
+            || info.getState() == BundleState.GracePeriod || info.getState() == BundleState.Installed) {
+            String title = ShellUtil.getBundleName(bundle);
+            System.out.println(title);
+            System.out.println(ShellUtil.getUnderlineString(title));
+            System.out.println("Status: " + info.getState().toString());
+            System.out.println(this.bundleService.getDiag(bundle));
+            System.out.println();
         }
     }
 

http://git-wip-us.apache.org/repos/asf/karaf/blob/ca651c8e/bundle/core/src/main/java/org/apache/karaf/bundle/command/DynamicImport.java
----------------------------------------------------------------------
diff --git a/bundle/core/src/main/java/org/apache/karaf/bundle/command/DynamicImport.java b/bundle/core/src/main/java/org/apache/karaf/bundle/command/DynamicImport.java
index 74fc20a..31f52c2 100644
--- a/bundle/core/src/main/java/org/apache/karaf/bundle/command/DynamicImport.java
+++ b/bundle/core/src/main/java/org/apache/karaf/bundle/command/DynamicImport.java
@@ -28,12 +28,8 @@ import org.osgi.framework.Bundle;
 @Service
 public class DynamicImport extends BundleCommand {
 
-    public DynamicImport() {
-        super(true);
-    }
-
     @Override
-    protected void doExecute(Bundle bundle) throws Exception {
+    protected Object doExecute(Bundle bundle) throws Exception {
         if (bundleService.isDynamicImport(bundle)) {
             System.out.printf("Disabling dynamic imports on bundle %s%n", bundle);
             bundleService.disableDynamicImports(bundle);
@@ -41,6 +37,7 @@ public class DynamicImport extends BundleCommand {
             System.out.printf("Enabling dynamic imports on bundle %s%n", bundle);
             bundleService.enableDynamicImports(bundle);
         }
+        return null;
     }
 
 }

http://git-wip-us.apache.org/repos/asf/karaf/blob/ca651c8e/bundle/core/src/main/java/org/apache/karaf/bundle/command/Headers.java
----------------------------------------------------------------------
diff --git a/bundle/core/src/main/java/org/apache/karaf/bundle/command/Headers.java b/bundle/core/src/main/java/org/apache/karaf/bundle/command/Headers.java
index 5cf92c3..69822be 100644
--- a/bundle/core/src/main/java/org/apache/karaf/bundle/command/Headers.java
+++ b/bundle/core/src/main/java/org/apache/karaf/bundle/command/Headers.java
@@ -62,18 +62,9 @@ public class Headers extends BundlesCommand {
 
     @Reference
     Terminal terminal;
-    
-    public Headers() {
-        super(true);
-    }
-
-    protected void doExecute(List<Bundle> bundles) throws Exception {
-        for (Bundle bundle : bundles) {
-            printHeaders(bundle);
-        }
-    }
 
-    protected void printHeaders(Bundle bundle) throws Exception {
+    @Override
+    protected void executeOnBundle(Bundle bundle) throws Exception {
         String title = ShellUtil.getBundleName(bundle);
         System.out.println("\n" + title);
         System.out.println(ShellUtil.getUnderlineString(title));

http://git-wip-us.apache.org/repos/asf/karaf/blob/ca651c8e/bundle/core/src/main/java/org/apache/karaf/bundle/command/Id.java
----------------------------------------------------------------------
diff --git a/bundle/core/src/main/java/org/apache/karaf/bundle/command/Id.java b/bundle/core/src/main/java/org/apache/karaf/bundle/command/Id.java
index 1e346b3..c843263 100644
--- a/bundle/core/src/main/java/org/apache/karaf/bundle/command/Id.java
+++ b/bundle/core/src/main/java/org/apache/karaf/bundle/command/Id.java
@@ -30,47 +30,11 @@ import org.osgi.framework.BundleContext;
 
 @Command(scope = "bundle", name = "id", description = "Gets the bundle ID.")
 @Service
-public class Id implements Action {
+public class Id extends BundleCommand {
 
-    @Argument(index = 0, name = "name", description = "The bundle name, name/version, or location", required = true, multiValued = false)
-    String name;
-
-    @Reference
-    BundleService bundleService;
-
-    @Reference
-    BundleContext bundleContext;
-
-    public Object execute() throws Exception {
-        return doExecute(true);
+    @Override
+    protected Object doExecute(Bundle bundle) throws Exception {
+        return bundle.getBundleId();
     }
 
-    protected Object doExecute(boolean force) throws Exception {
-        Bundle bundle = bundleService.getBundle(name, true);
-        
-        // if name or name/version were not successful, let's try searching by location
-        if (bundle == null) {
-            for (int i = 0; i < bundleContext.getBundles().length; i++) {
-                Bundle b = bundleContext.getBundles()[i];
-                if (name.equals(b.getLocation())) {
-                    bundle = b;
-                    break;
-                }
-            }
-        }
-        if (bundle != null) {            
-            if (force || !ShellUtil.isASystemBundle(bundleContext, bundle)) {                
-                return bundle.getBundleId();
-            } else {
-                System.err.println("Access to system bundle " + name + " is discouraged. You may override with -f");
-            }
-        } else {
-            System.err.println("Bundle " + name + " is not found");
-        }
-        return null;
-    }
-
-    public void setBundleService(BundleService bundleService) {
-        this.bundleService = bundleService;
-    }
 }

http://git-wip-us.apache.org/repos/asf/karaf/blob/ca651c8e/bundle/core/src/main/java/org/apache/karaf/bundle/command/Info.java
----------------------------------------------------------------------
diff --git a/bundle/core/src/main/java/org/apache/karaf/bundle/command/Info.java b/bundle/core/src/main/java/org/apache/karaf/bundle/command/Info.java
index 451ec87..a2e2ea2 100644
--- a/bundle/core/src/main/java/org/apache/karaf/bundle/command/Info.java
+++ b/bundle/core/src/main/java/org/apache/karaf/bundle/command/Info.java
@@ -20,6 +20,7 @@ import java.io.BufferedReader;
 import java.io.IOException;
 import java.io.InputStreamReader;
 import java.net.URL;
+import java.nio.Buffer;
 import java.util.List;
 
 import org.apache.karaf.bundle.command.wikidoc.AnsiPrintingWikiVisitor;
@@ -34,16 +35,6 @@ import org.osgi.framework.Bundle;
 @Service
 public class Info extends BundlesCommand {
 
-    public Info() {
-        super(true);
-    }
-
-    protected void doExecute(List<Bundle> bundles) throws Exception {
-        for (Bundle bundle : bundles) {
-          printInfo(bundle);
-        }
-    }
-
     /**
      * <p>
      * Get the OSGI-INF/bundle.info entry from the bundle and display it.
@@ -51,27 +42,21 @@ public class Info extends BundlesCommand {
      *
      * @param bundle the bundle.
      */
-    protected void printInfo(Bundle bundle) {
+    @Override
+    protected void executeOnBundle(Bundle bundle) throws Exception {
         String title = ShellUtil.getBundleName(bundle);
         System.out.println("\n" + title);
         System.out.println(ShellUtil.getUnderlineString(title));
         URL bundleInfo = bundle.getEntry("OSGI-INF/bundle.info");
         if (bundleInfo != null) {
-        	BufferedReader reader = null;
-            try {
-                reader = new BufferedReader(new InputStreamReader(bundleInfo.openStream()));
+            try (
+                BufferedReader reader = new BufferedReader(new InputStreamReader(bundleInfo.openStream()));
+            ) {
                 WikiVisitor visitor = new AnsiPrintingWikiVisitor(System.out);
                 WikiParser parser = new WikiParser(visitor);
                 parser.parse(reader);
             } catch (Exception e) {
                 // ignore
-            } finally {
-            	if (reader != null) {
-            		try {
-						reader.close();
-					} catch (IOException e) {
-					}
-            	}
             }
         }
     }

http://git-wip-us.apache.org/repos/asf/karaf/blob/ca651c8e/bundle/core/src/main/java/org/apache/karaf/bundle/command/Install.java
----------------------------------------------------------------------
diff --git a/bundle/core/src/main/java/org/apache/karaf/bundle/command/Install.java b/bundle/core/src/main/java/org/apache/karaf/bundle/command/Install.java
index 021ed99..e501762 100644
--- a/bundle/core/src/main/java/org/apache/karaf/bundle/command/Install.java
+++ b/bundle/core/src/main/java/org/apache/karaf/bundle/command/Install.java
@@ -19,6 +19,8 @@ package org.apache.karaf.bundle.command;
 import java.util.ArrayList;
 import java.util.List;
 
+import org.apache.karaf.bundle.core.BundleService;
+import org.apache.karaf.jaas.modules.JaasHelper;
 import org.apache.karaf.shell.api.action.Action;
 import org.apache.karaf.shell.api.action.Argument;
 import org.apache.karaf.shell.api.action.Command;
@@ -49,15 +51,26 @@ public class Install implements Action {
     
     @Reference
     Session session;
-    
+
+    @Reference
+    BundleService bundleService;
+
     @Reference
     BundleContext bundleContext;
 
     @Override
     public Object execute() throws Exception {
+        if (level != null) {
+            int sbsl = bundleService.getSystemBundleThreshold();
+            if (level < sbsl) {
+                if (!JaasHelper.currentUserHasRole(BundleService.SYSTEM_BUNDLES_ROLE)) {
+                    throw new IllegalArgumentException("Insufficient priviledges");
+                }
+            }
+        }
         // install the bundles
-        List<Exception> exceptions = new ArrayList<Exception>();
-        List<Bundle> bundles = new ArrayList<Bundle>();
+        List<Exception> exceptions = new ArrayList<>();
+        List<Bundle> bundles = new ArrayList<>();
         for (String url : urls) {
             try {
                 bundles.add(bundleContext.installBundle(url, null));
@@ -65,25 +78,16 @@ public class Install implements Action {
                 exceptions.add(new Exception("Unable to install bundle " + url, e));
             }
         }
-        
-        // optionally set the start level of the bundles
+        // optionally set start level
         if (level != null) {
-            if (level < 50 && !force){
-                for (;;) {
-                    String msg = "You are about to designate bundle as a system bundle.  Do you still wish to set the start level (yes/no): ";
-                    String str = session.readLine(msg, null);
-                    if ("yes".equalsIgnoreCase(str)) {
-                        setStartLevel(bundles);    
-                        break;
-                    } else if ("no".equalsIgnoreCase(str)) {
-                        break;
-                    }
-                }                
-            } else {
-                setStartLevel(bundles);    
+            for (Bundle bundle : bundles) {
+                try {
+                    bundle.adapt(BundleStartLevel.class).setStartLevel(level);
+                } catch (Exception e) {
+                    exceptions.add(new Exception("Unable to set bundle start level " + bundle.getLocation(), e));
+                }
             }
         }
-        
         // optionally start the bundles
         if (start) {
             for (Bundle bundle : bundles) {
@@ -112,15 +116,4 @@ public class Install implements Action {
         return null;
     }
 
-    private void setStartLevel(List<Bundle> bundles) {
-        for (Bundle bundle : bundles) {
-            BundleStartLevel bsl = bundle.adapt(BundleStartLevel.class);
-            if (bsl == null) {
-                System.out.println("StartLevel service is unavailable for bundle id " + bundle);
-                return;
-            }
-            bsl.setStartLevel(level);
-        }
-    }
-
 }

http://git-wip-us.apache.org/repos/asf/karaf/blob/ca651c8e/bundle/core/src/main/java/org/apache/karaf/bundle/command/List.java
----------------------------------------------------------------------
diff --git a/bundle/core/src/main/java/org/apache/karaf/bundle/command/List.java b/bundle/core/src/main/java/org/apache/karaf/bundle/command/List.java
new file mode 100644
index 0000000..14b2523
--- /dev/null
+++ b/bundle/core/src/main/java/org/apache/karaf/bundle/command/List.java
@@ -0,0 +1,161 @@
+/*
+ * 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.bundle.command;
+
+import org.apache.karaf.bundle.core.BundleInfo;
+import org.apache.karaf.bundle.core.BundleService;
+import org.apache.karaf.bundle.core.BundleState;
+import org.apache.karaf.shell.api.action.Action;
+import org.apache.karaf.shell.api.action.Command;
+import org.apache.karaf.shell.api.action.Option;
+import org.apache.karaf.shell.api.action.lifecycle.Reference;
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+import org.apache.karaf.shell.support.table.ShellTable;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.startlevel.FrameworkStartLevel;
+
+@Command(scope = "bundle", name = "list", description = "Lists all installed bundles.")
+@Service
+public class List extends BundlesCommand {
+
+    @Option(name = "-l", aliases = {}, description = "Show the locations", required = false, multiValued = false)
+    boolean showLocation;
+
+    @Option(name = "-s", description = "Shows the symbolic name", required = false, multiValued = false)
+    boolean showSymbolic;
+
+    @Option(name = "-u", description = "Shows the update locations", required = false, multiValued = false)
+    boolean showUpdate;
+
+    @Option(name = "-t", valueToShowInHelp = "", description = "Specifies the bundle threshold; bundles with a start-level less than this value will not get printed out.", required = false, multiValued = false)
+    int bundleLevelThreshold = -1;
+
+    @Option(name = "--no-format", description = "Disable table rendered output", required = false, multiValued = false)
+    boolean noFormat;
+
+    @Reference
+    BundleContext bundleContext;
+
+    @Reference
+    BundleService bundleService;
+
+    @Override
+    protected void executeOnBundle(Bundle bundle) throws Exception {
+    }
+
+    @Override
+    protected Object doExecute(java.util.List<Bundle> bundles) throws Exception {
+        determineBundleLevelThreshold();
+        
+        // Display active start level.
+        FrameworkStartLevel fsl = this.bundleContext.getBundle(0).adapt(FrameworkStartLevel.class);
+        if (fsl != null) {
+            System.out.println("START LEVEL " + fsl.getStartLevel() + " , List Threshold: " + bundleLevelThreshold);
+        }
+
+        ShellTable table = new ShellTable();
+        table.column("ID").alignRight();
+        table.column("State");
+        table.column("Lvl").alignRight();
+        table.column("Version");
+        table.column(getNameHeader());
+        
+        for (Bundle bundle : bundles) {
+            BundleInfo info = this.bundleService.getInfo(bundle);
+            if (info.getStartLevel() >= bundleLevelThreshold) {
+                String name = getNameToShow(info) + printFragments(info) + printHosts(info);
+                String version = info.getVersion();
+                table.addRow().addContent(info.getBundleId(), getStateString(info.getState()), 
+                        info.getStartLevel(), version, name);
+            }
+        }
+        table.print(System.out, !noFormat);
+        return null;
+    }
+
+    private String getNameHeader() {
+        String msg = "Name";
+        if (showLocation) {
+            msg = "Location";
+        } else if (showSymbolic) {
+            msg = "Symbolic name";
+        } else if (showUpdate) {
+            msg = "Update location";
+        }
+        return msg;
+    }
+
+    private void determineBundleLevelThreshold() {
+        if (bundleLevelThreshold < 0) {
+            bundleLevelThreshold = bundleService.getSystemBundleThreshold();
+        }
+    }
+
+    private String printHosts(BundleInfo info) {
+        if (info.getFragmentHosts().size() <= 0) {
+            return "";
+        }
+        StringBuilder builder = new StringBuilder();
+        builder.append(", Hosts: ");
+        boolean first = true;
+        for (Bundle host : info.getFragmentHosts()) {
+            builder.append((first ? "" : ", ") + host.getBundleId());
+            first = false;
+        }
+        return builder.toString();
+    }
+
+    private String printFragments(BundleInfo info) {
+        if (info.getFragments().size() <= 0) {
+            return "";
+        }
+        StringBuilder builder = new StringBuilder();
+        builder.append(", Fragments: ");
+        boolean first = true;
+        for (Bundle host : info.getFragments()) {
+            builder.append((first ? "" : ", ") + host.getBundleId());
+            first = false;
+        }
+        return builder.toString();
+    }
+
+    private String getStateString(BundleState state) {
+        return (state == null) ? "" : state.toString();
+    }
+
+    /**
+     * Overwrite the default value is the user specifically requested to display
+     * one or the other.
+     * 
+     * @param info
+     * @return
+     */
+    private String getNameToShow(BundleInfo info) {
+        if (showLocation) {
+            return info.getUpdateLocation();
+        } else if (showSymbolic) {
+            return info.getSymbolicName() == null ? "<no symbolic name>" : info.getSymbolicName();
+        } else if (showUpdate) {
+            return info.getUpdateLocation();
+        } else {
+            String name = (info.getName() == null) ? info.getSymbolicName() : info.getName();
+            return (name == null) ? info.getUpdateLocation() : name;
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/ca651c8e/bundle/core/src/main/java/org/apache/karaf/bundle/command/ListBundleServices.java
----------------------------------------------------------------------
diff --git a/bundle/core/src/main/java/org/apache/karaf/bundle/command/ListBundleServices.java b/bundle/core/src/main/java/org/apache/karaf/bundle/command/ListBundleServices.java
deleted file mode 100644
index 28f8264..0000000
--- a/bundle/core/src/main/java/org/apache/karaf/bundle/command/ListBundleServices.java
+++ /dev/null
@@ -1,116 +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.bundle.command;
-
-import java.util.Arrays;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.Option;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.apache.karaf.shell.support.ShellUtil;
-import org.osgi.framework.Bundle;
-import org.osgi.framework.Constants;
-import org.osgi.framework.ServiceReference;
-
-@Command(scope = "bundle", name = "services", description = "Lists OSGi services per Bundle")
-@Service
-public class ListBundleServices extends BundlesCommand {
-
-    @Option(name = "-a", aliases = {}, description = "Shows all services. (By default Karaf commands are hidden)", required = false, multiValued = false)
-    boolean showAll;
-
-    @Option(name = "-u", aliases = {}, description = "Shows the services each bundle uses. (By default the provided services are shown)", required = false, multiValued = false)
-    boolean inUse;
-    
-    @Option(name = "-p", aliases = {}, description = "Shows the properties of the services", required = false, multiValued = false)
-    boolean showProperties = false;
-
-    Set<String> hidden = new HashSet<String>(Arrays.asList(new String[] {
-        "org.apache.felix.service.command.Function",
-        "org.apache.karaf.shell.console.Completer"
-    }));
-    
-    public ListBundleServices() {
-        super(true);
-    }
-    
-    @Override
-    protected void doExecute(List<Bundle> bundles) throws Exception {
-        for (Bundle bundle : bundles) {
-            ServiceReference<?>[] refs = (inUse) ? bundle.getServicesInUse() : bundle.getRegisteredServices();
-            printServices(bundle, refs, showProperties);
-        }
-    }
-    
-    private void printServices(Bundle bundle, ServiceReference<?>[] refs, boolean showProperties) {
-        boolean headerPrinted = false;
-        boolean needSeparator = false;
-        
-        if (refs == null) {
-            return;
-        }
-
-        for (ServiceReference<?> serviceRef : refs) {
-            String[] objectClass = (String[]) serviceRef.getProperty(Constants.OBJECTCLASS);
-
-            boolean print = showAll || !isCommandOrCompleter(objectClass);
-
-            // Print header if we have not already done so.
-            if (!headerPrinted) {
-                headerPrinted = true;
-                System.out.println("");
-                String title = ShellUtil.getBundleName(bundle) + ((inUse) ? " uses:" : " provides:");
-                System.out.println(title);
-                System.out.println(ShellUtil.getUnderlineString(title));
-            }
-
-            if (print) {
-                // Print service separator if necessary.
-                if (needSeparator && showProperties) {
-                    System.out.println("----");
-                }
-
-                if (showProperties) {
-                    printProperties(serviceRef);
-                } else {
-                    System.out.println(ShellUtil.getValueString(objectClass));
-                }
-
-                needSeparator = true;
-            }
-        }
-    }
-
-    private boolean isCommandOrCompleter(String[] objectClasses) {
-        for (String objectClass : objectClasses) {
-            if (hidden.contains(objectClass)) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    private void printProperties(ServiceReference<?> serviceRef) {
-        for (String key : serviceRef.getPropertyKeys()) {
-            System.out.println(key + " = " + ShellUtil.getValueString(serviceRef.getProperty(key)));
-        }
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/ca651c8e/bundle/core/src/main/java/org/apache/karaf/bundle/command/ListBundles.java
----------------------------------------------------------------------
diff --git a/bundle/core/src/main/java/org/apache/karaf/bundle/command/ListBundles.java b/bundle/core/src/main/java/org/apache/karaf/bundle/command/ListBundles.java
deleted file mode 100644
index 107e578..0000000
--- a/bundle/core/src/main/java/org/apache/karaf/bundle/command/ListBundles.java
+++ /dev/null
@@ -1,176 +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.bundle.command;
-
-import org.apache.karaf.bundle.core.BundleInfo;
-import org.apache.karaf.bundle.core.BundleService;
-import org.apache.karaf.bundle.core.BundleState;
-import org.apache.karaf.shell.api.action.Action;
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.Option;
-import org.apache.karaf.shell.api.action.lifecycle.Reference;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.apache.karaf.shell.support.table.ShellTable;
-import org.osgi.framework.Bundle;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.startlevel.FrameworkStartLevel;
-
-@Command(scope = "bundle", name = "list", description = "Lists all installed bundles.")
-@Service
-public class ListBundles implements Action {
-
-    @Option(name = "-l", aliases = {}, description = "Show the locations", required = false, multiValued = false)
-    boolean showLoc;
-
-    @Option(name = "-s", description = "Shows the symbolic name", required = false, multiValued = false)
-    boolean showSymbolic;
-
-    @Option(name = "-u", description = "Shows the update locations", required = false, multiValued = false)
-    boolean showUpdate;
-
-    @Option(name = "-t", valueToShowInHelp = "", description = "Specifies the bundle threshold; bundles with a start-level less than this value will not get printed out.", required = false, multiValued = false)
-    int bundleLevelThreshold = -1;
-
-    @Option(name = "--no-format", description = "Disable table rendered output", required = false, multiValued = false)
-    boolean noFormat;
-
-    @Reference
-    BundleContext bundleContext;
-
-    @Reference
-    private BundleService bundleService;
-
-    public void setBundleService(BundleService bundleService) {
-        this.bundleService = bundleService;
-    }
-
-    @Override
-    public Object execute() throws Exception {
-        Bundle[] bundles = bundleContext.getBundles();
-        if (bundles == null) {
-            System.out.println("There are no installed bundles.");
-            return null;
-        }
-
-        determineBundleLevelThreshold();
-        
-        // Display active start level.
-        FrameworkStartLevel fsl = bundleContext.getBundle(0).adapt(FrameworkStartLevel.class);
-        if (fsl != null) {
-            System.out.println("START LEVEL " + fsl.getStartLevel() + " , List Threshold: " + bundleLevelThreshold);
-        }
-
-        ShellTable table = new ShellTable();
-        table.column("ID").alignRight();
-        table.column("State");
-        table.column("Lvl").alignRight();
-        table.column("Version");
-        table.column(getNameHeader());
-        
-        for (int i = 0; i < bundles.length; i++) {
-            Bundle bundle = bundles[i];
-            BundleInfo info = this.bundleService.getInfo(bundle);
-            if (info.getStartLevel() >= bundleLevelThreshold) {
-                String name = getNameToShow(info) + printFragments(info) + printHosts(info);
-                String version = info.getVersion();
-                table.addRow().addContent(info.getBundleId(), getStateString(info.getState()), 
-                        info.getStartLevel(), version, name);
-            }
-        }
-        table.print(System.out, !noFormat);
-
-        return null;
-    }
-
-    private String getNameHeader() {
-        String msg = "Name";
-        if (showLoc) {
-            msg = "Location";
-        } else if (showSymbolic) {
-            msg = "Symbolic name";
-        } else if (showUpdate) {
-            msg = "Update location";
-        }
-        return msg;
-    }
-
-    private void determineBundleLevelThreshold() {
-        final String sbslProp = bundleContext.getProperty("karaf.systemBundlesStartLevel");
-        if (sbslProp != null) {
-            try {
-                if (bundleLevelThreshold < 0) {
-                    bundleLevelThreshold = Integer.valueOf(sbslProp);
-                }
-            } catch (Exception ignore) {
-                // ignore
-            }
-        }
-    }
-
-    private String printHosts(BundleInfo info) {
-        if (info.getFragmentHosts().size() <= 0) {
-            return "";
-        }
-        StringBuilder builder = new StringBuilder();
-        builder.append(", Hosts: ");
-        boolean first = true;
-        for (Bundle host : info.getFragmentHosts()) {
-            builder.append((first ? "" : ", ") + host.getBundleId());
-            first = false;
-        }
-        return builder.toString();
-    }
-
-    private String printFragments(BundleInfo info) {
-        if (info.getFragments().size() <= 0) {
-            return "";
-        }
-        StringBuilder builder = new StringBuilder();
-        builder.append(", Fragments: ");
-        boolean first = true;
-        for (Bundle host : info.getFragments()) {
-            builder.append((first ? "" : ", ") + host.getBundleId());
-            first = false;
-        }
-        return builder.toString();
-    }
-
-    private String getStateString(BundleState state) {
-        return (state == null) ? "" : state.toString();
-    }
-
-    /**
-     * Overwrite the default value is the user specifically requested to display
-     * one or the other.
-     * 
-     * @param info
-     * @return
-     */
-    private String getNameToShow(BundleInfo info) {
-        if (showLoc) {
-            return info.getUpdateLocation();
-        } else if (showSymbolic) {
-            return info.getSymbolicName() == null ? "<no symbolic name>" : info.getSymbolicName();
-        } else if (showUpdate) {
-            return info.getUpdateLocation();
-        } else {
-            String name = (info.getName() == null) ? info.getSymbolicName() : info.getName();
-            return (name == null) ? info.getUpdateLocation() : name;
-        }
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/ca651c8e/bundle/core/src/main/java/org/apache/karaf/bundle/command/Refresh.java
----------------------------------------------------------------------
diff --git a/bundle/core/src/main/java/org/apache/karaf/bundle/command/Refresh.java b/bundle/core/src/main/java/org/apache/karaf/bundle/command/Refresh.java
index 53adaeb..b9b31a6 100644
--- a/bundle/core/src/main/java/org/apache/karaf/bundle/command/Refresh.java
+++ b/bundle/core/src/main/java/org/apache/karaf/bundle/command/Refresh.java
@@ -25,15 +25,16 @@ import org.osgi.framework.wiring.FrameworkWiring;
 
 @Command(scope = "bundle", name = "refresh", description = "Refresh bundles.")
 @Service
-public class Refresh extends BundlesCommandWithConfirmation {
+public class Refresh extends BundlesCommand {
     
     public Refresh() {
-        this.defaultAllBundles = false;
+        defaultAllBundles = false;
     }
 
-    protected void doExecute(List<Bundle> bundles) throws Exception {
+    protected Object doExecute(List<Bundle> bundles) throws Exception {
         FrameworkWiring wiring = bundleContext.getBundle(0).adapt(FrameworkWiring.class);
         wiring.refreshBundles(bundles == null || bundles.isEmpty() ? null : bundles);
+        return null;
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/karaf/blob/ca651c8e/bundle/core/src/main/java/org/apache/karaf/bundle/command/Requirements.java
----------------------------------------------------------------------
diff --git a/bundle/core/src/main/java/org/apache/karaf/bundle/command/Requirements.java b/bundle/core/src/main/java/org/apache/karaf/bundle/command/Requirements.java
index c87d4d4..88d5057 100644
--- a/bundle/core/src/main/java/org/apache/karaf/bundle/command/Requirements.java
+++ b/bundle/core/src/main/java/org/apache/karaf/bundle/command/Requirements.java
@@ -45,13 +45,13 @@ public class Requirements extends BundlesCommand {
 
     @Option(name = "--namespace")
     String namespace = "*";
-    
-    public Requirements() {
-        super(true);
+
+    @Override
+    protected void executeOnBundle(Bundle bundle) throws Exception {
     }
 
     @Override
-    protected void doExecute(List<Bundle> bundles) throws Exception {
+    protected Object doExecute(List<Bundle> bundles) throws Exception {
         boolean separatorNeeded = false;
         Pattern ns = Pattern.compile(namespace.replaceAll("\\.", "\\\\.").replaceAll("\\*", ".*"));
         for (Bundle b : bundles) {
@@ -84,6 +84,7 @@ public class Requirements extends BundlesCommand {
 
             separatorNeeded = true;
         }
+        return null;
     }
 
     private static boolean printMatchingRequirements(BundleWiring wiring, Pattern namespace) {

http://git-wip-us.apache.org/repos/asf/karaf/blob/ca651c8e/bundle/core/src/main/java/org/apache/karaf/bundle/command/Resolve.java
----------------------------------------------------------------------
diff --git a/bundle/core/src/main/java/org/apache/karaf/bundle/command/Resolve.java b/bundle/core/src/main/java/org/apache/karaf/bundle/command/Resolve.java
index 720f118..8df5c34 100644
--- a/bundle/core/src/main/java/org/apache/karaf/bundle/command/Resolve.java
+++ b/bundle/core/src/main/java/org/apache/karaf/bundle/command/Resolve.java
@@ -27,13 +27,14 @@ import org.osgi.framework.wiring.FrameworkWiring;
 @Service
 public class Resolve extends BundlesCommand {
 
-    public Resolve() {
-        super(true);
-    }
-
-    protected void doExecute(List<Bundle> bundles) throws Exception {
+    protected Object doExecute(List<Bundle> bundles) throws Exception {
         FrameworkWiring wiring = bundleContext.getBundle(0).adapt(FrameworkWiring.class);
         wiring.resolveBundles(bundles == null || bundles.isEmpty() ? null : bundles);
+        return null;
+    }
+
+    @Override
+    protected void executeOnBundle(Bundle bundle) throws Exception {
     }
 
 }

http://git-wip-us.apache.org/repos/asf/karaf/blob/ca651c8e/bundle/core/src/main/java/org/apache/karaf/bundle/command/Restart.java
----------------------------------------------------------------------
diff --git a/bundle/core/src/main/java/org/apache/karaf/bundle/command/Restart.java b/bundle/core/src/main/java/org/apache/karaf/bundle/command/Restart.java
index 95d5dfe..fd4c3d7 100644
--- a/bundle/core/src/main/java/org/apache/karaf/bundle/command/Restart.java
+++ b/bundle/core/src/main/java/org/apache/karaf/bundle/command/Restart.java
@@ -26,33 +26,35 @@ import org.osgi.framework.Bundle;
 
 @Command(scope = "bundle", name = "restart", description = "Restarts bundles.")
 @Service
-public class Restart extends BundlesCommandWithConfirmation {
+public class Restart extends BundlesCommand {
     
     public Restart() {
+        defaultAllBundles = false;
         errorMessage = "Error restarting bundle";
     }
 
-    protected void doExecute(List<Bundle> bundles) throws Exception {
+    protected Object doExecute(List<Bundle> bundles) throws Exception {
         if (bundles.isEmpty()) {
             System.err.println("No bundles specified.");
-            return;
+            return null;
         }
         List<Exception> exceptions = new ArrayList<Exception>();
         for (Bundle bundle : bundles) {
             try {
-                bundle.stop();
+                bundle.stop(Bundle.STOP_TRANSIENT);
             } catch (Exception e) {
                 exceptions.add(new Exception("Unable to stop bundle " + bundle.getBundleId() + ": " + e.getMessage(), e));
             }
         }
         for (Bundle bundle : bundles) {
             try {
-                bundle.start();
+                bundle.start(Bundle.START_TRANSIENT);
             } catch (Exception e) {
                 exceptions.add(new Exception("Unable to start bundle " + bundle.getBundleId() + ": " + e.getMessage(), e));
             }
         }
         MultiException.throwIf("Error restarting bundles", exceptions);
+        return null;
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/karaf/blob/ca651c8e/bundle/core/src/main/java/org/apache/karaf/bundle/command/Services.java
----------------------------------------------------------------------
diff --git a/bundle/core/src/main/java/org/apache/karaf/bundle/command/Services.java b/bundle/core/src/main/java/org/apache/karaf/bundle/command/Services.java
new file mode 100644
index 0000000..5b2080d
--- /dev/null
+++ b/bundle/core/src/main/java/org/apache/karaf/bundle/command/Services.java
@@ -0,0 +1,110 @@
+/*
+ * 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.bundle.command;
+
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.apache.karaf.shell.api.action.Command;
+import org.apache.karaf.shell.api.action.Option;
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+import org.apache.karaf.shell.support.ShellUtil;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.Constants;
+import org.osgi.framework.ServiceReference;
+
+@Command(scope = "bundle", name = "services", description = "Lists OSGi services per Bundle")
+@Service
+public class Services extends BundlesCommand {
+
+    @Option(name = "-a", aliases = {}, description = "Shows all services. (Karaf commands and completers are hidden by default)", required = false, multiValued = false)
+    boolean showAll;
+
+    @Option(name = "-u", aliases = {}, description = "Shows the services each bundle uses. (By default the provided services are shown)", required = false, multiValued = false)
+    boolean inUse;
+    
+    @Option(name = "-p", aliases = {}, description = "Shows the properties of the services", required = false, multiValued = false)
+    boolean showProperties = false;
+
+    Set<String> hidden = new HashSet<String>(Arrays.asList(new String[] {
+        "org.apache.felix.service.command.Function",
+        "org.apache.karaf.shell.console.Completer"
+    }));
+
+    @Override
+    protected void executeOnBundle(Bundle bundle) throws Exception {
+        ServiceReference<?>[] refs = (inUse) ? bundle.getServicesInUse() : bundle.getRegisteredServices();
+        printServices(bundle, refs, showProperties);
+    }
+    
+    private void printServices(Bundle bundle, ServiceReference<?>[] refs, boolean showProperties) {
+        boolean headerPrinted = false;
+        boolean needSeparator = false;
+        
+        if (refs == null) {
+            return;
+        }
+
+        for (ServiceReference<?> serviceRef : refs) {
+            String[] objectClass = (String[]) serviceRef.getProperty(Constants.OBJECTCLASS);
+
+            boolean print = showAll || !isCommandOrCompleter(objectClass);
+
+            // Print header if we have not already done so.
+            if (!headerPrinted) {
+                headerPrinted = true;
+                System.out.println("");
+                String title = ShellUtil.getBundleName(bundle) + ((inUse) ? " uses:" : " provides:");
+                System.out.println(title);
+                System.out.println(ShellUtil.getUnderlineString(title));
+            }
+
+            if (print) {
+                // Print service separator if necessary.
+                if (needSeparator && showProperties) {
+                    System.out.println("----");
+                }
+
+                if (showProperties) {
+                    printProperties(serviceRef);
+                } else {
+                    System.out.println(ShellUtil.getValueString(objectClass));
+                }
+
+                needSeparator = true;
+            }
+        }
+    }
+
+    private boolean isCommandOrCompleter(String[] objectClasses) {
+        for (String objectClass : objectClasses) {
+            if (hidden.contains(objectClass)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    private void printProperties(ServiceReference<?> serviceRef) {
+        for (String key : serviceRef.getPropertyKeys()) {
+            System.out.println(key + " = " + ShellUtil.getValueString(serviceRef.getProperty(key)));
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/ca651c8e/bundle/core/src/main/java/org/apache/karaf/bundle/command/ShowBundleTree.java
----------------------------------------------------------------------
diff --git a/bundle/core/src/main/java/org/apache/karaf/bundle/command/ShowBundleTree.java b/bundle/core/src/main/java/org/apache/karaf/bundle/command/ShowBundleTree.java
index f6f3d48..f1adf20 100644
--- a/bundle/core/src/main/java/org/apache/karaf/bundle/command/ShowBundleTree.java
+++ b/bundle/core/src/main/java/org/apache/karaf/bundle/command/ShowBundleTree.java
@@ -59,12 +59,8 @@ public class ShowBundleTree extends BundleCommand {
 
     private Tree<Bundle> tree;
 
-    public ShowBundleTree() {
-        super(false);
-    }
-
     @Override
-    protected void doExecute(Bundle bundle) throws Exception {
+    protected Object doExecute(Bundle bundle) throws Exception {
         long start = System.currentTimeMillis();
         // let's do the real work here
         printHeader(bundle);
@@ -74,6 +70,7 @@ public class ShowBundleTree extends BundleCommand {
         printDuplicatePackages(tree);
         LOGGER.debug(format("Dependency tree calculated in %d ms",
                             System.currentTimeMillis() - start));
+        return null;
     }
     
     /**

http://git-wip-us.apache.org/repos/asf/karaf/blob/ca651c8e/bundle/core/src/main/java/org/apache/karaf/bundle/command/Start.java
----------------------------------------------------------------------
diff --git a/bundle/core/src/main/java/org/apache/karaf/bundle/command/Start.java b/bundle/core/src/main/java/org/apache/karaf/bundle/command/Start.java
index 48e90fa..9d5180d 100644
--- a/bundle/core/src/main/java/org/apache/karaf/bundle/command/Start.java
+++ b/bundle/core/src/main/java/org/apache/karaf/bundle/command/Start.java
@@ -17,16 +17,25 @@
 package org.apache.karaf.bundle.command;
 
 import org.apache.karaf.shell.api.action.Command;
+import org.apache.karaf.shell.api.action.Option;
 import org.apache.karaf.shell.api.action.lifecycle.Service;
 import org.osgi.framework.Bundle;
 
 @Command(scope = "bundle", name = "start", description = "Starts bundles.")
 @Service
-public class Start extends BundlesCommandWithConfirmation {
+public class Start extends BundlesCommand {
+
+    @Option(name = "-t", aliases={"--transient"}, description="Keep the bundle as auto-start", required = false, multiValued = false)
+    boolean transientStart;
+
+    public Start() {
+        defaultAllBundles = false;
+        errorMessage = "Error starting bundle";
+    }
 
     @Override
     protected void executeOnBundle(Bundle bundle) throws Exception {
-        bundle.start();
+        bundle.start(transientStart ? Bundle.START_TRANSIENT : 0);
     }
 
 }

http://git-wip-us.apache.org/repos/asf/karaf/blob/ca651c8e/bundle/core/src/main/java/org/apache/karaf/bundle/command/StartLevel.java
----------------------------------------------------------------------
diff --git a/bundle/core/src/main/java/org/apache/karaf/bundle/command/StartLevel.java b/bundle/core/src/main/java/org/apache/karaf/bundle/command/StartLevel.java
index 30bec0f..060f005 100644
--- a/bundle/core/src/main/java/org/apache/karaf/bundle/command/StartLevel.java
+++ b/bundle/core/src/main/java/org/apache/karaf/bundle/command/StartLevel.java
@@ -16,8 +16,11 @@
  */
 package org.apache.karaf.bundle.command;
 
+import org.apache.karaf.bundle.core.BundleService;
+import org.apache.karaf.jaas.modules.JaasHelper;
 import org.apache.karaf.shell.api.action.Argument;
 import org.apache.karaf.shell.api.action.Command;
+import org.apache.karaf.shell.api.action.Option;
 import org.apache.karaf.shell.api.console.Session;
 import org.apache.karaf.shell.api.action.lifecycle.Reference;
 import org.apache.karaf.shell.api.action.lifecycle.Service;
@@ -26,39 +29,34 @@ import org.osgi.framework.startlevel.BundleStartLevel;
 
 @Command(scope = "bundle", name = "start-level", description = "Gets or sets the start level of a bundle.")
 @Service
-public class StartLevel extends BundleCommandWithConfirmation {
+public class StartLevel extends BundleCommand {
 
     @Argument(index = 1, name = "startLevel", description = "The bundle's new start level", required = false, multiValued = false)
     Integer level;
 
     @Reference
+    BundleService bundleService;
+
+    @Reference
     Session session;
 
-    protected void doExecute(Bundle bundle) throws Exception {
+    protected Object doExecute(Bundle bundle) throws Exception {
         // Get package instance service.
         BundleStartLevel bsl = bundle.adapt(BundleStartLevel.class);
-        if (bsl == null) {
-            System.out.println("StartLevel service is unavailable.");
-            return;
-        }
         if (level == null) {
             System.out.println("Level " + bsl.getStartLevel());
         }
-        else if ((level < 50) && (bsl.getStartLevel() > 50) && !force){
-            for (;;) {
-                String msg = "You are about to designate bundle as a system bundle.  Do you wish to continue (yes/no): ";
-                String str = session.readLine(msg, null);
-                if ("yes".equalsIgnoreCase(str)) {
-                    bsl.setStartLevel(level);
-                    break;
-                } else if ("no".equalsIgnoreCase(str)) {
-                    break;
+        else {
+            int sbsl = bundleService.getSystemBundleThreshold();
+            if ((level < sbsl) && (bsl.getStartLevel() >= sbsl)) {
+                if (!JaasHelper.currentUserHasRole(BundleService.SYSTEM_BUNDLES_ROLE)) {
+                    throw new IllegalArgumentException("Insufficient priviledges");
                 }
-            }
 
-        } else {
+            }
             bsl.setStartLevel(level);
         }
+        return null;
     }
 
 }

http://git-wip-us.apache.org/repos/asf/karaf/blob/ca651c8e/bundle/core/src/main/java/org/apache/karaf/bundle/command/Stop.java
----------------------------------------------------------------------
diff --git a/bundle/core/src/main/java/org/apache/karaf/bundle/command/Stop.java b/bundle/core/src/main/java/org/apache/karaf/bundle/command/Stop.java
index 0b0fed2..120310b 100644
--- a/bundle/core/src/main/java/org/apache/karaf/bundle/command/Stop.java
+++ b/bundle/core/src/main/java/org/apache/karaf/bundle/command/Stop.java
@@ -23,22 +23,19 @@ import org.osgi.framework.Bundle;
 
 @Command(scope = "bundle", name = "stop", description = "Stop bundles.")
 @Service
-public class Stop extends BundlesCommandWithConfirmation {
+public class Stop extends BundlesCommand {
     
 	@Option(name = "-t", aliases={"--transient"}, description="Keep the bundle as auto-start", required = false, multiValued = false)
 	boolean transientStop;
 	
     public Stop() {
-        this.errorMessage = "Unable to stop bundle";
+        defaultAllBundles = false;
+        errorMessage = "Error stopping bundle";
     }
 
     @Override
     protected void executeOnBundle(Bundle bundle) throws Exception {
-    	if (transientStop) {
-    		bundle.stop(Bundle.STOP_TRANSIENT);
-    	} else {
-    		bundle.stop();
-    	}
+        bundle.stop(transientStop ? Bundle.STOP_TRANSIENT : 0);
     }
 
 }

http://git-wip-us.apache.org/repos/asf/karaf/blob/ca651c8e/bundle/core/src/main/java/org/apache/karaf/bundle/command/Uninstall.java
----------------------------------------------------------------------
diff --git a/bundle/core/src/main/java/org/apache/karaf/bundle/command/Uninstall.java b/bundle/core/src/main/java/org/apache/karaf/bundle/command/Uninstall.java
index 67b5b14..7829e86 100644
--- a/bundle/core/src/main/java/org/apache/karaf/bundle/command/Uninstall.java
+++ b/bundle/core/src/main/java/org/apache/karaf/bundle/command/Uninstall.java
@@ -22,10 +22,11 @@ import org.osgi.framework.Bundle;
 
 @Command(scope = "bundle", name = "uninstall", description = "Uninstall bundles.")
 @Service
-public class Uninstall extends BundlesCommandWithConfirmation {
+public class Uninstall extends BundlesCommand {
     
     public Uninstall() {
-        this.errorMessage = "Unable to uninstall bundle";
+        defaultAllBundles = false;
+        errorMessage = "Error uninstalling bundle";
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/karaf/blob/ca651c8e/bundle/core/src/main/java/org/apache/karaf/bundle/command/Update.java
----------------------------------------------------------------------
diff --git a/bundle/core/src/main/java/org/apache/karaf/bundle/command/Update.java b/bundle/core/src/main/java/org/apache/karaf/bundle/command/Update.java
index 71ae74d..b918bca 100644
--- a/bundle/core/src/main/java/org/apache/karaf/bundle/command/Update.java
+++ b/bundle/core/src/main/java/org/apache/karaf/bundle/command/Update.java
@@ -26,23 +26,22 @@ import org.osgi.framework.Bundle;
 
 @Command(scope = "bundle", name = "update", description = "Update bundle.")
 @Service
-public class Update extends BundleCommandWithConfirmation {
+public class Update extends BundleCommand {
 
     @Argument(index = 1, name = "location", description = "The bundles update location", required = false, multiValued = false)
     String location;
 
-    protected void doExecute(Bundle bundle) throws Exception {
-        InputStream is = null;
+    protected Object doExecute(Bundle bundle) throws Exception {
         if (location != null) {
-            try {
-                is = new URL(location).openStream();
+            try (
+                InputStream is = new URL(location).openStream()
+            ) {
                 bundle.update(is);
-            } finally {
-                is.close();
             }
         } else {
             bundle.update();
         }
+        return null;
     }
 
 }

http://git-wip-us.apache.org/repos/asf/karaf/blob/ca651c8e/bundle/core/src/main/java/org/apache/karaf/bundle/core/BundleService.java
----------------------------------------------------------------------
diff --git a/bundle/core/src/main/java/org/apache/karaf/bundle/core/BundleService.java b/bundle/core/src/main/java/org/apache/karaf/bundle/core/BundleService.java
index 0ebf2ad..1728ac0 100644
--- a/bundle/core/src/main/java/org/apache/karaf/bundle/core/BundleService.java
+++ b/bundle/core/src/main/java/org/apache/karaf/bundle/core/BundleService.java
@@ -23,18 +23,22 @@ import org.osgi.framework.Bundle;
 import org.osgi.framework.wiring.BundleRequirement;
 
 public interface BundleService {
+
+    String SYSTEM_BUNDLES_ROLE = "systembundles";
     
     BundleInfo getInfo(Bundle bundle);
 
     List<Bundle> selectBundles(List<String> ids, boolean defaultAllBundles);
-    
-    List<Bundle> getBundlesByURL(String urlFilter);
 
-    Bundle getBundle(String id, boolean defaultAllBundles);
-    
+    List<Bundle> selectBundles(String context, List<String> ids, boolean defaultAllBundles);
+
+    Bundle getBundle(String id);
+
+    Bundle getBundle(String context, String id);
+
     String getDiag(Bundle bundle);
     
-    List<BundleRequirement> getUnsatisfiedRquirements(Bundle bundle, String namespace);
+    List<BundleRequirement> getUnsatisfiedRequirements(Bundle bundle, String namespace);
     
     Map<String, Bundle> getWiredBundles(Bundle bundle);
     
@@ -44,4 +48,6 @@ public interface BundleService {
 
     void disableDynamicImports(Bundle bundle);
 
+    int getSystemBundleThreshold();
+
 }

http://git-wip-us.apache.org/repos/asf/karaf/blob/ca651c8e/bundle/core/src/main/java/org/apache/karaf/bundle/core/internal/BundleSelectorImpl.java
----------------------------------------------------------------------
diff --git a/bundle/core/src/main/java/org/apache/karaf/bundle/core/internal/BundleSelectorImpl.java b/bundle/core/src/main/java/org/apache/karaf/bundle/core/internal/BundleSelectorImpl.java
index 5806f39..bd728a2 100644
--- a/bundle/core/src/main/java/org/apache/karaf/bundle/core/internal/BundleSelectorImpl.java
+++ b/bundle/core/src/main/java/org/apache/karaf/bundle/core/internal/BundleSelectorImpl.java
@@ -35,7 +35,7 @@ public class BundleSelectorImpl {
     }
     
     public List<Bundle> selectBundles(List<String> ids, boolean defaultAllBundles) {
-        List<Bundle> bundles = new ArrayList<Bundle>();
+        List<Bundle> bundles = new ArrayList<>();
         if (ids != null && !ids.isEmpty()) {
             for (String id : ids) {
                 if (id == null) {
@@ -49,7 +49,7 @@ public class BundleSelectorImpl {
         return bundles;
     }
     
-    public void addMatchingBundles(String id, List<Bundle> bundles) {
+    private void addMatchingBundles(String id, List<Bundle> bundles) {
         // id is a number
         Pattern pattern = Pattern.compile("^\\d+$");
         Matcher matcher = pattern.matcher(id);
@@ -76,8 +76,9 @@ public class BundleSelectorImpl {
             return;
         }
 
+        // bundles by name
         int index = id.indexOf('/');
-        List<Bundle> bundlesByName = null;
+        List<Bundle> bundlesByName;
         if (index != -1) {
             // user has provided name and version
             bundlesByName = getBundleByNameAndVersion(id.substring(0, index), id.substring(index + 1));
@@ -88,6 +89,12 @@ public class BundleSelectorImpl {
         for (Bundle bundleByName : bundlesByName) {
             addBundle(bundleByName, id, bundles);
         }
+
+        // bundles by location
+        List<Bundle> bundlesByLocation = getBundlesByLocation(id);
+        for (Bundle bundleByLocation : bundlesByLocation) {
+            addBundle(bundleByLocation, id, bundles);
+        }
     }
 
     private void addBundle(Bundle bundle, String id, List<Bundle> bundles) {
@@ -136,91 +143,62 @@ public class BundleSelectorImpl {
     private List<Bundle> getBundleByNameAndVersion(String name, String version) {
         Bundle[] bundles = bundleContext.getBundles();
 
-        ArrayList<Bundle> result = new ArrayList<Bundle>();
+        ArrayList<Bundle> result = new ArrayList<>();
 
         Pattern namePattern = Pattern.compile(name);
 
-        for (int i = 0; i < bundles.length; i++) {
+        for (Bundle bundle : bundles) {
 
-            String bundleSymbolicName = bundles[i].getSymbolicName();
+            String bundleSymbolicName = bundle.getSymbolicName();
             // skip bundles without Bundle-SymbolicName header
             if (bundleSymbolicName == null) {
                 continue;
             }
-            
+
             Matcher symbolicNameMatcher = namePattern.matcher(bundleSymbolicName);
-            
+
             Matcher nameMatcher = null;
-            String bundleName = (String) bundles[i].getHeaders().get(Constants.BUNDLE_NAME);
+            String bundleName = bundle.getHeaders().get(Constants.BUNDLE_NAME);
             if (bundleName != null) {
                 nameMatcher = namePattern.matcher(bundleName);
             }
 
             if (version != null) {
-                String bundleVersion = (String) bundles[i].getHeaders().get(Constants.BUNDLE_VERSION);
+                String bundleVersion = bundle.getHeaders().get(Constants.BUNDLE_VERSION);
                 if (bundleVersion != null) {
                     boolean nameMatch = (nameMatcher != null && nameMatcher.find()) || symbolicNameMatcher.find();
                     if (nameMatch) {
                         Pattern versionPattern = Pattern.compile(version);
-                        Matcher versionMatcher = versionPattern.matcher(bundleVersion);                    
+                        Matcher versionMatcher = versionPattern.matcher(bundleVersion);
                         if (versionMatcher.find()) {
-                            result.add(bundles[i]);
+                            result.add(bundle);
                         }
                     }
                 }
             } else {
                 boolean nameMatch = (nameMatcher != null && nameMatcher.find()) || symbolicNameMatcher.find();
                 if (nameMatch) {
-                    result.add(bundles[i]);
+                    result.add(bundle);
                 }
             }
         }
         return result;
     }
     
-    public List<Bundle> getBundlesByURL(String url) {
-        List<Bundle> bundleList = new ArrayList<Bundle>();
-        try {
-            Long id = Long.parseLong(url);
-            Bundle bundle = bundleContext.getBundle(id);
-            if (bundle != null) {
-                bundleList.add(bundle);
-            }
-        } catch (NumberFormatException e) {
-            for (int i = 0; i < bundleContext.getBundles().length; i++) {
-                Bundle bundle = bundleContext.getBundles()[i];
-                if (isMavenSnapshotUrl(bundle.getLocation()) && wildCardMatch(bundle.getLocation(), url)) {
-                    bundleList.add(bundle);
-                }
-            }
-        }
-        return bundleList;
-    }
+    private List<Bundle> getBundlesByLocation(String url) {
+        Bundle[] bundles = bundleContext.getBundles();
 
-    private boolean isMavenSnapshotUrl(String url) {
-        return url.startsWith("mvn:") && url.contains("SNAPSHOT");
-    }
+        ArrayList<Bundle> result = new ArrayList<>();
 
-    /**
-     * Matches text using a pattern containing wildcards.
-     * 
-     * @param text
-     * @param pattern
-     * @return
-     */
-    private boolean wildCardMatch(String text, String pattern) {
-        String[] cards = pattern.split("\\*");
-        for (String card : cards) {
-            int idx = text.indexOf(card);
-            // Card not detected in the text.
-            if (idx == -1) {
-                return false;
-            }
+        Pattern locationPattern = Pattern.compile(url);
 
-            // Move ahead, towards the right of the text.
-            text = text.substring(idx + card.length());
+        for (Bundle bundle : bundles) {
+            Matcher locationMatcher = locationPattern.matcher(bundle.getLocation());
+            if (locationMatcher.find()) {
+                result.add(bundle);
+            }
         }
-        return true;
+        return result;
     }
 
 }


[4/4] git commit: [KARAF-2948] Add su and sudo commands

Posted by gn...@apache.org.
[KARAF-2948] Add su and sudo commands


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

Branch: refs/heads/master
Commit: c10dde0cd6dec1bec7700c1762a26989944b125d
Parents: dde4a38
Author: Guillaume Nodet <gn...@gmail.com>
Authored: Mon Apr 28 10:46:51 2014 +0200
Committer: Guillaume Nodet <gn...@gmail.com>
Committed: Mon Apr 28 20:01:25 2014 +0200

----------------------------------------------------------------------
 .../apache/karaf/jaas/command/SuCommand.java    | 93 ++++++++++++++++++++
 .../apache/karaf/jaas/command/SudoCommand.java  | 92 +++++++++++++++++++
 2 files changed, 185 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/karaf/blob/c10dde0c/jaas/command/src/main/java/org/apache/karaf/jaas/command/SuCommand.java
----------------------------------------------------------------------
diff --git a/jaas/command/src/main/java/org/apache/karaf/jaas/command/SuCommand.java b/jaas/command/src/main/java/org/apache/karaf/jaas/command/SuCommand.java
new file mode 100644
index 0000000..9a1a265
--- /dev/null
+++ b/jaas/command/src/main/java/org/apache/karaf/jaas/command/SuCommand.java
@@ -0,0 +1,93 @@
+/*
+ * 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.jaas.command;
+
+import java.io.IOException;
+import java.security.PrivilegedExceptionAction;
+
+import javax.security.auth.Subject;
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.NameCallback;
+import javax.security.auth.callback.PasswordCallback;
+import javax.security.auth.callback.UnsupportedCallbackException;
+import javax.security.auth.login.LoginContext;
+
+import org.apache.karaf.jaas.modules.JaasHelper;
+import org.apache.karaf.shell.api.action.Action;
+import org.apache.karaf.shell.api.action.Argument;
+import org.apache.karaf.shell.api.action.Command;
+import org.apache.karaf.shell.api.action.Option;
+import org.apache.karaf.shell.api.action.lifecycle.Reference;
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+import org.apache.karaf.shell.api.console.Session;
+import org.apache.karaf.shell.support.ShellUtil;
+
+@Command(scope = "jaas", name = "su", description = "Substitute user identity")
+@Service
+public class SuCommand implements Action {
+
+    @Option(name = "--realm")
+    String realm = "karaf";
+
+    @Argument(description = "Name of the user to substitute")
+    String user = "karaf";
+
+    @Reference
+    Session session;
+
+    @Override
+    public Object execute() throws Exception {
+        Subject subject = new Subject();
+        LoginContext loginContext = new LoginContext(realm, subject, new CallbackHandler() {
+            public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
+                for (Callback callback : callbacks) {
+                    if (callback instanceof NameCallback) {
+                        ((NameCallback) callback).setName(user);
+                    } else if (callback instanceof PasswordCallback) {
+                        String password = SuCommand.this.session.readLine("Password: ", '*');
+                        ((PasswordCallback) callback).setPassword(password.toCharArray());
+                    } else {
+                        throw new UnsupportedCallbackException(callback);
+                    }
+                }
+            }
+        });
+        loginContext.login();
+
+        JaasHelper.doAs(subject, new PrivilegedExceptionAction<Object>() {
+            public Object run() throws InterruptedException {
+                final Session newSession = session.getFactory().create(
+                        System.in, System.out, System.err, SuCommand.this.session.getTerminal(), null, null);
+                Object oldIgnoreInterrupts = session.get(Session.IGNORE_INTERRUPTS);
+                try {
+                    session.put(Session.IGNORE_INTERRUPTS, Boolean.TRUE);
+                    String name = "Karaf local console user " + ShellUtil.getCurrentUserName();
+                    Thread thread = new Thread(newSession, name);
+                    thread.start();
+                    thread.join();
+                } finally {
+                    session.put(Session.IGNORE_INTERRUPTS, oldIgnoreInterrupts);
+                }
+                return null;
+            }
+        });
+
+        loginContext.logout();
+        return null;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/c10dde0c/jaas/command/src/main/java/org/apache/karaf/jaas/command/SudoCommand.java
----------------------------------------------------------------------
diff --git a/jaas/command/src/main/java/org/apache/karaf/jaas/command/SudoCommand.java b/jaas/command/src/main/java/org/apache/karaf/jaas/command/SudoCommand.java
new file mode 100644
index 0000000..ba027c6
--- /dev/null
+++ b/jaas/command/src/main/java/org/apache/karaf/jaas/command/SudoCommand.java
@@ -0,0 +1,92 @@
+/*
+ * 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.jaas.command;
+
+import java.io.IOException;
+import java.security.PrivilegedExceptionAction;
+import java.util.List;
+
+import javax.security.auth.Subject;
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.NameCallback;
+import javax.security.auth.callback.PasswordCallback;
+import javax.security.auth.callback.UnsupportedCallbackException;
+import javax.security.auth.login.LoginContext;
+
+import org.apache.karaf.jaas.modules.JaasHelper;
+import org.apache.karaf.shell.api.action.Action;
+import org.apache.karaf.shell.api.action.Argument;
+import org.apache.karaf.shell.api.action.Command;
+import org.apache.karaf.shell.api.action.Option;
+import org.apache.karaf.shell.api.action.lifecycle.Reference;
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+import org.apache.karaf.shell.api.console.Session;
+
+@Command(scope = "jaas", name = "sudo", description = "Execute a command as another user")
+@Service
+public class SudoCommand implements Action {
+
+    @Option(name = "--realm")
+    String realm = "karaf";
+
+    @Option(name = "--user")
+    String user = "karaf";
+
+    @Argument(multiValued = true)
+    List<String> command;
+
+    @Reference
+    Session session;
+
+    @Override
+    public Object execute() throws Exception {
+        Subject subject = new Subject();
+        LoginContext loginContext = new LoginContext(realm, subject, new CallbackHandler() {
+            public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
+                for (Callback callback : callbacks) {
+                    if (callback instanceof NameCallback) {
+                        ((NameCallback) callback).setName(user);
+                    } else if (callback instanceof PasswordCallback) {
+                        String password = SudoCommand.this.session.readLine("Password: ", '*');
+                        ((PasswordCallback) callback).setPassword(password.toCharArray());
+                    } else {
+                        throw new UnsupportedCallbackException(callback);
+                    }
+                }
+            }
+        });
+        loginContext.login();
+
+        final StringBuilder sb = new StringBuilder();
+        for (String s : command) {
+            if (sb.length() > 0) {
+                sb.append(" ");
+            }
+            sb.append(s);
+        }
+        JaasHelper.doAs(subject, new PrivilegedExceptionAction<Object>() {
+            @Override
+            public Object run() throws Exception {
+                return session.execute(sb);
+            }
+        });
+
+        loginContext.logout();
+        return null;
+    }
+
+}