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

[1/3] git commit: Fix utest on the Karaf shell console

Repository: karaf
Updated Branches:
  refs/heads/karaf-3.0.x d581dfc84 -> 9ddd8b7da


Fix utest on the Karaf shell console


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

Branch: refs/heads/karaf-3.0.x
Commit: 9ddd8b7da3da374ab49a9396c07d200557179ad0
Parents: 9ad9fd5
Author: Jean-Baptiste Onofré <jb...@apache.org>
Authored: Sat Sep 13 15:05:24 2014 +0200
Committer: Guillaume Nodet <gn...@gmail.com>
Committed: Mon Sep 15 08:52:37 2014 +0200

----------------------------------------------------------------------
 .../shell/security/impl/SecuredCommandProcessorImplTest.java      | 3 +++
 1 file changed, 3 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/karaf/blob/9ddd8b7d/shell/console/src/test/java/org/apache/karaf/shell/security/impl/SecuredCommandProcessorImplTest.java
----------------------------------------------------------------------
diff --git a/shell/console/src/test/java/org/apache/karaf/shell/security/impl/SecuredCommandProcessorImplTest.java b/shell/console/src/test/java/org/apache/karaf/shell/security/impl/SecuredCommandProcessorImplTest.java
index 0c66eb6..2e98ffa 100644
--- a/shell/console/src/test/java/org/apache/karaf/shell/security/impl/SecuredCommandProcessorImplTest.java
+++ b/shell/console/src/test/java/org/apache/karaf/shell/security/impl/SecuredCommandProcessorImplTest.java
@@ -62,6 +62,7 @@ public class SecuredCommandProcessorImplTest {
         }).anyTimes();
         EasyMock.expect(bc.getServiceReferences((String) EasyMock.anyObject(), (String) EasyMock.anyObject())).andReturn(null).anyTimes();
 
+
         // Capture the listeners
         final Map<String, ServiceListener> listeners = new HashMap<String, ServiceListener>();
 
@@ -94,6 +95,7 @@ public class SecuredCommandProcessorImplTest {
                 ServiceReference<?> cdRef = EasyMock.createMock(ServiceReference.class);
                 EasyMock.expect(cdRef.getProperty(CommandProcessor.COMMAND_SCOPE)).andReturn("foo");
                 EasyMock.expect(cdRef.getProperty(CommandProcessor.COMMAND_FUNCTION)).andReturn("bar");
+                EasyMock.expect(cdRef.getProperty("service.ranking")).andReturn("1");
                 EasyMock.replay(cdRef);
 
                 ServiceEvent event = new ServiceEvent(ServiceEvent.REGISTERED, cdRef);
@@ -105,6 +107,7 @@ public class SecuredCommandProcessorImplTest {
                 EasyMock.expect(cd2Ref.getProperty(CommandProcessor.COMMAND_SCOPE)).andReturn("xxx");
                 EasyMock.expect(cd2Ref.getProperty(CommandProcessor.COMMAND_FUNCTION)).andReturn(
                         new String[] {"aaa", "bbb"});
+                EasyMock.expect(cd2Ref.getProperty("service.ranking")).andReturn("2");
                 EasyMock.replay(cd2Ref);
 
                 ServiceEvent event2 = new ServiceEvent(ServiceEvent.REGISTERED, cd2Ref);


[3/3] git commit: Fix packaging problems with gogo as Gogo is deployed in its own bundle, but also partially embedded in shell/core. * Embed gogo in shell/core * Export the secured CommandProcessor directly

Posted by gn...@apache.org.
Fix packaging problems with gogo as Gogo is deployed in its own bundle, but also partially embedded in shell/core.
 * Embed gogo in shell/core
 * Export the secured CommandProcessor directly


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

Branch: refs/heads/karaf-3.0.x
Commit: 507b41d1956dc6f0282c2e1b123ae7f591c2c4cb
Parents: d581dfc
Author: Guillaume Nodet <gn...@gmail.com>
Authored: Sat Sep 13 13:05:15 2014 +0200
Committer: Guillaume Nodet <gn...@gmail.com>
Committed: Mon Sep 15 08:52:37 2014 +0200

----------------------------------------------------------------------
 .../filtered-resources/resources/bin/instance   |   2 +-
 .../resources/bin/instance.bat                  |   2 +-
 .../standard/src/main/feature/feature.xml       |   1 -
 .../apache/karaf/itests/KarafTestSupport.java   |   4 +-
 .../apache/karaf/jaas/modules/JaasHelper.java   |  10 +
 shell/console/pom.xml                           |  15 +-
 .../apache/karaf/shell/console/impl/Main.java   |   2 +-
 .../impl/jline/ConsoleFactoryService.java       |   2 +-
 .../shell/console/impl/jline/ConsoleImpl.java   |  37 +---
 .../console/impl/jline/LocalConsoleManager.java |  30 ++-
 .../security/impl/SecCommandProcessorImpl.java  |  42 ++++
 .../impl/SecuredCommandProcessorImpl.java       |  99 +++++-----
 .../OSGI-INF/blueprint/karaf-console.xml        |  11 +-
 .../shell/console/ExampleSubclassMain.java      |   2 +-
 .../console/impl/jline/ConsoleImplTest.java     | 195 -------------------
 .../impl/SecuredCommandProcessorImplTest.java   |   2 +-
 .../karaf/shell/ssh/ShellFactoryImpl.java       |  68 +++++--
 .../karaf/webconsole/gogo/GogoPlugin.java       |  12 +-
 18 files changed, 214 insertions(+), 322 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/karaf/blob/507b41d1/assemblies/features/framework/src/main/filtered-resources/resources/bin/instance
----------------------------------------------------------------------
diff --git a/assemblies/features/framework/src/main/filtered-resources/resources/bin/instance b/assemblies/features/framework/src/main/filtered-resources/resources/bin/instance
index e5e0215..2d19cca 100755
--- a/assemblies/features/framework/src/main/filtered-resources/resources/bin/instance
+++ b/assemblies/features/framework/src/main/filtered-resources/resources/bin/instance
@@ -331,7 +331,7 @@ init() {
 
 run() {
 
-    CLASSPATH="${KARAF_HOME}/system/org/apache/karaf/instance/org.apache.karaf.instance.command/${project.version}/org.apache.karaf.instance.command-${project.version}.jar:${KARAF_HOME}/system/org/apache/karaf/instance/org.apache.karaf.instance.core/${project.version}/org.apache.karaf.instance.core-${project.version}.jar:${KARAF_HOME}/system/org/apache/karaf/shell/org.apache.karaf.shell.console/${project.version}/org.apache.karaf.shell.console-${project.version}.jar:${KARAF_HOME}/system/org/apache/karaf/shell/org.apache.karaf.shell.table/${project.version}/org.apache.karaf.shell.table-${project.version}.jar:${KARAF_HOME}/system/org/apache/aries/blueprint/org.apache.aries.blueprint.api/${aries.blueprint.api.version}/org.apache.aries.blueprint.api-${aries.blueprint.api.version}.jar:${KARAF_HOME}/system/org/apache/aries/blueprint/org.apache.aries.blueprint.core/${aries.blueprint.core.version}/org.apache.aries.blueprint.core-${aries.blueprint.core.version}.jar:${KARAF_HOME}/system/org/a
 pache/aries/blueprint/org.apache.aries.blueprint.cm/${aries.blueprint.cm.version}/org.apache.aries.blueprint.cm-${aries.blueprint.cm.version}.jar:${KARAF_HOME}/system/org/ops4j/pax/logging/pax-logging-api/${pax.logging.version}/pax-logging-api-${pax.logging.version}.jar:${KARAF_HOME}/system/org/apache/felix/org.apache.felix.framework/${felix.framework.version}/org.apache.felix.framework-${felix.framework.version}.jar:${KARAF_HOME}/system/jline/jline/${jline.version}/jline-${jline.version}.jar:${KARAF_HOME}/system/org/apache/felix/org.apache.felix.gogo.runtime/${felix.gogo.version}/org.apache.felix.gogo.runtime-${felix.gogo.version}.jar:$CLASSPATH"
+    CLASSPATH="${KARAF_HOME}/system/org/apache/karaf/instance/org.apache.karaf.instance.command/${project.version}/org.apache.karaf.instance.command-${project.version}.jar:${KARAF_HOME}/system/org/apache/karaf/instance/org.apache.karaf.instance.core/${project.version}/org.apache.karaf.instance.core-${project.version}.jar:${KARAF_HOME}/system/org/apache/karaf/shell/org.apache.karaf.shell.console/${project.version}/org.apache.karaf.shell.console-${project.version}.jar:${KARAF_HOME}/system/org/apache/karaf/shell/org.apache.karaf.shell.table/${project.version}/org.apache.karaf.shell.table-${project.version}.jar:${KARAF_HOME}/system/org/apache/aries/blueprint/org.apache.aries.blueprint.api/${aries.blueprint.api.version}/org.apache.aries.blueprint.api-${aries.blueprint.api.version}.jar:${KARAF_HOME}/system/org/apache/aries/blueprint/org.apache.aries.blueprint.core/${aries.blueprint.core.version}/org.apache.aries.blueprint.core-${aries.blueprint.core.version}.jar:${KARAF_HOME}/system/org/a
 pache/aries/blueprint/org.apache.aries.blueprint.cm/${aries.blueprint.cm.version}/org.apache.aries.blueprint.cm-${aries.blueprint.cm.version}.jar:${KARAF_HOME}/system/org/ops4j/pax/logging/pax-logging-api/${pax.logging.version}/pax-logging-api-${pax.logging.version}.jar:${KARAF_HOME}/system/org/apache/felix/org.apache.felix.framework/${felix.framework.version}/org.apache.felix.framework-${felix.framework.version}.jar:${KARAF_HOME}/system/jline/jline/${jline.version}/jline-${jline.version}.jar:$CLASSPATH"
 
     if $cygwin; then
         KARAF_HOME=`cygpath --path --windows "$KARAF_HOME"`

http://git-wip-us.apache.org/repos/asf/karaf/blob/507b41d1/assemblies/features/framework/src/main/filtered-resources/resources/bin/instance.bat
----------------------------------------------------------------------
diff --git a/assemblies/features/framework/src/main/filtered-resources/resources/bin/instance.bat b/assemblies/features/framework/src/main/filtered-resources/resources/bin/instance.bat
index 52e9141..e502677 100644
--- a/assemblies/features/framework/src/main/filtered-resources/resources/bin/instance.bat
+++ b/assemblies/features/framework/src/main/filtered-resources/resources/bin/instance.bat
@@ -139,7 +139,7 @@ goto :EOF
 
 :CLASSPATH_END
 
-set CLASSPATH=%KARAF_HOME%\system\org\apache\karaf\instance\org.apache.karaf.instance.command\${project.version}\org.apache.karaf.instance.command-${project.version}.jar;%KARAF_HOME%\system\org\apache\karaf\instance\org.apache.karaf.instance.core\${project.version}\org.apache.karaf.instance.core-${project.version}.jar;%KARAF_HOME%\system\org\apache\karaf\shell\org.apache.karaf.shell.console\${project.version}\org.apache.karaf.shell.console-${project.version}.jar;%KARAF_HOME%\system\org\apache\karaf\shell\org.apache.karaf.shell.table\${project.version}\org.apache.karaf.shell.table-${project.version}.jar;%KARAF_HOME%\system\org\apache\aries\blueprint\org.apache.aries.blueprint.api\${aries.blueprint.api.version}\org.apache.aries.blueprint.api-${aries.blueprint.api.version}.jar;%KARAF_HOME%\system\org\apache\aries\blueprint\org.apache.aries.blueprint.core\${aries.blueprint.core.version}\org.apache.aries.blueprint.core-${aries.blueprint.core.version}.jar;%KARAF_HOME%\system\org\apache\ar
 ies\blueprint\org.apache.aries.blueprint.cm\${aries.blueprint.cm.version}\org.apache.aries.blueprint.cm-${aries.blueprint.cm.version}.jar;%KARAF_HOME%\system\org\ops4j\pax\logging\pax-logging-api\${pax.logging.version}\pax-logging-api-${pax.logging.version}.jar;%KARAF_HOME%\system\org\apache\felix\org.apache.felix.framework\${felix.framework.version}\org.apache.felix.framework-${felix.framework.version}.jar;%KARAF_HOME%\system\jline\jline\${jline.version}\jline-${jline.version}.jar;%KARAF_HOME%\system\org\apache\felix\org.apache.felix.gogo.runtime\${felix.gogo.version}\org.apache.felix.gogo.runtime-${felix.gogo.version}.jar;%CLASSPATH%
+set CLASSPATH=%KARAF_HOME%\system\org\apache\karaf\instance\org.apache.karaf.instance.command\${project.version}\org.apache.karaf.instance.command-${project.version}.jar;%KARAF_HOME%\system\org\apache\karaf\instance\org.apache.karaf.instance.core\${project.version}\org.apache.karaf.instance.core-${project.version}.jar;%KARAF_HOME%\system\org\apache\karaf\shell\org.apache.karaf.shell.console\${project.version}\org.apache.karaf.shell.console-${project.version}.jar;%KARAF_HOME%\system\org\apache\karaf\shell\org.apache.karaf.shell.table\${project.version}\org.apache.karaf.shell.table-${project.version}.jar;%KARAF_HOME%\system\org\apache\aries\blueprint\org.apache.aries.blueprint.api\${aries.blueprint.api.version}\org.apache.aries.blueprint.api-${aries.blueprint.api.version}.jar;%KARAF_HOME%\system\org\apache\aries\blueprint\org.apache.aries.blueprint.core\${aries.blueprint.core.version}\org.apache.aries.blueprint.core-${aries.blueprint.core.version}.jar;%KARAF_HOME%\system\org\apache\ar
 ies\blueprint\org.apache.aries.blueprint.cm\${aries.blueprint.cm.version}\org.apache.aries.blueprint.cm-${aries.blueprint.cm.version}.jar;%KARAF_HOME%\system\org\ops4j\pax\logging\pax-logging-api\${pax.logging.version}\pax-logging-api-${pax.logging.version}.jar;%KARAF_HOME%\system\org\apache\felix\org.apache.felix.framework\${felix.framework.version}\org.apache.felix.framework-${felix.framework.version}.jar;%KARAF_HOME%\system\jline\jline\${jline.version}\jline-${jline.version}.jar;%CLASSPATH%
 
 :EXECUTE
     if "%SHIFT%" == "true" SET ARGS=%2 %3 %4 %5 %6 %7 %8

http://git-wip-us.apache.org/repos/asf/karaf/blob/507b41d1/assemblies/features/standard/src/main/feature/feature.xml
----------------------------------------------------------------------
diff --git a/assemblies/features/standard/src/main/feature/feature.xml b/assemblies/features/standard/src/main/feature/feature.xml
index 8832071..b8fa750 100644
--- a/assemblies/features/standard/src/main/feature/feature.xml
+++ b/assemblies/features/standard/src/main/feature/feature.xml
@@ -25,7 +25,6 @@
     </feature>
 
     <feature name="standard" description="Karaf standard feature" version="${project.version}">
-        <bundle start-level="30">mvn:org.apache.felix/org.apache.felix.gogo.runtime/${felix.gogo.version}</bundle>
         <bundle start-level="30">mvn:org.apache.karaf.shell/org.apache.karaf.shell.console/${project.version}</bundle>
         <bundle start-level="30">mvn:org.apache.karaf.features/org.apache.karaf.features.core/${project.version}</bundle>
         <bundle start-level="30">mvn:org.apache.karaf.features/org.apache.karaf.features.command/${project.version}</bundle>

http://git-wip-us.apache.org/repos/asf/karaf/blob/507b41d1/itests/src/test/java/org/apache/karaf/itests/KarafTestSupport.java
----------------------------------------------------------------------
diff --git a/itests/src/test/java/org/apache/karaf/itests/KarafTestSupport.java b/itests/src/test/java/org/apache/karaf/itests/KarafTestSupport.java
index e7595a1..1fb9b20 100644
--- a/itests/src/test/java/org/apache/karaf/itests/KarafTestSupport.java
+++ b/itests/src/test/java/org/apache/karaf/itests/KarafTestSupport.java
@@ -164,8 +164,6 @@ public class KarafTestSupport {
         String response;
         final ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
         final PrintStream printStream = new PrintStream(byteArrayOutputStream);
-        final CommandProcessor commandProcessor = getOsgiService(CommandProcessor.class);
-        final CommandSession commandSession = commandProcessor.createSession(System.in, printStream, System.err);
 
         final Callable<String> commandCallable = new Callable<String>() {
             @Override
@@ -174,6 +172,8 @@ public class KarafTestSupport {
                     if (!silent) {
                         System.err.println(command);
                     }
+                    final CommandProcessor commandProcessor = getOsgiService(CommandProcessor.class);
+                    final CommandSession commandSession = commandProcessor.createSession(System.in, printStream, System.err);
                     commandSession.execute(command);
                 } catch (Exception e) {
                     throw new RuntimeException(e.getMessage(), e);

http://git-wip-us.apache.org/repos/asf/karaf/blob/507b41d1/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..52b7f93 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,18 @@ import java.security.ProtectionDomain;
 import javax.security.auth.Subject;
 import javax.security.auth.SubjectDomainCombiner;
 
+import org.apache.karaf.jaas.boot.principal.UserPrincipal;
+
 public class JaasHelper {
 
+    public static String getUserName(final Subject subject) {
+        if (subject != null && subject.getPrincipals().iterator().hasNext()) {
+            return subject.getPrincipals(UserPrincipal.class).iterator().next().getName();
+        } else {
+            return null;
+        }
+    }
+
     public static <T> T doAs(final Subject subject,
                              final PrivilegedAction<T> action) {
         if (action == null) {

http://git-wip-us.apache.org/repos/asf/karaf/blob/507b41d1/shell/console/pom.xml
----------------------------------------------------------------------
diff --git a/shell/console/pom.xml b/shell/console/pom.xml
index b1d4fa2..f2512d3 100644
--- a/shell/console/pom.xml
+++ b/shell/console/pom.xml
@@ -129,7 +129,8 @@
                 <configuration>
                     <instructions>
                         <Import-Package>
-                            !org.apache.felix.gogo.runtime.*,
+                            !org.apache.felix.gogo.*,
+                            !org.apache.felix.service.*,
                             org.osgi.service.event;resolution:=optional,
                             org.apache.karaf.branding;resolution:=optional,
                             org.apache.sshd.agent*;resolution:=optional,
@@ -154,7 +155,10 @@
                             org.apache.karaf.shell.console.jline;version=2.3.0,
                         	org.apache.karaf.shell.util;version=${project.version},
                             org.apache.karaf.shell.util;version=2.3.0,
-                            org.apache.felix.gogo.commands*;version=${felix.gogo.version}
+                            org.apache.felix.gogo.api;version=${felix.gogo.version},
+                            org.apache.felix.gogo.commands*;version=${felix.gogo.version},
+                            org.apache.felix.service.command;version=${felix.gogo.version},
+                            org.apache.felix.service.threadio;version=${felix.gogo.version}
                         </Export-Package>
                         <Private-Package>
                         	org.apache.karaf.shell.console.impl*,
@@ -162,11 +166,16 @@
                             
                             <!-- We need to embed gogo runtime to be able to create 
                                  SecuredCommandProcessorImpl which needs CommandProcessorImpl -->
-                            org.apache.felix.gogo.runtime
+                            org.apache.felix.gogo.runtime.*
                         </Private-Package>
                         <Main-Class>
                             org.apache.karaf.shell.console.impl.Main
                         </Main-Class>
+                        <Export-Service>
+                            org.apache.felix.service.threadio.ThreadIO,
+                            org.apache.felix.service.command.CommandProcessor,
+                            org.apache.felix.service.command.Converter
+                        </Export-Service>
                     </instructions>
                     <unpackBundle>true</unpackBundle>
                 </configuration>

http://git-wip-us.apache.org/repos/asf/karaf/blob/507b41d1/shell/console/src/main/java/org/apache/karaf/shell/console/impl/Main.java
----------------------------------------------------------------------
diff --git a/shell/console/src/main/java/org/apache/karaf/shell/console/impl/Main.java b/shell/console/src/main/java/org/apache/karaf/shell/console/impl/Main.java
index 2b0d0d9..4cc2686 100644
--- a/shell/console/src/main/java/org/apache/karaf/shell/console/impl/Main.java
+++ b/shell/console/src/main/java/org/apache/karaf/shell/console/impl/Main.java
@@ -230,7 +230,7 @@ public class Main {
      * @throws Exception
      */
     protected ConsoleImpl createConsole(CommandProcessorImpl commandProcessor, ThreadIO threadIO, InputStream in, PrintStream out, PrintStream err, Terminal terminal) throws Exception {
-        return new ConsoleImpl(commandProcessor, threadIO, in, out, err, terminal, null, null, null, false);
+        return new ConsoleImpl(commandProcessor, threadIO, in, out, err, terminal, null, null, null);
     }
 
     /**

http://git-wip-us.apache.org/repos/asf/karaf/blob/507b41d1/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 263c7ee..93a0b95 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
@@ -69,7 +69,7 @@ public class ConsoleFactoryService implements ConsoleFactory {
     @Override
     public Console create(CommandProcessor processor, ThreadIO threadIO, InputStream in, PrintStream out, PrintStream err, final Terminal terminal,
             String encoding, Runnable closeCallback) {
-        ConsoleImpl console = new ConsoleImpl(processor, threadIO, in, out, err, terminal, encoding, closeCallback, bundleContext, true);
+        ConsoleImpl console = new ConsoleImpl(processor, threadIO, in, out, err, terminal, encoding, closeCallback, bundleContext);
         CommandSession session = console.getSession();
         session.put("APPLICATION", System.getProperty("karaf.name", "root"));
         session.put("#LINES", new Function() {

http://git-wip-us.apache.org/repos/asf/karaf/blob/507b41d1/shell/console/src/main/java/org/apache/karaf/shell/console/impl/jline/ConsoleImpl.java
----------------------------------------------------------------------
diff --git a/shell/console/src/main/java/org/apache/karaf/shell/console/impl/jline/ConsoleImpl.java b/shell/console/src/main/java/org/apache/karaf/shell/console/impl/jline/ConsoleImpl.java
index 4ce7194..a16df1e 100644
--- a/shell/console/src/main/java/org/apache/karaf/shell/console/impl/jline/ConsoleImpl.java
+++ b/shell/console/src/main/java/org/apache/karaf/shell/console/impl/jline/ConsoleImpl.java
@@ -91,21 +91,15 @@ public class ConsoleImpl implements Console {
                        Terminal term,
                        String encoding,
                        Runnable closeCallback,
-                       BundleContext bc,
-                       boolean secured) {
+                       BundleContext bc) {
         this.threadIO = threadIO;
         this.in = in;
         this.out = out;
         this.err = err;
-        this.secured = secured;
         this.queue = new ArrayBlockingQueue<Integer>(1024);
         this.terminal = term == null ? new UnsupportedTerminal() : term;
         this.consoleInput = new ConsoleInputStream();
-        if (secured) {
-            this.session = new DelegateSession();
-        } else {
-            this.session = processor.createSession(consoleInput, out, err);
-        }
+        this.session = processor.createSession(consoleInput, out, err);
         this.session.put("SCOPE", "shell:bundle:*");
         this.session.put("SUBSHELL", "");
         this.setCompletionMode();
@@ -190,10 +184,6 @@ public class ConsoleImpl implements Console {
     public void run() {
         try {
             threadIO.setStreams(consoleInput, out, err);
-            SecuredCommandProcessorImpl secCP = null;
-            if (secured) {
-                secCP = createSecuredCommandProcessor();
-            }
             thread = Thread.currentThread();
             CommandSessionHolder.setSession(session);
             running = true;
@@ -225,13 +215,6 @@ public class ConsoleImpl implements Console {
                     ShellUtil.logException(session, t);
                 }
             }
-            if (secured) {
-                try {
-                    secCP.close();
-                } catch (Throwable t) {
-                    // Ignore
-                }
-            }
             close(true);
         } finally {
             try {
@@ -241,22 +224,6 @@ public class ConsoleImpl implements Console {
             }
         }
     }
-
-    SecuredCommandProcessorImpl createSecuredCommandProcessor() {
-        if (!(session instanceof DelegateSession)) {
-            throw new IllegalStateException("Should be an Delegate Session here, about to set the delegate");
-        }
-        DelegateSession is = (DelegateSession) session;
-
-        // make it active
-        SecuredCommandProcessorImpl secCP = new SecuredCommandProcessorImpl(bundleContext);
-        CommandSession s = secCP.createSession(consoleInput, out, err);
-
-        // before the session is activated attributes may have been set on it. Pass these on to the real session now
-        is.setDelegate(s);
-        return secCP;
-    }
-
     private void setCompletionMode() {
         try {
             File shellCfg = new File(System.getProperty("karaf.etc"), "/org.apache.karaf.shell.cfg");

http://git-wip-us.apache.org/repos/asf/karaf/blob/507b41d1/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 9ea2f96..e9e6f70 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
@@ -19,6 +19,7 @@
 package org.apache.karaf.shell.console.impl.jline;
 
 import java.nio.charset.Charset;
+import java.security.PrivilegedAction;
 
 import javax.security.auth.Subject;
 
@@ -28,6 +29,7 @@ import org.apache.felix.service.command.CommandSession;
 import org.apache.felix.service.threadio.ThreadIO;
 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.ConsoleFactory;
 import org.osgi.framework.BundleContext;
@@ -81,7 +83,7 @@ public class LocalConsoleManager {
         }
 
         final Terminal terminal = terminalFactory.getTerminal();
-        Runnable callback = new Runnable() {
+        final Runnable callback = new Runnable() {
             public void run() {
                 try {
                     bundleContext.getBundle(0).stop();
@@ -91,19 +93,31 @@ public class LocalConsoleManager {
             }
         };
         String ctype = System.getenv("LC_CTYPE");
-        String encoding = ctype;
-        if (encoding != null && encoding.indexOf('.') > 0) {
-            encoding = encoding.substring(encoding.indexOf('.') + 1);
+        final String encoding;
+        if (ctype != null && ctype.indexOf('.') > 0) {
+            encoding = ctype.substring(ctype.indexOf('.') + 1);
         } else {
             encoding = System.getProperty("input.encoding", Charset.defaultCharset().name());
         }
-        this.console = consoleFactory.createLocal(this.commandProcessor, this.threadIO, terminal, encoding, callback);
-
-        registration = bundleContext.registerService(CommandSession.class, console.getSession(), null);
 
         Runnable consoleStarter = new Runnable() {
             public void run() {
-                consoleFactory.startConsoleAs(console, subject, "Local");
+                new Thread("Karaf Console Local for user " + JaasHelper.getUserName(subject)) {
+                    @Override
+                    public void run() {
+                        JaasHelper.doAs(subject, new PrivilegedAction<Object>() {
+                            @Override
+                            public Object run() {
+                                console = consoleFactory.createLocal(commandProcessor, threadIO, terminal, encoding, callback);
+                                registration = bundleContext.registerService(CommandSession.class, console.getSession(), null);
+                                CommandSession session = console.getSession();
+                                session.put("USER", JaasHelper.getUserName(subject));
+                                console.run();
+                                return null;
+                            }
+                        });
+                    }
+                }.start();
             }
         };
         

http://git-wip-us.apache.org/repos/asf/karaf/blob/507b41d1/shell/console/src/main/java/org/apache/karaf/shell/security/impl/SecCommandProcessorImpl.java
----------------------------------------------------------------------
diff --git a/shell/console/src/main/java/org/apache/karaf/shell/security/impl/SecCommandProcessorImpl.java b/shell/console/src/main/java/org/apache/karaf/shell/security/impl/SecCommandProcessorImpl.java
new file mode 100644
index 0000000..29b02a2
--- /dev/null
+++ b/shell/console/src/main/java/org/apache/karaf/shell/security/impl/SecCommandProcessorImpl.java
@@ -0,0 +1,42 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.karaf.shell.security.impl;
+
+import java.io.InputStream;
+import java.io.PrintStream;
+
+import org.apache.felix.service.command.CommandProcessor;
+import org.apache.felix.service.command.CommandSession;
+import org.apache.felix.service.threadio.ThreadIO;
+import org.osgi.framework.BundleContext;
+
+public class SecCommandProcessorImpl implements CommandProcessor {
+
+    private final BundleContext bundleContext;
+    private final ThreadIO threadIO;
+
+    public SecCommandProcessorImpl(BundleContext bundleContext, ThreadIO threadIO) {
+        this.bundleContext = bundleContext;
+        this.threadIO = threadIO;
+    }
+
+    public CommandSession createSession(InputStream in, PrintStream out, PrintStream err) {
+        SecuredCommandProcessorImpl scp = new SecuredCommandProcessorImpl(bundleContext, threadIO);
+        return scp.createSession(in, out, err);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/507b41d1/shell/console/src/main/java/org/apache/karaf/shell/security/impl/SecuredCommandProcessorImpl.java
----------------------------------------------------------------------
diff --git a/shell/console/src/main/java/org/apache/karaf/shell/security/impl/SecuredCommandProcessorImpl.java b/shell/console/src/main/java/org/apache/karaf/shell/security/impl/SecuredCommandProcessorImpl.java
index 84224c4..3a83958 100644
--- a/shell/console/src/main/java/org/apache/karaf/shell/security/impl/SecuredCommandProcessorImpl.java
+++ b/shell/console/src/main/java/org/apache/karaf/shell/security/impl/SecuredCommandProcessorImpl.java
@@ -22,7 +22,6 @@ import org.apache.felix.gogo.runtime.CommandProxy;
 import org.apache.felix.gogo.runtime.activator.Activator;
 import org.apache.felix.service.command.CommandProcessor;
 import org.apache.felix.service.command.Converter;
-import org.apache.felix.service.command.Function;
 import org.apache.felix.service.threadio.ThreadIO;
 import org.apache.karaf.jaas.boot.principal.RolePrincipal;
 import org.osgi.framework.BundleContext;
@@ -35,48 +34,47 @@ import javax.security.auth.Subject;
 import java.security.AccessControlContext;
 import java.security.AccessController;
 import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
 
 public class SecuredCommandProcessorImpl extends CommandProcessorImpl {
 
     private final BundleContext bundleContext;
-    private final ServiceReference<ThreadIO> threadIOServiceReference;
     private final ServiceTracker<Object, Object> commandTracker;
     private final ServiceTracker<Converter, Converter> converterTracker;
     private final ServiceTracker<CommandSessionListener, CommandSessionListener> listenerTracker;
 
-    public SecuredCommandProcessorImpl(BundleContext bc) {
-        this(bc, bc.getServiceReference(ThreadIO.class));
-    }
-
-    private SecuredCommandProcessorImpl(BundleContext bc, ServiceReference<ThreadIO> sr) {
-        super(bc.getService(sr));
+    public SecuredCommandProcessorImpl(BundleContext bc, ThreadIO io) {
+        super(io);
         bundleContext = bc;
-        threadIOServiceReference = sr;
+
+        String roleClause = "";
 
         AccessControlContext acc = AccessController.getContext();
         Subject sub = Subject.getSubject(acc);
-        if (sub == null)
-            throw new SecurityException("No current Subject in the Access Control Context");
-
-        Set<RolePrincipal> rolePrincipals = sub.getPrincipals(RolePrincipal.class);
-        if (rolePrincipals.size() == 0)
-            throw new SecurityException("Current user has no associated roles.");
-
-        // TODO cater for custom roles
-        StringBuilder sb = new StringBuilder();
-        sb.append("(|");
-        for (RolePrincipal rp : rolePrincipals) {
-            sb.append('(');
-            sb.append("org.apache.karaf.service.guard.roles");
-            sb.append('=');
-            sb.append(rp.getName());
+        if (sub != null) {
+            Set<RolePrincipal> rolePrincipals = sub.getPrincipals(RolePrincipal.class);
+            if (rolePrincipals.size() == 0)
+                throw new SecurityException("Current user has no associated roles.");
+
+            // TODO cater for custom roles
+            StringBuilder sb = new StringBuilder();
+            sb.append("(|");
+            for (RolePrincipal rp : rolePrincipals) {
+                sb.append('(');
+                sb.append("org.apache.karaf.service.guard.roles");
+                sb.append('=');
+                sb.append(rp.getName());
+                sb.append(')');
+            }
+            sb.append("(!(org.apache.karaf.service.guard.roles=*))"); // Or no roles specified at all
             sb.append(')');
+            roleClause = sb.toString();
         }
-        sb.append("(!(org.apache.karaf.service.guard.roles=*))"); // Or no roles specified at all
-        sb.append(')');
-        String roleClause = sb.toString();
 
         addConstant(Activator.CONTEXT, bc);
         addCommand("osgi", this, "addCommand");
@@ -101,7 +99,6 @@ public class SecuredCommandProcessorImpl extends CommandProcessorImpl {
         commandTracker.close();
         converterTracker.close();
         listenerTracker.close();
-        bundleContext.ungetService(threadIOServiceReference);
     }
 
     private ServiceTracker<Object, Object> trackCommands(final BundleContext context, String roleClause) throws InvalidSyntaxException {
@@ -109,45 +106,57 @@ public class SecuredCommandProcessorImpl extends CommandProcessorImpl {
                 CommandProcessor.COMMAND_SCOPE, CommandProcessor.COMMAND_FUNCTION, roleClause));
 
         return new ServiceTracker<Object, Object>(context, filter, null) {
+            private final ConcurrentMap<ServiceReference, Map<String, CommandProxy>> proxies
+                    = new ConcurrentHashMap<ServiceReference, Map<String, CommandProxy>>();
+
             @Override
-            public Object addingService(ServiceReference<Object> reference) {
+            public Object addingService(ServiceReference reference)
+            {
                 Object scope = reference.getProperty(CommandProcessor.COMMAND_SCOPE);
                 Object function = reference.getProperty(CommandProcessor.COMMAND_FUNCTION);
                 List<Object> commands = new ArrayList<Object>();
 
-                if (scope != null && function != null) {
-                    if (function.getClass().isArray()) {
-                        for (Object f : ((Object[]) function)) {
-                            Function target = new CommandProxy(context, reference,
-                                    f.toString());
+                if (scope != null && function != null)
+                {
+                    Map<String, CommandProxy> proxyMap = new HashMap<String, CommandProxy>();
+                    if (function.getClass().isArray())
+                    {
+                        for (Object f : ((Object[]) function))
+                        {
+                            CommandProxy target = new CommandProxy(context, reference, f.toString());
+                            proxyMap.put(f.toString(), target);
                             addCommand(scope.toString(), target, f.toString());
                             commands.add(target);
                         }
-                    } else {
-                        Function target = new CommandProxy(context, reference,
-                                function.toString());
+                    }
+                    else
+                    {
+                        CommandProxy target = new CommandProxy(context, reference, function.toString());
+                        proxyMap.put(function.toString(), target);
                         addCommand(scope.toString(), target, function.toString());
                         commands.add(target);
                     }
+                    proxies.put(reference, proxyMap);
                     return commands;
                 }
                 return null;
             }
 
             @Override
-            public void removedService(ServiceReference<Object> reference, Object service) {
+            public void removedService(ServiceReference reference, Object service)
+            {
                 Object scope = reference.getProperty(CommandProcessor.COMMAND_SCOPE);
                 Object function = reference.getProperty(CommandProcessor.COMMAND_FUNCTION);
 
-                if (scope != null && function != null) {
-                    if (!function.getClass().isArray()) {
-                        removeCommand(scope.toString(), function.toString());
-                    } else {
-                        for (Object func : (Object[]) function) {
-                            removeCommand(scope.toString(), func.toString());
-                        }
+                if (scope != null && function != null)
+                {
+                    Map<String, CommandProxy> proxyMap = proxies.remove(reference);
+                    for (Map.Entry<String, CommandProxy> entry : proxyMap.entrySet())
+                    {
+                        removeCommand(scope.toString(), entry.getKey());
                     }
                 }
+
                 super.removedService(reference, service);
             }
         };

http://git-wip-us.apache.org/repos/asf/karaf/blob/507b41d1/shell/console/src/main/resources/OSGI-INF/blueprint/karaf-console.xml
----------------------------------------------------------------------
diff --git a/shell/console/src/main/resources/OSGI-INF/blueprint/karaf-console.xml b/shell/console/src/main/resources/OSGI-INF/blueprint/karaf-console.xml
index e37ff4b..1151cb8 100644
--- a/shell/console/src/main/resources/OSGI-INF/blueprint/karaf-console.xml
+++ b/shell/console/src/main/resources/OSGI-INF/blueprint/karaf-console.xml
@@ -26,8 +26,15 @@
         </ext:default-properties>
     </ext:property-placeholder>
 
-    <reference id="commandProcessor" interface="org.apache.felix.service.command.CommandProcessor"/>
-    <reference id="threadIO" interface="org.apache.felix.service.threadio.ThreadIO" />
+    <bean id="threadIO" class="org.apache.felix.gogo.runtime.threadio.ThreadIOImpl"
+          init-method="start" destroy-method="stop"/>
+    <service ref="threadIO" auto-export="interfaces"/>
+
+    <bean id="commandProcessor" class="org.apache.karaf.shell.security.impl.SecCommandProcessorImpl">
+        <argument ref="blueprintBundleContext"/>
+        <argument ref="threadIO"/>
+    </bean>
+    <service ref="commandProcessor" auto-export="interfaces"/>
 
     <bean id="consoleFactoryService" class="org.apache.karaf.shell.console.impl.jline.ConsoleFactoryService">
         <argument ref="blueprintBundleContext"/>

http://git-wip-us.apache.org/repos/asf/karaf/blob/507b41d1/shell/console/src/test/java/org/apache/karaf/shell/console/ExampleSubclassMain.java
----------------------------------------------------------------------
diff --git a/shell/console/src/test/java/org/apache/karaf/shell/console/ExampleSubclassMain.java b/shell/console/src/test/java/org/apache/karaf/shell/console/ExampleSubclassMain.java
index 05ce705..8229d08 100644
--- a/shell/console/src/test/java/org/apache/karaf/shell/console/ExampleSubclassMain.java
+++ b/shell/console/src/test/java/org/apache/karaf/shell/console/ExampleSubclassMain.java
@@ -47,7 +47,7 @@ public class ExampleSubclassMain extends Main  {
 
     @Override
     protected ConsoleImpl createConsole(CommandProcessorImpl commandProcessor, ThreadIO threadIO, InputStream in, PrintStream out, PrintStream err, Terminal terminal) throws Exception {
-        return new ConsoleImpl(commandProcessor, threadIO, in, out, err, terminal, null, null, null, true) {
+        return new ConsoleImpl(commandProcessor, threadIO, in, out, err, terminal, null, null, null) {
 
             /**
              * If you don't overwrite, then karaf will use the welcome message found in the

http://git-wip-us.apache.org/repos/asf/karaf/blob/507b41d1/shell/console/src/test/java/org/apache/karaf/shell/console/impl/jline/ConsoleImplTest.java
----------------------------------------------------------------------
diff --git a/shell/console/src/test/java/org/apache/karaf/shell/console/impl/jline/ConsoleImplTest.java b/shell/console/src/test/java/org/apache/karaf/shell/console/impl/jline/ConsoleImplTest.java
deleted file mode 100644
index 24b229b..0000000
--- a/shell/console/src/test/java/org/apache/karaf/shell/console/impl/jline/ConsoleImplTest.java
+++ /dev/null
@@ -1,195 +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.shell.console.impl.jline;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertSame;
-import static org.junit.Assert.assertTrue;
-
-import java.io.InputStream;
-import java.io.PrintStream;
-import java.security.PrivilegedAction;
-
-import javax.security.auth.Subject;
-
-import org.apache.felix.gogo.api.CommandSessionListener;
-import org.apache.felix.gogo.runtime.threadio.ThreadIOImpl;
-import org.apache.felix.service.command.CommandProcessor;
-import org.apache.felix.service.command.CommandSession;
-import org.apache.felix.service.command.Converter;
-import org.apache.karaf.jaas.boot.principal.RolePrincipal;
-import org.apache.karaf.shell.console.impl.jline.ConsoleImpl.DelegateSession;
-import org.apache.karaf.shell.security.impl.SecuredCommandProcessorImpl;
-import org.easymock.EasyMock;
-import org.easymock.IAnswer;
-import org.junit.Test;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.Filter;
-import org.osgi.framework.FrameworkUtil;
-import org.osgi.framework.ServiceListener;
-import org.osgi.framework.ServiceReference;
-
-public class ConsoleImplTest {
-    @Test
-    public void testConsoleImpl() throws Exception {
-        ServiceReference<?> cmRef = EasyMock.createMock(ServiceReference.class);
-        EasyMock.expect(cmRef.getProperty(CommandProcessor.COMMAND_SCOPE)).andReturn("myscope").anyTimes();
-        EasyMock.expect(cmRef.getProperty(CommandProcessor.COMMAND_FUNCTION)).andReturn("myfunction").anyTimes();
-        EasyMock.replay(cmRef);
-        ServiceReference<?>[] cmRefs = new ServiceReference[] {cmRef};
-
-        BundleContext bc = EasyMock.createMock(BundleContext.class);
-        EasyMock.expect(bc.getServiceReference((Class<?>) EasyMock.anyObject())).andReturn(null).anyTimes();
-        EasyMock.expect(bc.getService((ServiceReference<?>) EasyMock.anyObject())).andReturn(null).anyTimes();
-        bc.addServiceListener(EasyMock.isA(ServiceListener.class), EasyMock.isA(String.class));
-        EasyMock.expectLastCall().anyTimes();
-        EasyMock.expect(bc.getServiceReferences((String) null,
-                "(&(osgi.command.scope=*)(osgi.command.function=*)" +
-                        "(|(org.apache.karaf.service.guard.roles=myrole)(!(org.apache.karaf.service.guard.roles=*))))")).andReturn(cmRefs).anyTimes();
-        EasyMock.expect(bc.getServiceReferences(Converter.class.getName(), null)).andReturn(null).anyTimes();
-        EasyMock.expect(bc.getServiceReferences(CommandSessionListener.class.getName(), null)).andReturn(null).anyTimes();
-        EasyMock.expect(bc.createFilter(EasyMock.isA(String.class))).andAnswer(new IAnswer<Filter>() {
-            @Override
-            public Filter answer() throws Throwable {
-                return FrameworkUtil.createFilter((String) EasyMock.getCurrentArguments()[0]);
-            }
-        }).anyTimes();
-        EasyMock.replay(bc);
-
-        final ConsoleImpl console = new ConsoleImpl(null, new ThreadIOImpl(), System.in, System.out, System.err, null, "UTF-8", null, bc, true);
-        assertTrue(console.session instanceof DelegateSession);
-
-        console.session.put("foo", "bar");
-
-        final DelegateSession ds = (DelegateSession) console.session;
-        assertNull("Precondition", ds.delegate);
-
-        Subject subject = new Subject();
-        subject.getPrincipals().add(new RolePrincipal("myrole"));
-
-        Subject.doAs(subject, new PrivilegedAction<Object>() {
-            @Override
-            public Object run() {
-                SecuredCommandProcessorImpl secCP = console.createSecuredCommandProcessor();
-                assertNotNull(ds.delegate);
-                assertEquals("Attributes set before the delegate was set should have been transferred",
-                        "bar", ds.get("foo"));
-                assertEquals("Attributes set before the delegate was set should have been transferred",
-                        "bar", ds.delegate.get("foo"));
-                assertSame(System.out, ds.delegate.getConsole());
-                assertSame(System.out, ds.getConsole());
-
-                assertTrue(secCP.getCommands().contains("myscope:myfunction"));
-
-                return null;
-            }
-        });
-    }
-
-    @Test
-    public void testDelegateSession() throws Exception {
-        DelegateSession ds = new DelegateSession();
-
-        ds.put("a", "b");
-        assertEquals("b", ds.get("a"));
-
-        TestSession ts = new TestSession();
-
-        assertNull("Precondition", ts.lastInvoked);
-
-        ds.setDelegate(ts);
-        assertEquals("put(a,b)", ts.lastInvoked);
-
-        ds.put("c", "d");
-        assertEquals("put(c,d)", ts.lastInvoked);
-
-        ds.execute("hello 1234");
-        assertEquals("execute(hello 1234)", ts.lastInvoked);
-
-        ds.close();
-        assertEquals("close", ts.lastInvoked);
-
-        ds.getKeyboard();
-        assertEquals("getKeyboard", ts.lastInvoked);
-
-        ds.getConsole();
-        assertEquals("getConsole", ts.lastInvoked);
-
-        ds.get("xyz");
-        assertEquals("get(xyz)", ts.lastInvoked);
-
-        ds.format("foo", 12);
-        assertEquals("format(foo,12)", ts.lastInvoked);
-
-        ds.convert(TestSession.class, "a string");
-        assertEquals("convert(TestSession,a string)", ts.lastInvoked);
-    }
-
-    static class TestSession implements CommandSession {
-        String lastInvoked;
-
-        @Override
-        public Object execute(CharSequence commandline) throws Exception {
-            lastInvoked = "execute(" + commandline + ")";
-            return null;
-        }
-
-        @Override
-        public void close() {
-            lastInvoked = "close";
-        }
-
-        @Override
-        public InputStream getKeyboard() {
-            lastInvoked = "getKeyboard";
-            return null;
-        }
-
-        @Override
-        public PrintStream getConsole() {
-            lastInvoked = "getConsole";
-            return null;
-        }
-
-        @Override
-        public Object get(String name) {
-            lastInvoked = "get(" + name + ")";
-            return null;
-        }
-
-        @Override
-        public void put(String name, Object value) {
-            lastInvoked = "put(" + name + "," + value + ")";
-        }
-
-        @Override
-        public CharSequence format(Object target, int level) {
-            lastInvoked = "format(" + target + "," + level + ")";
-            return null;
-        }
-
-        @Override
-        public Object convert(Class<?> type, Object instance) {
-            lastInvoked = "convert(" + type.getSimpleName() + "," + instance + ")";
-            return null;
-        }
-    }
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/karaf/blob/507b41d1/shell/console/src/test/java/org/apache/karaf/shell/security/impl/SecuredCommandProcessorImplTest.java
----------------------------------------------------------------------
diff --git a/shell/console/src/test/java/org/apache/karaf/shell/security/impl/SecuredCommandProcessorImplTest.java b/shell/console/src/test/java/org/apache/karaf/shell/security/impl/SecuredCommandProcessorImplTest.java
index 351a89f..0c66eb6 100644
--- a/shell/console/src/test/java/org/apache/karaf/shell/security/impl/SecuredCommandProcessorImplTest.java
+++ b/shell/console/src/test/java/org/apache/karaf/shell/security/impl/SecuredCommandProcessorImplTest.java
@@ -132,7 +132,7 @@ public class SecuredCommandProcessorImplTest {
     // Subclass to provide access to some protected members
     static class MySecuredCommandProcessorImpl extends SecuredCommandProcessorImpl {
         public MySecuredCommandProcessorImpl(BundleContext bc) {
-            super(bc);
+            super(bc, null);
         }
 
         Map<String, Object> getConstants() {

http://git-wip-us.apache.org/repos/asf/karaf/blob/507b41d1/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 08bf0d8..4b33699 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
@@ -24,14 +24,15 @@ import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
 import java.io.PrintStream;
+import java.security.PrivilegedAction;
 import java.util.Map;
 
 import javax.security.auth.Subject;
 
 import jline.Terminal;
-
 import org.apache.felix.service.command.CommandProcessor;
 import org.apache.felix.service.command.CommandSession;
+import org.apache.karaf.jaas.modules.JaasHelper;
 import org.apache.karaf.shell.console.Console;
 import org.apache.karaf.shell.console.ConsoleFactory;
 import org.apache.felix.service.command.Function;
@@ -43,12 +44,17 @@ import org.apache.sshd.server.ExitCallback;
 import org.apache.sshd.server.SessionAware;
 import org.apache.sshd.server.session.ServerSession;
 import org.osgi.service.blueprint.container.ReifiedType;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 /**
  * SSHD {@link org.apache.sshd.server.Command} factory which provides access to
  * Shell.
  */
 public class ShellFactoryImpl implements Factory<Command> {
+
+    private static final Logger LOGGER = LoggerFactory.getLogger(ShellFactoryImpl.class);
+
     private CommandProcessor commandProcessor;
     private ConsoleFactory consoleFactory;
     private ThreadIO threadIO;
@@ -97,29 +103,49 @@ public class ShellFactoryImpl implements Factory<Command> {
         }
 
         public void start(final Environment env) throws IOException {
-            try {
-                final Subject subject = ShellImpl.this.session != null ? ShellImpl.this.session
-                        .getAttribute(KarafJaasAuthenticator.SUBJECT_ATTRIBUTE_KEY) : null;
-                final Terminal terminal = new SshTerminal(env);
-                Runnable destroyCallback = new Runnable() {
-                    public void run() {
-                        destroy();
+            new Thread() {
+                @Override
+                public void run() {
+                    final Subject subject = ShellImpl.this.session != null ? ShellImpl.this.session.getAttribute(KarafJaasAuthenticator.SUBJECT_ATTRIBUTE_KEY) : null;
+                    if (subject != null) {
+                        JaasHelper.doAs(subject, new PrivilegedAction<Object>() {
+                            public Object run() {
+                                String userName = JaasHelper.getUserName(subject);
+                                Thread.currentThread().setName("Karaf Console ssh for user " + userName);
+                                runConsole(userName);
+                                return null;
+                            }
+                        });
+                    } else {
+                        Thread.currentThread().setName("Karaf Console ssh for anonymous user");
+                        runConsole(null);
                     }
-                };
-                String encoding = env.getEnv().get("LC_CTYPE");
-                if (encoding != null && encoding.indexOf('.') > 0) {
-                    encoding = encoding.substring(encoding.indexOf('.') + 1);
                 }
-                Console console = consoleFactory.create(commandProcessor, threadIO, in,
-                        lfToCrLfPrintStream(out), lfToCrLfPrintStream(err), terminal, encoding, destroyCallback);
-                final CommandSession session = console.getSession();
-                for (Map.Entry<String, String> e : env.getEnv().entrySet()) {
-                    session.put(e.getKey(), e.getValue());
+                protected void runConsole(String userName) {
+                    try {
+                        final Terminal terminal = new SshTerminal(env);
+                        Runnable destroyCallback = new Runnable() {
+                            public void run() {
+                                ShellImpl.this.destroy();
+                            }
+                        };
+                        String encoding = env.getEnv().get("LC_CTYPE");
+                        if (encoding != null && encoding.indexOf('.') > 0) {
+                            encoding = encoding.substring(encoding.indexOf('.') + 1);
+                        }
+                        final Console console = consoleFactory.create(commandProcessor, threadIO, in,
+                                lfToCrLfPrintStream(out), lfToCrLfPrintStream(err), terminal, encoding, destroyCallback);
+                        final CommandSession session = console.getSession();
+                        for (Map.Entry<String,String> e : env.getEnv().entrySet()) {
+                            session.put(e.getKey(), e.getValue());
+                        }
+                        session.put("USER", userName);
+                        console.run();
+                    } catch (Exception e) {
+                        LOGGER.warn("Unable to start shell", e);
+                    }
                 }
-                consoleFactory.startConsoleAs(console, subject, "ssh");
-            } catch (Exception e) {
-                throw (IOException) new IOException("Unable to start shell").initCause(e);
-            }
+            }.start();
         }
 
         private PrintStream lfToCrLfPrintStream(OutputStream stream) {

http://git-wip-us.apache.org/repos/asf/karaf/blob/507b41d1/webconsole/gogo/src/main/java/org/apache/karaf/webconsole/gogo/GogoPlugin.java
----------------------------------------------------------------------
diff --git a/webconsole/gogo/src/main/java/org/apache/karaf/webconsole/gogo/GogoPlugin.java b/webconsole/gogo/src/main/java/org/apache/karaf/webconsole/gogo/GogoPlugin.java
index 077c31b..b58eb67 100644
--- a/webconsole/gogo/src/main/java/org/apache/karaf/webconsole/gogo/GogoPlugin.java
+++ b/webconsole/gogo/src/main/java/org/apache/karaf/webconsole/gogo/GogoPlugin.java
@@ -33,6 +33,8 @@ import java.io.PrintWriter;
 import java.net.URL;
 import java.security.AccessControlContext;
 import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.security.PrivilegedExceptionAction;
 import java.util.zip.GZIPOutputStream;
 
 import javax.security.auth.Subject;
@@ -42,6 +44,7 @@ import javax.servlet.http.HttpServletResponse;
 
 import org.apache.felix.service.command.CommandProcessor;
 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.ConsoleFactory;
 import org.apache.felix.webconsole.AbstractWebConsolePlugin;
@@ -194,11 +197,12 @@ public class GogoPlugin extends AbstractWebConsolePlugin {
 
                 in = new PipedOutputStream();
                 out = new PipedInputStream();
-                PrintStream pipedOut = new PrintStream(new PipedOutputStream(out), true);
+                final PrintStream pipedOut = new PrintStream(new PipedOutputStream(out), true);
 
                 AccessControlContext acc = AccessController.getContext();
-                final Subject subject = Subject.getSubject(acc);
-                
+                Subject subject = Subject.getSubject(acc);
+                String userName = JaasHelper.getUserName(subject);
+
                 Console console = consoleFactory.create(commandProcessor,
                         threadIO,
                         new PipedInputStream(in),
@@ -207,7 +211,7 @@ public class GogoPlugin extends AbstractWebConsolePlugin {
                         new WebTerminal(TERM_WIDTH, TERM_HEIGHT),
                         null,
                         null);
-                consoleFactory.startConsoleAs(console, subject, "Web");
+                new Thread(console, "Karaf Console Web for user " + userName).start();
             } catch (IOException e) {
                 e.printStackTrace();
                 throw e;


[2/3] git commit: [KARAF-3221] Incorporate the fix for FELIX-4637 into shell/core, fix the scr commands to use a service.ranking property

Posted by gn...@apache.org.
[KARAF-3221] Incorporate the fix for FELIX-4637 into shell/core, fix the scr commands to use a service.ranking property


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

Branch: refs/heads/karaf-3.0.x
Commit: 9ad9fd54ec36d0719a3fa4ba01896a8d7dfed52d
Parents: 507b41d
Author: Guillaume Nodet <gn...@gmail.com>
Authored: Thu Sep 11 23:18:53 2014 +0200
Committer: Guillaume Nodet <gn...@gmail.com>
Committed: Mon Sep 15 08:52:37 2014 +0200

----------------------------------------------------------------------
 .../scr/command/ActivateCommandComponent.java   |   4 +-
 .../scr/command/DeactivateCommandComponent.java |   4 +-
 .../scr/command/DetailsCommandComponent.java    |   4 +-
 .../karaf/scr/command/ListCommandComponent.java |   4 +-
 .../gogo/runtime/CommandProcessorImpl.java      | 358 +++++++++++++++++++
 .../impl/SecuredCommandProcessorImpl.java       |  20 +-
 6 files changed, 387 insertions(+), 7 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/karaf/blob/9ad9fd54/scr/command/src/main/java/org/apache/karaf/scr/command/ActivateCommandComponent.java
----------------------------------------------------------------------
diff --git a/scr/command/src/main/java/org/apache/karaf/scr/command/ActivateCommandComponent.java b/scr/command/src/main/java/org/apache/karaf/scr/command/ActivateCommandComponent.java
index d3b2607..46b9c21 100644
--- a/scr/command/src/main/java/org/apache/karaf/scr/command/ActivateCommandComponent.java
+++ b/scr/command/src/main/java/org/apache/karaf/scr/command/ActivateCommandComponent.java
@@ -30,6 +30,7 @@ import aQute.bnd.annotation.component.Activate;
 import aQute.bnd.annotation.component.Component;
 import aQute.bnd.annotation.component.Deactivate;
 import aQute.bnd.annotation.component.Reference;
+import org.osgi.framework.Constants;
 
 /**
  * Shell Command used to activate a Declarative Service Component.
@@ -42,7 +43,8 @@ import aQute.bnd.annotation.component.Reference;
         properties={
                 ScrCommandConstants.OSGI_COMMAND_SCOPE_KEY + "=" + ScrCommandConstants.SCR_COMMAND,
                 ScrCommandConstants.OSGI_COMMAND_FUNCTION_KEY + "=" + ScrCommandConstants.ACTIVATE_FUNCTION,
-                ScrCommandConstants.HIDDEN_COMPONENT_KEY + "=true"
+                ScrCommandConstants.HIDDEN_COMPONENT_KEY + "=true",
+                Constants.SERVICE_RANKING + "=1"
         })
 public class ActivateCommandComponent extends ScrCommandSupport {
 

http://git-wip-us.apache.org/repos/asf/karaf/blob/9ad9fd54/scr/command/src/main/java/org/apache/karaf/scr/command/DeactivateCommandComponent.java
----------------------------------------------------------------------
diff --git a/scr/command/src/main/java/org/apache/karaf/scr/command/DeactivateCommandComponent.java b/scr/command/src/main/java/org/apache/karaf/scr/command/DeactivateCommandComponent.java
index ae2bf9f..c1cd01c 100644
--- a/scr/command/src/main/java/org/apache/karaf/scr/command/DeactivateCommandComponent.java
+++ b/scr/command/src/main/java/org/apache/karaf/scr/command/DeactivateCommandComponent.java
@@ -30,6 +30,7 @@ import aQute.bnd.annotation.component.Activate;
 import aQute.bnd.annotation.component.Component;
 import aQute.bnd.annotation.component.Deactivate;
 import aQute.bnd.annotation.component.Reference;
+import org.osgi.framework.Constants;
 
 /**
  * Shell Command used to deactivate a Declarative Service Component.
@@ -42,7 +43,8 @@ import aQute.bnd.annotation.component.Reference;
         properties={
                 ScrCommandConstants.OSGI_COMMAND_SCOPE_KEY + "=" + ScrCommandConstants.SCR_COMMAND,
                 ScrCommandConstants.OSGI_COMMAND_FUNCTION_KEY + "=" + ScrCommandConstants.DEACTIVATE_FUNCTION,
-                ScrCommandConstants.HIDDEN_COMPONENT_KEY + "=true"
+                ScrCommandConstants.HIDDEN_COMPONENT_KEY + "=true",
+                Constants.SERVICE_RANKING + "=1"
         })
 public class DeactivateCommandComponent extends ScrCommandSupport {
 

http://git-wip-us.apache.org/repos/asf/karaf/blob/9ad9fd54/scr/command/src/main/java/org/apache/karaf/scr/command/DetailsCommandComponent.java
----------------------------------------------------------------------
diff --git a/scr/command/src/main/java/org/apache/karaf/scr/command/DetailsCommandComponent.java b/scr/command/src/main/java/org/apache/karaf/scr/command/DetailsCommandComponent.java
index 51407b0..51025ef 100644
--- a/scr/command/src/main/java/org/apache/karaf/scr/command/DetailsCommandComponent.java
+++ b/scr/command/src/main/java/org/apache/karaf/scr/command/DetailsCommandComponent.java
@@ -30,6 +30,7 @@ import aQute.bnd.annotation.component.Activate;
 import aQute.bnd.annotation.component.Component;
 import aQute.bnd.annotation.component.Deactivate;
 import aQute.bnd.annotation.component.Reference;
+import org.osgi.framework.Constants;
 
 /**
  * Shell Command that prints the current state details of a given
@@ -43,7 +44,8 @@ import aQute.bnd.annotation.component.Reference;
         properties={
                 ScrCommandConstants.OSGI_COMMAND_SCOPE_KEY + "=" + ScrCommandConstants.SCR_COMMAND,
                 ScrCommandConstants.OSGI_COMMAND_FUNCTION_KEY + "=" + ScrCommandConstants.DETAILS_FUNCTION,
-                ScrCommandConstants.HIDDEN_COMPONENT_KEY + "=true"
+                ScrCommandConstants.HIDDEN_COMPONENT_KEY + "=true",
+                Constants.SERVICE_RANKING + "=1"
         })
 public class DetailsCommandComponent extends ScrCommandSupport {
 

http://git-wip-us.apache.org/repos/asf/karaf/blob/9ad9fd54/scr/command/src/main/java/org/apache/karaf/scr/command/ListCommandComponent.java
----------------------------------------------------------------------
diff --git a/scr/command/src/main/java/org/apache/karaf/scr/command/ListCommandComponent.java b/scr/command/src/main/java/org/apache/karaf/scr/command/ListCommandComponent.java
index 23d82f3..551f742 100644
--- a/scr/command/src/main/java/org/apache/karaf/scr/command/ListCommandComponent.java
+++ b/scr/command/src/main/java/org/apache/karaf/scr/command/ListCommandComponent.java
@@ -28,6 +28,7 @@ import aQute.bnd.annotation.component.Activate;
 import aQute.bnd.annotation.component.Component;
 import aQute.bnd.annotation.component.Deactivate;
 import aQute.bnd.annotation.component.Reference;
+import org.osgi.framework.Constants;
 
 /**
  * Shell Command that lists the available Declarative Service Components.
@@ -40,7 +41,8 @@ import aQute.bnd.annotation.component.Reference;
         properties={
                 ScrCommandConstants.OSGI_COMMAND_SCOPE_KEY + "=" + ScrCommandConstants.SCR_COMMAND,
                 ScrCommandConstants.OSGI_COMMAND_FUNCTION_KEY + "=" + ScrCommandConstants.LIST_FUNCTION,
-                ScrCommandConstants.HIDDEN_COMPONENT_KEY + "=true"
+                ScrCommandConstants.HIDDEN_COMPONENT_KEY + "=true",
+                Constants.SERVICE_RANKING + "=1"
         })
 public class ListCommandComponent extends ScrCommandSupport {
 

http://git-wip-us.apache.org/repos/asf/karaf/blob/9ad9fd54/shell/console/src/main/java/org/apache/felix/gogo/runtime/CommandProcessorImpl.java
----------------------------------------------------------------------
diff --git a/shell/console/src/main/java/org/apache/felix/gogo/runtime/CommandProcessorImpl.java b/shell/console/src/main/java/org/apache/felix/gogo/runtime/CommandProcessorImpl.java
new file mode 100644
index 0000000..72cff88
--- /dev/null
+++ b/shell/console/src/main/java/org/apache/felix/gogo/runtime/CommandProcessorImpl.java
@@ -0,0 +1,358 @@
+/*
+ * 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.felix.gogo.runtime;
+
+import java.io.InputStream;
+import java.io.PrintStream;
+import java.lang.reflect.Method;
+import java.util.Collections;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+import java.util.TreeSet;
+import java.util.WeakHashMap;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.CopyOnWriteArraySet;
+
+import org.apache.felix.gogo.api.CommandSessionListener;
+import org.apache.felix.service.command.CommandProcessor;
+import org.apache.felix.service.command.CommandSession;
+import org.apache.felix.service.command.Converter;
+import org.apache.felix.service.command.Function;
+import org.apache.felix.service.threadio.ThreadIO;
+
+/**
+ * TODO: remove this class when upgraded to gogo-runtime >= 0.12.2, see FELIX-4637 / KARAF-3221
+ */
+public class CommandProcessorImpl implements CommandProcessor
+{
+    protected final Set<Converter> converters = new CopyOnWriteArraySet<Converter>();
+    protected final Set<CommandSessionListener> listeners = new CopyOnWriteArraySet<CommandSessionListener>();
+    protected final ConcurrentMap<String, Map<Object, Integer>> commands = new ConcurrentHashMap<String, Map<Object, Integer>>();
+    protected final Map<String, Object> constants = new ConcurrentHashMap<String, Object>();
+    protected final ThreadIO threadIO;
+    protected final WeakHashMap<CommandSession, Object> sessions = new WeakHashMap<CommandSession, Object>();
+    protected boolean stopped;
+
+    public CommandProcessorImpl(ThreadIO tio)
+    {
+        threadIO = tio;
+    }
+
+    public CommandSession createSession(InputStream in, PrintStream out, PrintStream err)
+    {
+        synchronized (sessions)
+        {
+            if (stopped) {
+                throw new IllegalStateException("CommandProcessor has been stopped");
+            }
+            CommandSessionImpl session = new CommandSessionImpl(this, in, out, err);
+            sessions.put(session, null);
+            return session;
+        }
+    }
+
+    public void stop()
+    {
+        synchronized (sessions)
+        {
+            stopped = true;
+            for (CommandSession session : sessions.keySet())
+            {
+                session.close();
+            }
+        }
+    }
+
+    public void addConverter(Converter c)
+    {
+        converters.add(c);
+    }
+
+    public void removeConverter(Converter c)
+    {
+        converters.remove(c);
+    }
+
+    public void addListener(CommandSessionListener l)
+    {
+        listeners.add(l);
+    }
+
+    public void removeListener(CommandSessionListener l)
+    {
+        listeners.remove(l);
+    }
+
+    public Set<String> getCommands()
+    {
+        return Collections.unmodifiableSet(commands.keySet());
+    }
+
+    Function getCommand(String name, final Object path)
+    {
+        int colon = name.indexOf(':');
+
+        if (colon < 0)
+        {
+            return null;
+        }
+
+        name = name.toLowerCase();
+        String cfunction = name.substring(colon);
+        boolean anyScope = (colon == 1 && name.charAt(0) == '*');
+
+        Map<Object, Integer> cmdMap = commands.get(name);
+
+        if (null == cmdMap && anyScope)
+        {
+            String scopePath = (null == path ? "*" : path.toString());
+
+            for (String scope : scopePath.split(":"))
+            {
+                if (scope.equals("*"))
+                {
+                    for (Entry<String, Map<Object, Integer>> entry : commands.entrySet())
+                    {
+                        if (entry.getKey().endsWith(cfunction))
+                        {
+                            cmdMap = entry.getValue();
+                            break;
+                        }
+                    }
+                }
+                else
+                {
+                    cmdMap = commands.get(scope + cfunction);
+                    if (cmdMap != null)
+                    {
+                        break;
+                    }
+                }
+            }
+        }
+
+        Object cmd = null;
+        if (cmdMap != null && !cmdMap.isEmpty())
+        {
+            for (Entry<Object, Integer> e : cmdMap.entrySet())
+            {
+                if (cmd == null || e.getValue() > cmdMap.get(cmd))
+                {
+                    cmd = e.getKey();
+                }
+            }
+        }
+        if ((null == cmd) || (cmd instanceof Function))
+        {
+            return (Function) cmd;
+        }
+
+        return new CommandProxy(cmd, cfunction.substring(1));
+    }
+
+    public void addCommand(String scope, Object target)
+    {
+        Class<?> tc = (target instanceof Class<?>) ? (Class<?>) target
+            : target.getClass();
+        addCommand(scope, target, tc);
+    }
+
+    public void addCommand(String scope, Object target, Class<?> functions)
+    {
+        addCommand(scope, target, functions, 0);
+    }
+
+    public void addCommand(String scope, Object target, Class<?> functions, int ranking)
+    {
+        if (target == null)
+        {
+            return;
+        }
+
+        String[] names = getFunctions(functions);
+        for (String function : names)
+        {
+            addCommand(scope, target, function, ranking);
+        }
+    }
+
+    public Object addConstant(String name, Object target)
+    {
+        return constants.put(name, target);
+    }
+
+    public Object removeConstant(String name)
+    {
+        return constants.remove(name);
+    }
+
+    public void addCommand(String scope, Object target, String function)
+    {
+        addCommand(scope, target, function, 0);
+    }
+
+    public void addCommand(String scope, Object target, String function, int ranking)
+    {
+        String key = (scope + ":" + function).toLowerCase();
+        Map<Object, Integer> cmdMap = commands.get(key);
+        if (cmdMap == null)
+        {
+            commands.putIfAbsent(key, new LinkedHashMap<Object, Integer>());
+            cmdMap = commands.get(key);
+        }
+        cmdMap.put(target, ranking);
+    }
+
+    public void removeCommand(String scope, String function)
+    {
+        // TODO: WARNING: this method does remove all mapping for scope:function
+        String key = (scope + ":" + function).toLowerCase();
+        commands.remove(key);
+    }
+
+    public void removeCommand(String scope, String function, Object target)
+    {
+        // TODO: WARNING: this method does remove all mapping for scope:function
+        String key = (scope + ":" + function).toLowerCase();
+        Map<Object, Integer> cmdMap = commands.get(key);
+        if (cmdMap != null)
+        {
+            cmdMap.remove(target);
+        }
+    }
+
+    public void removeCommand(Object target)
+    {
+        for (Map<Object, Integer> cmdMap : commands.values())
+        {
+            cmdMap.remove(target);
+        }
+    }
+
+    private String[] getFunctions(Class<?> target)
+    {
+        String[] functions;
+        Set<String> list = new TreeSet<String>();
+        Method methods[] = target.getMethods();
+        for (Method m : methods)
+        {
+            if (m.getDeclaringClass().equals(Object.class))
+            {
+                continue;
+            }
+            list.add(m.getName());
+            if (m.getName().startsWith("get"))
+            {
+                String s = m.getName().substring(3);
+                if (s.length() > 0)
+                {
+                    list.add(s.substring(0, 1).toLowerCase() + s.substring(1));
+                }
+            }
+        }
+
+        functions = list.toArray(new String[list.size()]);
+        return functions;
+    }
+
+    public Object convert(Class<?> desiredType, Object in)
+    {
+        for (Converter c : converters)
+        {
+            try
+            {
+                Object converted = c.convert(desiredType, in);
+                if (converted != null)
+                {
+                    return converted;
+                }
+            }
+            catch (Exception e)
+            {
+                e.printStackTrace();
+            }
+        }
+        return null;
+    }
+
+    // eval is needed to force expansions to be treated as commands (FELIX-1473)
+    public Object eval(CommandSession session, Object[] argv) throws Exception
+    {
+        StringBuilder buf = new StringBuilder();
+
+        for (Object arg : argv)
+        {
+            if (buf.length() > 0)
+                buf.append(' ');
+            buf.append(arg);
+        }
+
+        return session.execute(buf);
+    }
+
+    void beforeExecute(CommandSession session, CharSequence commandline)
+    {
+        for (CommandSessionListener l : listeners)
+        {
+            try
+            {
+                l.beforeExecute(session, commandline);
+            }
+            catch (Throwable t)
+            {
+                // Ignore
+            }
+        }
+    }
+
+    void afterExecute(CommandSession session, CharSequence commandline,
+        Exception exception)
+    {
+        for (CommandSessionListener l : listeners)
+        {
+            try
+            {
+                l.afterExecute(session, commandline, exception);
+            }
+            catch (Throwable t)
+            {
+                // Ignore
+            }
+        }
+    }
+
+    void afterExecute(CommandSession session, CharSequence commandline, Object result)
+    {
+        for (CommandSessionListener l : listeners)
+        {
+            try
+            {
+                l.afterExecute(session, commandline, result);
+            }
+            catch (Throwable t)
+            {
+                // Ignore
+            }
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/9ad9fd54/shell/console/src/main/java/org/apache/karaf/shell/security/impl/SecuredCommandProcessorImpl.java
----------------------------------------------------------------------
diff --git a/shell/console/src/main/java/org/apache/karaf/shell/security/impl/SecuredCommandProcessorImpl.java b/shell/console/src/main/java/org/apache/karaf/shell/security/impl/SecuredCommandProcessorImpl.java
index 3a83958..0e16a56 100644
--- a/shell/console/src/main/java/org/apache/karaf/shell/security/impl/SecuredCommandProcessorImpl.java
+++ b/shell/console/src/main/java/org/apache/karaf/shell/security/impl/SecuredCommandProcessorImpl.java
@@ -25,6 +25,7 @@ import org.apache.felix.service.command.Converter;
 import org.apache.felix.service.threadio.ThreadIO;
 import org.apache.karaf.jaas.boot.principal.RolePrincipal;
 import org.osgi.framework.BundleContext;
+import org.osgi.framework.Constants;
 import org.osgi.framework.Filter;
 import org.osgi.framework.InvalidSyntaxException;
 import org.osgi.framework.ServiceReference;
@@ -114,8 +115,21 @@ public class SecuredCommandProcessorImpl extends CommandProcessorImpl {
             {
                 Object scope = reference.getProperty(CommandProcessor.COMMAND_SCOPE);
                 Object function = reference.getProperty(CommandProcessor.COMMAND_FUNCTION);
+                Object ranking = reference.getProperty(Constants.SERVICE_RANKING);
                 List<Object> commands = new ArrayList<Object>();
 
+                int rank = 0;
+                if (ranking != null)
+                {
+                    try
+                    {
+                        rank = Integer.parseInt(ranking.toString());
+                    }
+                    catch (NumberFormatException e)
+                    {
+                        // Ignore
+                    }
+                }
                 if (scope != null && function != null)
                 {
                     Map<String, CommandProxy> proxyMap = new HashMap<String, CommandProxy>();
@@ -125,7 +139,7 @@ public class SecuredCommandProcessorImpl extends CommandProcessorImpl {
                         {
                             CommandProxy target = new CommandProxy(context, reference, f.toString());
                             proxyMap.put(f.toString(), target);
-                            addCommand(scope.toString(), target, f.toString());
+                            addCommand(scope.toString(), target, f.toString(), rank);
                             commands.add(target);
                         }
                     }
@@ -133,7 +147,7 @@ public class SecuredCommandProcessorImpl extends CommandProcessorImpl {
                     {
                         CommandProxy target = new CommandProxy(context, reference, function.toString());
                         proxyMap.put(function.toString(), target);
-                        addCommand(scope.toString(), target, function.toString());
+                        addCommand(scope.toString(), target, function.toString(), rank);
                         commands.add(target);
                     }
                     proxies.put(reference, proxyMap);
@@ -153,7 +167,7 @@ public class SecuredCommandProcessorImpl extends CommandProcessorImpl {
                     Map<String, CommandProxy> proxyMap = proxies.remove(reference);
                     for (Map.Entry<String, CommandProxy> entry : proxyMap.entrySet())
                     {
-                        removeCommand(scope.toString(), entry.getKey());
+                        removeCommand(scope.toString(), entry.getKey(), entry.getValue());
                     }
                 }