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 2017/06/02 13:33:16 UTC

[1/2] karaf git commit: Code cleanup

Repository: karaf
Updated Branches:
  refs/heads/master f13b88f7c -> 928a249d5


Code cleanup

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

Branch: refs/heads/master
Commit: 928a249d52701e92fc1d1581fc995766a0b6a8ec
Parents: 58e552c
Author: Guillaume Nodet <gn...@apache.org>
Authored: Fri Jun 2 15:28:04 2017 +0200
Committer: Guillaume Nodet <gn...@apache.org>
Committed: Fri Jun 2 15:33:08 2017 +0200

----------------------------------------------------------------------
 .../org/apache/karaf/shell/ssh/Activator.java   |  8 ++---
 .../karaf/shell/ssh/KarafJaasAuthenticator.java | 36 +++++++++----------
 .../karaf/shell/ssh/ServerKeyVerifierImpl.java  |  2 +-
 .../apache/karaf/shell/ssh/ShellCommand.java    | 18 +++++-----
 .../karaf/shell/ssh/ShellCommandFactory.java    | 37 --------------------
 5 files changed, 29 insertions(+), 72 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/karaf/blob/928a249d/shell/ssh/src/main/java/org/apache/karaf/shell/ssh/Activator.java
----------------------------------------------------------------------
diff --git a/shell/ssh/src/main/java/org/apache/karaf/shell/ssh/Activator.java b/shell/ssh/src/main/java/org/apache/karaf/shell/ssh/Activator.java
index ab254aa..8725079 100644
--- a/shell/ssh/src/main/java/org/apache/karaf/shell/ssh/Activator.java
+++ b/shell/ssh/src/main/java/org/apache/karaf/shell/ssh/Activator.java
@@ -21,7 +21,7 @@ package org.apache.karaf.shell.ssh;
 import java.io.File;
 import java.io.IOException;
 import java.nio.file.Paths;
-import java.util.Arrays;
+import java.util.Collections;
 
 import org.apache.karaf.shell.api.action.lifecycle.Manager;
 import org.apache.karaf.shell.api.console.CommandLoggingFilter;
@@ -184,8 +184,8 @@ public class Activator extends BaseActivator implements ManagedService {
         server.setCipherFactories(SshUtils.buildCiphers(ciphers));
         server.setKeyExchangeFactories(SshUtils.buildKexAlgorithms(kexAlgorithms));
         server.setShellFactory(new ShellFactoryImpl(sessionFactory));
-        server.setCommandFactory(new ScpCommandFactory.Builder().withDelegate(new ShellCommandFactory(sessionFactory)).build());
-        server.setSubsystemFactories(Arrays.asList(new SftpSubsystemFactory()));
+        server.setCommandFactory(new ScpCommandFactory.Builder().withDelegate(cmd -> new ShellCommand(sessionFactory, cmd)).build());
+        server.setSubsystemFactories(Collections.singletonList(new SftpSubsystemFactory()));
         server.setKeyPairProvider(keyPairProvider);
         server.setPasswordAuthenticator(authenticator);
         server.setPublickeyAuthenticator(authenticator);
@@ -194,7 +194,7 @@ public class Activator extends BaseActivator implements ManagedService {
         server.setAgentFactory(KarafAgentFactory.getInstance());
         server.setTcpipForwardingFilter(AcceptAllForwardingFilter.INSTANCE);
         server.getProperties().put(SshServer.IDLE_TIMEOUT, Long.toString(sshIdleTimeout));
-        server.getProperties().put(SshServer.NIO_WORKERS, new Integer(nioWorkers).toString());
+        server.getProperties().put(SshServer.NIO_WORKERS, Integer.toString(nioWorkers));
         if (moduliUrl != null) {
             server.getProperties().put(SshServer.MODULI_URL, moduliUrl);
         }

http://git-wip-us.apache.org/repos/asf/karaf/blob/928a249d/shell/ssh/src/main/java/org/apache/karaf/shell/ssh/KarafJaasAuthenticator.java
----------------------------------------------------------------------
diff --git a/shell/ssh/src/main/java/org/apache/karaf/shell/ssh/KarafJaasAuthenticator.java b/shell/ssh/src/main/java/org/apache/karaf/shell/ssh/KarafJaasAuthenticator.java
index b6d1034..48a1096 100644
--- a/shell/ssh/src/main/java/org/apache/karaf/shell/ssh/KarafJaasAuthenticator.java
+++ b/shell/ssh/src/main/java/org/apache/karaf/shell/ssh/KarafJaasAuthenticator.java
@@ -65,16 +65,14 @@ public class KarafJaasAuthenticator implements PasswordAuthenticator, PublickeyA
     public boolean authenticate(final String username, final String password, final ServerSession session) {
         try {
             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(username);
-                        } else if (callback instanceof PasswordCallback) {
-                            ((PasswordCallback) callback).setPassword(password.toCharArray());
-                        } else {
-                            throw new UnsupportedCallbackException(callback);
-                        }
+            LoginContext loginContext = new LoginContext(realm, subject, callbacks -> {
+                for (Callback callback : callbacks) {
+                    if (callback instanceof NameCallback) {
+                        ((NameCallback) callback).setName(username);
+                    } else if (callback instanceof PasswordCallback) {
+                        ((PasswordCallback) callback).setPassword(password.toCharArray());
+                    } else {
+                        throw new UnsupportedCallbackException(callback);
                     }
                 }
             });
@@ -102,16 +100,14 @@ public class KarafJaasAuthenticator implements PasswordAuthenticator, PublickeyA
     public boolean authenticate(final String username, final PublicKey key, final ServerSession session) {
         try {
             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(username);
-                        } else if (callback instanceof PublickeyCallback) {
-                            ((PublickeyCallback) callback).setPublicKey(key);
-                        } else {
-                            throw new UnsupportedCallbackException(callback);
-                        }
+            LoginContext loginContext = new LoginContext(realm, subject, callbacks -> {
+                for (Callback callback : callbacks) {
+                    if (callback instanceof NameCallback) {
+                        ((NameCallback) callback).setName(username);
+                    } else if (callback instanceof PublickeyCallback) {
+                        ((PublickeyCallback) callback).setPublicKey(key);
+                    } else {
+                        throw new UnsupportedCallbackException(callback);
                     }
                 }
             });

http://git-wip-us.apache.org/repos/asf/karaf/blob/928a249d/shell/ssh/src/main/java/org/apache/karaf/shell/ssh/ServerKeyVerifierImpl.java
----------------------------------------------------------------------
diff --git a/shell/ssh/src/main/java/org/apache/karaf/shell/ssh/ServerKeyVerifierImpl.java b/shell/ssh/src/main/java/org/apache/karaf/shell/ssh/ServerKeyVerifierImpl.java
index 6973ad6..0d471b4 100644
--- a/shell/ssh/src/main/java/org/apache/karaf/shell/ssh/ServerKeyVerifierImpl.java
+++ b/shell/ssh/src/main/java/org/apache/karaf/shell/ssh/ServerKeyVerifierImpl.java
@@ -32,7 +32,7 @@ public class ServerKeyVerifierImpl implements ServerKeyVerifier {
 	private final boolean quiet;
 
     private final static String keyChangedMessage =
-            " @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ \n" +
+            		" @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ \n" +
                     " @    WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!      @ \n" +
                     " @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ \n" +
                     "IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!\n" +

http://git-wip-us.apache.org/repos/asf/karaf/blob/928a249d/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 2b3d507..daa4ecc 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
@@ -44,7 +44,7 @@ import org.apache.sshd.server.session.ServerSession;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-public class ShellCommand implements Command, Runnable, SessionAware {
+public class ShellCommand implements Command, SessionAware {
 
     public static final String SHELL_INIT_SCRIPT = "karaf.shell.init.script";
     public static final String EXEC_INIT_SCRIPT = "karaf.exec.init.script";
@@ -93,7 +93,7 @@ public class ShellCommand implements Command, Runnable, SessionAware {
 
     public void start(final Environment env) throws IOException {
         this.env = env;
-        new Thread(this).start();
+        new Thread(this::run).start();
     }
 
     public void run() {
@@ -108,15 +108,13 @@ public class ShellCommand implements Command, Runnable, SessionAware {
                 Object result;
                 if (subject != null) {
                     try {
-                        result = JaasHelper.doAs(subject, new PrivilegedExceptionAction<Object>() {
-                            public Object run() throws Exception {
-                                String scriptFileName = System.getProperty(EXEC_INIT_SCRIPT);
-                                if (scriptFileName == null) {
-                                    scriptFileName = System.getProperty(SHELL_INIT_SCRIPT);
-                                }
-                                executeScript(scriptFileName, session);
-                                return session.execute(command);
+                        result = JaasHelper.doAs(subject, (PrivilegedExceptionAction<Object>) () -> {
+                            String scriptFileName = System.getProperty(EXEC_INIT_SCRIPT);
+                            if (scriptFileName == null) {
+                                scriptFileName = System.getProperty(SHELL_INIT_SCRIPT);
                             }
+                            executeScript(scriptFileName, session);
+                            return session.execute(command);
                         });
                     } catch (PrivilegedActionException e) {
                         throw e.getException();

http://git-wip-us.apache.org/repos/asf/karaf/blob/928a249d/shell/ssh/src/main/java/org/apache/karaf/shell/ssh/ShellCommandFactory.java
----------------------------------------------------------------------
diff --git a/shell/ssh/src/main/java/org/apache/karaf/shell/ssh/ShellCommandFactory.java b/shell/ssh/src/main/java/org/apache/karaf/shell/ssh/ShellCommandFactory.java
deleted file mode 100644
index dc1f04e..0000000
--- a/shell/ssh/src/main/java/org/apache/karaf/shell/ssh/ShellCommandFactory.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.shell.ssh;
-
-import org.apache.karaf.shell.api.console.SessionFactory;
-import org.apache.sshd.server.Command;
-import org.apache.sshd.server.CommandFactory;
-
-public class ShellCommandFactory implements CommandFactory {
-
-    private SessionFactory sessionFactory;
-
-    public ShellCommandFactory(SessionFactory sessionFactory) {
-        this.sessionFactory = sessionFactory;
-    }
-
-    public Command createCommand(String command) {
-        return new ShellCommand(sessionFactory, command);
-    }
-
-}


[2/2] karaf git commit: [KARAF-5143] Command cannot be executed via SSH when property "karaf.shell.init.script" (etc/system.properties) has its default value

Posted by gn...@apache.org.
[KARAF-5143] Command cannot be executed via SSH when property "karaf.shell.init.script" (etc/system.properties) has its default value

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

Branch: refs/heads/master
Commit: 58e552cc4e1c84cbd07655057ed969fc8ce1edc9
Parents: f13b88f
Author: Guillaume Nodet <gn...@apache.org>
Authored: Fri Jun 2 15:17:09 2017 +0200
Committer: Guillaume Nodet <gn...@apache.org>
Committed: Fri Jun 2 15:33:08 2017 +0200

----------------------------------------------------------------------
 shell/core/pom.xml                              |   1 +
 .../shell/impl/console/ConsoleSessionImpl.java  |   1 +
 .../karaf/shell/impl/console/FilesStream.java   | 156 ------------------
 shell/ssh/pom.xml                               |   1 +
 .../apache/karaf/shell/ssh/ShellCommand.java    |  44 ++----
 .../karaf/util/filesstream/FilesStream.java     | 157 +++++++++++++++++++
 6 files changed, 175 insertions(+), 185 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/karaf/blob/58e552cc/shell/core/pom.xml
----------------------------------------------------------------------
diff --git a/shell/core/pom.xml b/shell/core/pom.xml
index e8bdbe0..6c83e11 100644
--- a/shell/core/pom.xml
+++ b/shell/core/pom.xml
@@ -150,6 +150,7 @@
                             org.apache.karaf.service.guard.tools,
                             org.apache.karaf.shell.impl.*,
                             org.apache.karaf.util,
+                            org.apache.karaf.util.filesstream,
                             org.apache.karaf.util.jaas,
                             org.apache.karaf.util.tracker,
                             org.apache.felix.utils.properties,

http://git-wip-us.apache.org/repos/asf/karaf/blob/58e552cc/shell/core/src/main/java/org/apache/karaf/shell/impl/console/ConsoleSessionImpl.java
----------------------------------------------------------------------
diff --git a/shell/core/src/main/java/org/apache/karaf/shell/impl/console/ConsoleSessionImpl.java b/shell/core/src/main/java/org/apache/karaf/shell/impl/console/ConsoleSessionImpl.java
index 5f1d7aa..f0a8569 100644
--- a/shell/core/src/main/java/org/apache/karaf/shell/impl/console/ConsoleSessionImpl.java
+++ b/shell/core/src/main/java/org/apache/karaf/shell/impl/console/ConsoleSessionImpl.java
@@ -57,6 +57,7 @@ import org.apache.karaf.shell.support.ShellUtil;
 import org.apache.karaf.shell.support.completers.FileCompleter;
 import org.apache.karaf.shell.support.completers.FileOrUriCompleter;
 import org.apache.karaf.shell.support.completers.UriCompleter;
+import org.apache.karaf.util.filesstream.FilesStream;
 import org.jline.builtins.Completers;
 import org.jline.reader.Completer;
 import org.jline.reader.EndOfFileException;

http://git-wip-us.apache.org/repos/asf/karaf/blob/58e552cc/shell/core/src/main/java/org/apache/karaf/shell/impl/console/FilesStream.java
----------------------------------------------------------------------
diff --git a/shell/core/src/main/java/org/apache/karaf/shell/impl/console/FilesStream.java b/shell/core/src/main/java/org/apache/karaf/shell/impl/console/FilesStream.java
deleted file mode 100644
index 496945e..0000000
--- a/shell/core/src/main/java/org/apache/karaf/shell/impl/console/FilesStream.java
+++ /dev/null
@@ -1,156 +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.impl.console;
-
-import java.io.IOException;
-import java.nio.file.FileVisitOption;
-import java.nio.file.FileVisitResult;
-import java.nio.file.FileVisitor;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.PathMatcher;
-import java.nio.file.Paths;
-import java.nio.file.attribute.BasicFileAttributes;
-import java.util.ArrayList;
-import java.util.EnumSet;
-import java.util.List;
-import java.util.stream.Stream;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-final class FilesStream {
-	private static final Logger LOGGER = LoggerFactory.getLogger(ConsoleSessionImpl.class);
-
-    private FilesStream() {
-	}
-
-    /**
-     * Returns a stream of Paths for the given fileNames.
-     * The given names can be delimited by ",". A name can also contain
-     * {@link java.nio.file.FileSystem#getPathMatcher} syntax to refer to matching files.  
-     * 
-     * @param fileNames list of names 
-     * @return Paths to the scripts 
-     */
-	static Stream<Path> stream(String fileNames) {
-        if (fileNames == null) {
-            return Stream.empty();
-        }
-        List<String> files = new ArrayList<>();
-        List<String> generators = new ArrayList<>();
-        StringBuilder buf = new StringBuilder(fileNames.length());
-        boolean hasUnescapedReserved = false;
-        boolean escaped = false;
-        for (int i = 0; i < fileNames.length(); i++) {
-            char c = fileNames.charAt(i);
-            if (escaped) {
-                buf.append(c);
-                escaped = false;
-            } else if (c == '\\') {
-                escaped = true;
-            } else if (c == ',') {
-                if (hasUnescapedReserved) {
-                    generators.add(buf.toString());
-                } else {
-                    files.add(buf.toString());
-                }
-                hasUnescapedReserved = false;
-                buf.setLength(0);
-            } else if ("*?{[".indexOf(c) >= 0) {
-                hasUnescapedReserved = true;
-                buf.append(c);
-            } else {
-                buf.append(c);
-            }
-        }
-        if (buf.length() > 0) {
-            if (hasUnescapedReserved) {
-                generators.add(buf.toString());
-            } else {
-                files.add(buf.toString());
-            }
-        }
-        Path cur = Paths.get(System.getProperty("karaf.base"));
-        return Stream.concat(
-                files.stream().map(cur::resolve),
-                generators.stream().flatMap(s -> files(cur, s)));
-    }
-
-    private static Stream<Path> files(Path cur, String glob) {
-        String prefix;
-        String rem;
-        int idx = glob.lastIndexOf('/');
-        if (idx >= 0) {
-            prefix = glob.substring(0, idx + 1);
-            rem = glob.substring(idx + 1);
-        } else {
-            prefix = "";
-            rem = glob;
-        }
-        Path dir = cur.resolve(prefix);
-        final PathMatcher matcher = dir.getFileSystem().getPathMatcher("glob:" + rem);
-        Stream.Builder<Path> stream = Stream.builder();
-        try {
-            Files.walkFileTree(dir,
-                    EnumSet.of(FileVisitOption.FOLLOW_LINKS),
-                    Integer.MAX_VALUE,
-                    new FileVisitor<Path>() {
-                        @Override
-                        public FileVisitResult preVisitDirectory(Path file, BasicFileAttributes attrs) throws IOException {
-                            if (file.equals(dir)) {
-                                return FileVisitResult.CONTINUE;
-                            }
-                            if (Files.isHidden(file)) {
-                                return FileVisitResult.SKIP_SUBTREE;
-                            }
-                            Path r = dir.relativize(file);
-                            if (matcher.matches(r)) {
-                                stream.add(file);
-                            }
-                            return FileVisitResult.CONTINUE;
-                        }
-
-                        @Override
-                        public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
-                            if (!Files.isHidden(file)) {
-                                Path r = dir.relativize(file);
-                                if (matcher.matches(r)) {
-                                    stream.add(file);
-                                }
-                            }
-                            return FileVisitResult.CONTINUE;
-                        }
-
-                        @Override
-                        public FileVisitResult visitFileFailed(Path file, IOException exc) throws IOException {
-                            return FileVisitResult.CONTINUE;
-                        }
-
-                        @Override
-                        public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {
-                            return FileVisitResult.CONTINUE;
-                        }
-                    });
-        } catch (IOException e) {
-            LOGGER.warn("Error generating filenames", e);
-        }
-        return stream.build();
-    }
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/58e552cc/shell/ssh/pom.xml
----------------------------------------------------------------------
diff --git a/shell/ssh/pom.xml b/shell/ssh/pom.xml
index e7cfed1..abf5678 100644
--- a/shell/ssh/pom.xml
+++ b/shell/ssh/pom.xml
@@ -142,6 +142,7 @@
                         </Import-Package>
                         <Private-Package>
                             org.apache.karaf.util,
+                            org.apache.karaf.util.filesstream,
                             org.apache.karaf.util.jaas,
                         </Private-Package>
                     </instructions>

http://git-wip-us.apache.org/repos/asf/karaf/blob/58e552cc/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 f85ec3a..2b3d507 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,15 +18,12 @@
  */
 package org.apache.karaf.shell.ssh;
 
-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.nio.file.Files;
+import java.nio.file.Path;
 import java.security.PrivilegedActionException;
 import java.security.PrivilegedExceptionAction;
 import java.util.Map;
@@ -37,6 +34,7 @@ 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.filesstream.FilesStream;
 import org.apache.karaf.util.jaas.JaasHelper;
 import org.apache.sshd.server.Command;
 import org.apache.sshd.server.Environment;
@@ -152,30 +150,18 @@ public class ShellCommand implements Command, Runnable, SessionAware {
     public void destroy() {
 	}
 
-    private void executeScript(String scriptFileName, Session session) {
-        if (scriptFileName != null) {
-            Reader r = null;
-            try {
-                File scriptFile = new File(scriptFileName);
-                r = new InputStreamReader(new FileInputStream(scriptFile));
-                CharArrayWriter w = new CharArrayWriter();
-                int n;
-                char[] buf = new char[8192];
-                while ((n = r.read(buf)) > 0) {
-                    w.write(buf, 0, n);
-                }
-                session.execute(new String(w.toCharArray()));
-            } catch (Exception e) {
-                LOGGER.debug("Error in initialization script", e);
-            } finally {
-                if (r != null) {
-                    try {
-                        r.close();
-                    } catch (IOException e) {
-                        // Ignore
-                    }
-                }
-            }
+    private void executeScript(String names, Session session) {
+        FilesStream.stream(names).forEach(p -> doExecuteScript(session, p));
+    }
+
+    private void doExecuteScript(Session session, Path scriptFileName) {
+        try {
+            String script = String.join("\n",
+                    Files.readAllLines(scriptFileName));
+            session.execute(script);
+        } catch (Exception e) {
+            LOGGER.debug("Error in initialization script {}", scriptFileName, e);
+            System.err.println("Error in initialization script: " + scriptFileName + ": " + e.getMessage());
         }
     }
 

http://git-wip-us.apache.org/repos/asf/karaf/blob/58e552cc/util/src/main/java/org/apache/karaf/util/filesstream/FilesStream.java
----------------------------------------------------------------------
diff --git a/util/src/main/java/org/apache/karaf/util/filesstream/FilesStream.java b/util/src/main/java/org/apache/karaf/util/filesstream/FilesStream.java
new file mode 100644
index 0000000..49d32a8
--- /dev/null
+++ b/util/src/main/java/org/apache/karaf/util/filesstream/FilesStream.java
@@ -0,0 +1,157 @@
+/*
+ * 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.util.filesstream;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.IOException;
+import java.nio.file.FileVisitOption;
+import java.nio.file.FileVisitResult;
+import java.nio.file.FileVisitor;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.PathMatcher;
+import java.nio.file.Paths;
+import java.nio.file.attribute.BasicFileAttributes;
+import java.util.ArrayList;
+import java.util.EnumSet;
+import java.util.List;
+import java.util.stream.Stream;
+
+public final class FilesStream {
+
+	private static final Logger LOGGER = LoggerFactory.getLogger(FilesStream.class);
+
+    private FilesStream() {
+	}
+
+    /**
+     * Returns a stream of Paths for the given fileNames.
+     * The given names can be delimited by ",". A name can also contain
+     * {@link java.nio.file.FileSystem#getPathMatcher} syntax to refer to matching files.  
+     * 
+     * @param fileNames list of names 
+     * @return Paths to the scripts 
+     */
+	public static Stream<Path> stream(String fileNames) {
+        if (fileNames == null) {
+            return Stream.empty();
+        }
+        List<String> files = new ArrayList<>();
+        List<String> generators = new ArrayList<>();
+        StringBuilder buf = new StringBuilder(fileNames.length());
+        boolean hasUnescapedReserved = false;
+        boolean escaped = false;
+        for (int i = 0; i < fileNames.length(); i++) {
+            char c = fileNames.charAt(i);
+            if (escaped) {
+                buf.append(c);
+                escaped = false;
+            } else if (c == '\\') {
+                escaped = true;
+            } else if (c == ',') {
+                if (hasUnescapedReserved) {
+                    generators.add(buf.toString());
+                } else {
+                    files.add(buf.toString());
+                }
+                hasUnescapedReserved = false;
+                buf.setLength(0);
+            } else if ("*?{[".indexOf(c) >= 0) {
+                hasUnescapedReserved = true;
+                buf.append(c);
+            } else {
+                buf.append(c);
+            }
+        }
+        if (buf.length() > 0) {
+            if (hasUnescapedReserved) {
+                generators.add(buf.toString());
+            } else {
+                files.add(buf.toString());
+            }
+        }
+        Path cur = Paths.get(System.getProperty("karaf.base"));
+        return Stream.concat(
+                files.stream().map(cur::resolve),
+                generators.stream().flatMap(s -> files(cur, s)));
+    }
+
+    private static Stream<Path> files(Path cur, String glob) {
+        String prefix;
+        String rem;
+        int idx = glob.lastIndexOf('/');
+        if (idx >= 0) {
+            prefix = glob.substring(0, idx + 1);
+            rem = glob.substring(idx + 1);
+        } else {
+            prefix = "";
+            rem = glob;
+        }
+        Path dir = cur.resolve(prefix);
+        final PathMatcher matcher = dir.getFileSystem().getPathMatcher("glob:" + rem);
+        Stream.Builder<Path> stream = Stream.builder();
+        try {
+            Files.walkFileTree(dir,
+                    EnumSet.of(FileVisitOption.FOLLOW_LINKS),
+                    Integer.MAX_VALUE,
+                    new FileVisitor<Path>() {
+                        @Override
+                        public FileVisitResult preVisitDirectory(Path file, BasicFileAttributes attrs) throws IOException {
+                            if (file.equals(dir)) {
+                                return FileVisitResult.CONTINUE;
+                            }
+                            if (Files.isHidden(file)) {
+                                return FileVisitResult.SKIP_SUBTREE;
+                            }
+                            Path r = dir.relativize(file);
+                            if (matcher.matches(r)) {
+                                stream.add(file);
+                            }
+                            return FileVisitResult.CONTINUE;
+                        }
+
+                        @Override
+                        public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
+                            if (!Files.isHidden(file)) {
+                                Path r = dir.relativize(file);
+                                if (matcher.matches(r)) {
+                                    stream.add(file);
+                                }
+                            }
+                            return FileVisitResult.CONTINUE;
+                        }
+
+                        @Override
+                        public FileVisitResult visitFileFailed(Path file, IOException exc) throws IOException {
+                            return FileVisitResult.CONTINUE;
+                        }
+
+                        @Override
+                        public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {
+                            return FileVisitResult.CONTINUE;
+                        }
+                    });
+        } catch (IOException e) {
+            LOGGER.warn("Error generating filenames", e);
+        }
+        return stream.build();
+    }
+}