Move ServiceMix Kernel trunk into Felix
git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@768912 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/karaf/gshell/gshell-core/pom.xml b/karaf/gshell/gshell-core/pom.xml
new file mode 100644
index 0000000..19e9a27
--- /dev/null
+++ b/karaf/gshell/gshell-core/pom.xml
@@ -0,0 +1,480 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+
+ <!--
+
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.apache.servicemix.kernel.gshell</groupId>
+ <artifactId>gshell</artifactId>
+ <version>1.2.0-SNAPSHOT</version>
+ </parent>
+
+ <groupId>org.apache.servicemix.kernel.gshell</groupId>
+ <artifactId>org.apache.servicemix.kernel.gshell.core</artifactId>
+ <packaging>bundle</packaging>
+ <version>1.2.0-SNAPSHOT</version>
+ <name>Apache ServiceMix Kernel :: GShell Core</name>
+
+ <description>
+ Provides the OSGi GShell integration
+ </description>
+
+ <properties>
+ <gshell.osgi.import>
+ org.springframework.aop,
+ org.springframework.aop.framework,
+ org.springframework.beans.factory.annotation,
+ org.springframework.context.annotation,
+ org.springframework.osgi.service.importer,
+ org.aopalliance.aop,
+ org.apache.commons.vfs.provider.temp,
+ org.apache.commons.vfs.provider.ram,
+ jline*,
+ org.apache.servicemix.kernel.jaas.config;resolution:=optional,
+ org.apache.servicemix.kernel.version;resolution:=optional,
+ org.apache.servicemix.kernel.main.spi;resolution:=optional;version="1.0.0",
+ org.codehaus.plexus*;resolution:=optional,
+ org.apache.sshd.server.keyprovider,
+ org.apache.sshd.server.jaas,
+ org.jsecurity*;resolution:=optional,
+ *
+ </gshell.osgi.import>
+ <!-- TODO: remove plexus util package -->
+ <gshell.osgi.export>
+ org.apache.geronimo.gshell*;version="1.0.0.alpha-2-SNAPSHOT";-split-package:=merge-first,
+ org.apache.servicemix.kernel.gshell.core*,
+ org.codehaus.plexus.interpolation*;-split-package:=merge-first,
+ org.codehaus.plexus.util;-split-package:=merge-first
+ </gshell.osgi.export>
+ </properties>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.servicemix.kernel</groupId>
+ <artifactId>org.apache.servicemix.kernel.main</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.servicemix.kernel.jaas</groupId>
+ <artifactId>org.apache.servicemix.kernel.jaas.config</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.servicemix.bundles</groupId>
+ <artifactId>org.apache.servicemix.bundles.cglib</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework.osgi</groupId>
+ <artifactId>spring-osgi-core</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.geronimo.gshell.commands</groupId>
+ <artifactId>gshell-builtin</artifactId>
+ <exclusions>
+ <exclusion>
+ <groupId>oro</groupId>
+ <artifactId>oro</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>commons-vfs</groupId>
+ <artifactId>commons-vfs</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.geronimo.gshell.commands</groupId>
+ <artifactId>gshell-file</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.geronimo.gshell.commands</groupId>
+ <artifactId>gshell-network</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.geronimo.gshell.commands</groupId>
+ <artifactId>gshell-shell</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.geronimo.gshell.commands</groupId>
+ <artifactId>gshell-ssh</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.geronimo.gshell.commands</groupId>
+ <artifactId>gshell-text</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.geronimo.gshell.wisdom</groupId>
+ <artifactId>gshell-wisdom-core</artifactId>
+ <exclusions>
+ <exclusion>
+ <groupId>org.apache.geronimo.gshell.support</groupId>
+ <artifactId>gshell-ivy</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>org.apache.geronimo.gshell.support</groupId>
+ <artifactId>gshell-xstore</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>commons-jexl</groupId>
+ <artifactId>commons-jexl</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
+ <groupId>org.codehaus.plexus</groupId>
+ <artifactId>plexus-utils</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-context</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-aop</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-jdk14</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.servicemix.bundles</groupId>
+ <artifactId>org.apache.servicemix.bundles.commons-httpclient</artifactId>
+ <exclusions>
+ <exclusion>
+ <groupId>commons-codec</groupId>
+ <artifactId>commons-codec</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.servicemix.bundles</groupId>
+ <artifactId>org.apache.servicemix.bundles.commons-codec</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.servicemix.bundles</groupId>
+ <artifactId>org.apache.servicemix.bundles.commons-jexl</artifactId>
+ <exclusions>
+ <exclusion>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.servicemix.bundles</groupId>
+ <artifactId>org.apache.servicemix.bundles.commons-vfs</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.servicemix.bundles</groupId>
+ <artifactId>org.apache.servicemix.bundles.oro</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.mina</groupId>
+ <artifactId>mina-core</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.sshd</groupId>
+ <artifactId>sshd-core</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.servicemix.bundles</groupId>
+ <artifactId>org.apache.servicemix.bundles.junit</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.servicemix.bundles</groupId>
+ <artifactId>org.apache.servicemix.bundles.jline</artifactId>
+ </dependency>
+
+ <!-- jsecurity is a dependency for the ssh commands -->
+ <dependency>
+ <groupId>org.jsecurity</groupId>
+ <artifactId>jsecurity</artifactId>
+ <version>0.9.0-RC2</version>
+ <exclusions>
+ <exclusion>
+ <groupId>commons-logging</groupId>
+ <artifactId>commons-logging</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <resources>
+ <resource>
+ <directory>${pom.basedir}/src/main/resources</directory>
+ <includes>
+ <include>**/*</include>
+ </includes>
+ </resource>
+ <resource>
+ <directory>${pom.basedir}/src/main/filtered-resources</directory>
+ <filtering>true</filtering>
+ <includes>
+ <include>**/*</include>
+ </includes>
+ </resource>
+ </resources>
+ <plugins>
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>exec-maven-plugin</artifactId>
+ <configuration>
+ <mainClass>Main</mainClass>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+ <configuration>
+ <instructions>
+ <Bundle-SymbolicName>${artifactId}</Bundle-SymbolicName>
+ <Import-Package>${gshell.osgi.import}</Import-Package>
+ <Export-Package>${gshell.osgi.export}</Export-Package>
+ <Spring-Context>*;publish-context:=false;create-asynchronously:=false</Spring-Context>
+ </instructions>
+ <unpackBundle>true</unpackBundle>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-shade-plugin</artifactId>
+ <executions>
+ <execution>
+ <phase>package</phase>
+ <goals>
+ <goal>shade</goal>
+ </goals>
+ <configuration>
+ <artifactSet>
+ <includes>
+ <include>org.apache.geronimo.gshell:gshell-api</include>
+ <include>org.apache.geronimo.gshell:gshell-application</include>
+ <include>org.apache.geronimo.gshell:gshell-parser</include>
+ <include>org.apache.geronimo.gshell.commands:gshell-builtin</include>
+ <include>org.apache.geronimo.gshell.commands:gshell-file</include>
+ <include>org.apache.geronimo.gshell.commands:gshell-network</include>
+ <include>org.apache.geronimo.gshell.commands:gshell-shell</include>
+ <include>org.apache.geronimo.gshell.commands:gshell-text</include>
+ <include>org.apache.geronimo.gshell.support:gshell-ansi</include>
+ <include>org.apache.geronimo.gshell.support:gshell-artifact</include>
+ <include>org.apache.geronimo.gshell.support:gshell-chronos</include>
+ <include>org.apache.geronimo.gshell.support:gshell-clp</include>
+ <include>org.apache.geronimo.gshell.support:gshell-console</include>
+ <include>org.apache.geronimo.gshell.support:gshell-event</include>
+ <include>org.apache.geronimo.gshell.support:gshell-i18n</include>
+ <include>org.apache.geronimo.gshell.support:gshell-interpolation</include>
+ <include>org.apache.geronimo.gshell.support:gshell-io</include>
+ <include>org.apache.geronimo.gshell.support:gshell-security</include>
+ <include>org.apache.geronimo.gshell.support:gshell-spring</include>
+ <include>org.apache.geronimo.gshell.support:gshell-terminal</include>
+ <include>org.apache.geronimo.gshell.support:gshell-vfs</include>
+ <include>org.apache.geronimo.gshell.support:gshell-vfs-meta</include>
+ <include>org.apache.geronimo.gshell.support:gshell-yarn</include>
+ <include>org.apache.geronimo.gshell.wisdom:gshell-wisdom-core</include>
+ <include>org.apache.geronimo.gshell.wisdom:gshell-wisdom-bootstrap</include>
+ <include>org.codehaus.plexus:plexus-utils</include>
+ <include>org.codehaus.plexus:plexus-interpolation</include>
+ <include>${project.groupId}:${project.artifactId}</include>
+ </includes>
+ </artifactSet>
+ <filters>
+ <filter>
+ <artifact>org.apache.geronimo.gshell:gshell-api</artifact>
+ <excludes>
+ <exclude>org/apache/geronimo/gshell/**</exclude>
+ </excludes>
+ </filter>
+ <filter>
+ <artifact>org.apache.geronimo.gshell:gshell-application</artifact>
+ <excludes>
+ <exclude>org/apache/geronimo/gshell/**</exclude>
+ </excludes>
+ </filter>
+ <filter>
+ <artifact>org.apache.geronimo.gshell:gshell-parser</artifact>
+ <excludes>
+ <exclude>org/apache/geronimo/gshell/**</exclude>
+ </excludes>
+ </filter>
+ <filter>
+ <artifact>org.apache.geronimo.gshell.commands:gshell-builtin</artifact>
+ <excludes>
+ <exclude>org/apache/geronimo/gshell/**</exclude>
+ </excludes>
+ </filter>
+ <filter>
+ <artifact>org.apache.geronimo.gshell.commands:gshell-file</artifact>
+ <excludes>
+ <exclude>org/apache/geronimo/gshell/**</exclude>
+ </excludes>
+ </filter>
+ <filter>
+ <artifact>org.apache.geronimo.gshell.commands:gshell-network</artifact>
+ <excludes>
+ <exclude>org/apache/geronimo/gshell/**</exclude>
+ </excludes>
+ </filter>
+ <filter>
+ <artifact>org.apache.geronimo.gshell.commands:gshell-shell</artifact>
+ <excludes>
+ <exclude>org/apache/geronimo/gshell/**</exclude>
+ </excludes>
+ </filter>
+ <filter>
+ <artifact>org.apache.geronimo.gshell.commands:gshell-ssh</artifact>
+ <excludes>
+ <exclude>org/apache/geronimo/gshell/**</exclude>
+ </excludes>
+ </filter>
+ <filter>
+ <artifact>org.apache.geronimo.gshell.commands:gshell-text</artifact>
+ <excludes>
+ <exclude>org/apache/geronimo/gshell/**</exclude>
+ </excludes>
+ </filter>
+ <filter>
+ <artifact>org.apache.geronimo.gshell.support:gshell-ansi</artifact>
+ <excludes>
+ <exclude>org/apache/geronimo/gshell/**</exclude>
+ </excludes>
+ </filter>
+ <filter>
+ <artifact>org.apache.geronimo.gshell.support:gshell-artifact</artifact>
+ <excludes>
+ <exclude>org/apache/geronimo/gshell/**</exclude>
+ </excludes>
+ </filter>
+ <filter>
+ <artifact>org.apache.geronimo.gshell.support:gshell-chronos</artifact>
+ <excludes>
+ <exclude>org/apache/geronimo/gshell/**</exclude>
+ </excludes>
+ </filter>
+ <filter>
+ <artifact>org.apache.geronimo.gshell.support:gshell-clp</artifact>
+ <excludes>
+ <exclude>org/apache/geronimo/gshell/**</exclude>
+ </excludes>
+ </filter>
+ <filter>
+ <artifact>org.apache.geronimo.gshell.support:gshell-console</artifact>
+ <excludes>
+ <exclude>org/apache/geronimo/gshell/**</exclude>
+ </excludes>
+ </filter>
+ <filter>
+ <artifact>org.apache.geronimo.gshell.support:gshell-event</artifact>
+ <excludes>
+ <exclude>org/apache/geronimo/gshell/**</exclude>
+ </excludes>
+ </filter>
+ <filter>
+ <artifact>org.apache.geronimo.gshell.support:gshell-i18n</artifact>
+ <excludes>
+ <exclude>org/apache/geronimo/gshell/**</exclude>
+ </excludes>
+ </filter>
+ <filter>
+ <artifact>org.apache.geronimo.gshell.support:gshell-interpolation</artifact>
+ <excludes>
+ <exclude>org/apache/geronimo/gshell/**</exclude>
+ </excludes>
+ </filter>
+ <filter>
+ <artifact>org.apache.geronimo.gshell.support:gshell-io</artifact>
+ <excludes>
+ <exclude>org/apache/geronimo/gshell/**</exclude>
+ </excludes>
+ </filter>
+ <filter>
+ <artifact>org.apache.geronimo.gshell.support:gshell-security</artifact>
+ <excludes>
+ <exclude>org/apache/geronimo/gshell/**</exclude>
+ </excludes>
+ </filter>
+ <filter>
+ <artifact>org.apache.geronimo.gshell.support:gshell-spring</artifact>
+ <excludes>
+ <exclude>org/apache/geronimo/gshell/**</exclude>
+ </excludes>
+ </filter>
+ <filter>
+ <artifact>org.apache.geronimo.gshell.support:gshell-terminal</artifact>
+ <excludes>
+ <exclude>org/apache/geronimo/gshell/**</exclude>
+ </excludes>
+ </filter>
+ <filter>
+ <artifact>org.apache.geronimo.gshell.support:gshell-vfs</artifact>
+ <excludes>
+ <exclude>org/apache/geronimo/gshell/**</exclude>
+ </excludes>
+ </filter>
+ <filter>
+ <artifact>org.apache.geronimo.gshell.support:gshell-vfs-meta</artifact>
+ <excludes>
+ <exclude>org/apache/geronimo/gshell/**</exclude>
+ </excludes>
+ </filter>
+ <filter>
+ <artifact>org.apache.geronimo.gshell.support:gshell-yarn</artifact>
+ <excludes>
+ <exclude>org/apache/geronimo/gshell/**</exclude>
+ </excludes>
+ </filter>
+ <filter>
+ <artifact>org.apache.geronimo.gshell.wisdom:gshell-wisdom-core</artifact>
+ <excludes>
+ <exclude>org/apache/geronimo/gshell/**</exclude>
+ </excludes>
+ </filter>
+ <filter>
+ <artifact>org.apache.geronimo.gshell.wisdom:gshell-wisdom-bootstrap</artifact>
+ <excludes>
+ <exclude>org/apache/geronimo/gshell/**</exclude>
+ </excludes>
+ </filter>
+ <filter>
+ <artifact>org.codehaus.plexus:plexus-utils</artifact>
+ <excludes>
+ <exclude>org/codehaus/plexus/**</exclude>
+ </excludes>
+ </filter>
+ <filter>
+ <artifact>org.codehaus.plexus:plexus-interpolation</artifact>
+ <excludes>
+ <exclude>org/codehaus/plexus/**</exclude>
+ </excludes>
+ </filter>
+ </filters>
+ <createSourcesJar>${createSourcesJar}</createSourcesJar>
+ <promoteTransitiveDependencies>true</promoteTransitiveDependencies>
+ <createDependencyReducedPom>true</createDependencyReducedPom>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+</project>
diff --git a/karaf/gshell/gshell-core/src/main/filtered-resources/org/apache/servicemix/kernel/gshell/core/servicemix-version.properties b/karaf/gshell/gshell-core/src/main/filtered-resources/org/apache/servicemix/kernel/gshell/core/servicemix-version.properties
new file mode 100644
index 0000000..1fc0355
--- /dev/null
+++ b/karaf/gshell/gshell-core/src/main/filtered-resources/org/apache/servicemix/kernel/gshell/core/servicemix-version.properties
@@ -0,0 +1,20 @@
+##
+## 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.
+##
+
+version=${pom.version}
diff --git a/karaf/gshell/gshell-core/src/main/java/org/apache/geronimo/gshell/commands/shell/FindAction.java b/karaf/gshell/gshell-core/src/main/java/org/apache/geronimo/gshell/commands/shell/FindAction.java
new file mode 100644
index 0000000..203e340
--- /dev/null
+++ b/karaf/gshell/gshell-core/src/main/java/org/apache/geronimo/gshell/commands/shell/FindAction.java
@@ -0,0 +1,208 @@
+/*
+ * 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.geronimo.gshell.commands.shell;
+
+import java.net.URI;
+
+import org.apache.commons.vfs.FileObject;
+import org.apache.commons.vfs.FileSelectInfo;
+import org.apache.commons.vfs.FileSelector;
+import org.apache.commons.vfs.FileSystemException;
+import org.apache.commons.vfs.FileType;
+import org.apache.geronimo.gshell.clp.Argument;
+import org.apache.geronimo.gshell.clp.Option;
+import org.apache.geronimo.gshell.command.CommandAction;
+import org.apache.geronimo.gshell.command.CommandContext;
+import org.apache.geronimo.gshell.io.IO;
+import org.apache.geronimo.gshell.vfs.FileObjects;
+import org.apache.geronimo.gshell.vfs.selector.AggregateFileSelector;
+import org.apache.geronimo.gshell.vfs.support.VfsActionSupport;
+import org.apache.oro.text.GlobCompiler;
+import org.apache.oro.text.regex.MalformedPatternException;
+import org.apache.oro.text.regex.Pattern;
+import org.apache.oro.text.regex.PatternCompiler;
+import org.apache.oro.text.regex.PatternMatcher;
+import org.apache.oro.text.regex.Perl5Matcher;
+
+/**
+ * Find files in a hierarchy.
+ *
+ * TODO: remove this file when gshell is upgraded
+ *
+ * @version $Rev: 722797 $ $Date: 2008-12-03 08:18:16 +0100 (Wed, 03 Dec 2008) $
+ */
+public class FindAction
+ extends VfsActionSupport
+{
+ private final AggregateFileSelector selector = new AggregateFileSelector();
+
+ @Option(name="-name")
+ private void addNameFilter(final String name) throws MalformedPatternException {
+ log.debug("Adding -name selector for: {}", name);
+ selector.getSelectors().add(new NameSelector(name));
+ }
+
+ @Option(name="-iname")
+ private void addiNameFilter(final String name) throws MalformedPatternException {
+ log.debug("Adding -iname selector for: {}", name);
+ selector.getSelectors().add(new NameSelector(name, true));
+ }
+
+ @Option(name="-type")
+ private void addTypeFilter(final Type type) {
+ log.debug("Adding -type selector for: {}", type);
+ selector.getSelectors().add(new TypeSelector(type));
+ }
+
+ @Argument(required=true)
+ private String path;
+
+ public Object execute(final CommandContext context) throws Exception {
+ assert context != null;
+ IO io = context.getIo();
+
+ FileObject root = resolveFile(context, path);
+
+ ensureFileExists(root);
+
+ find(context, root, selector);
+
+ FileObjects.close(root);
+
+ return CommandAction.Result.SUCCESS;
+ }
+
+ private void find(final CommandContext context, final FileObject file, final FileSelector selector) throws FileSystemException {
+ assert context != null;
+ assert file != null;
+ assert selector != null;
+
+ FileObject[] files = file.findFiles(selector);
+
+ if (files != null && files.length != 0) {
+ for (FileObject child : files) {
+ display(context, child, file);
+ }
+ }
+ }
+
+ private void display(final CommandContext context, final FileObject file, final FileObject root) throws FileSystemException {
+ assert context != null;
+ assert file != null;
+
+ String path;
+ try {
+ path = new URI(this.path).resolve(root.getURL().toURI().relativize(file.getURL().toURI())).toString();
+ } catch (Exception e) {
+ path = file.getName().getPath();
+ }
+ IO io = context.getIo();
+ io.info(path);
+ }
+
+ //
+ // Type & TypeSelector
+ //
+
+ private enum Type
+ {
+ F, // normal file
+ D, // directory
+ }
+
+ private class TypeSelector
+ implements FileSelector
+ {
+ private final Type type;
+
+ public TypeSelector(final Type type) {
+ assert type != null;
+
+ this.type = type;
+
+ log.trace("Type: {}", type);
+ }
+
+ public boolean includeFile(final FileSelectInfo selection) throws Exception {
+ assert selection != null;
+
+ FileType ftype = selection.getFile().getType();
+
+ switch (type) {
+ case D:
+ return ftype == FileType.FOLDER;
+
+ case F:
+ return ftype == FileType.FILE;
+
+ // TODO: Handle FileType.FILE_OR_FOLDER
+
+ default:
+ return false;
+ }
+ }
+
+ public boolean traverseDescendents(final FileSelectInfo selection) throws Exception {
+ return true;
+ }
+ }
+
+ //
+ // NameSelector
+ //
+
+ private class NameSelector
+ implements FileSelector
+ {
+ private final Pattern pattern;
+
+ private final PatternMatcher matcher;
+
+ public NameSelector(final String name, final boolean ignoreCase) throws MalformedPatternException {
+ assert name != null;
+
+ PatternCompiler compiler = new GlobCompiler();
+ int options;
+ if (ignoreCase) {
+ options = GlobCompiler.CASE_INSENSITIVE_MASK;
+ }
+ else {
+ options = GlobCompiler.DEFAULT_MASK;
+ }
+ this.pattern = compiler.compile(name, options);
+ this.matcher = new Perl5Matcher();
+
+ log.trace("Pattern: {}", pattern.getPattern());
+ }
+
+ public NameSelector(final String name) throws MalformedPatternException {
+ this(name, false);
+ }
+
+ public boolean includeFile(final FileSelectInfo selection) throws Exception {
+ assert selection != null;
+ return matcher.matches(selection.getFile().getName().getBaseName(), pattern);
+ }
+
+ public boolean traverseDescendents(final FileSelectInfo selection) throws Exception {
+ return true;
+ }
+ }
+}
\ No newline at end of file
diff --git a/karaf/gshell/gshell-core/src/main/java/org/apache/geronimo/gshell/commands/ssh/JSecurityPasswordAuthenticator.java b/karaf/gshell/gshell-core/src/main/java/org/apache/geronimo/gshell/commands/ssh/JSecurityPasswordAuthenticator.java
new file mode 100644
index 0000000..d3bb6de
--- /dev/null
+++ b/karaf/gshell/gshell-core/src/main/java/org/apache/geronimo/gshell/commands/ssh/JSecurityPasswordAuthenticator.java
@@ -0,0 +1,84 @@
+/*
+ * 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.geronimo.gshell.commands.ssh;
+
+import org.apache.sshd.server.PasswordAuthenticator;
+import org.jsecurity.SecurityUtils;
+import org.jsecurity.authc.AuthenticationException;
+import org.jsecurity.authc.UsernamePasswordToken;
+import org.jsecurity.mgt.SecurityManager;
+import org.jsecurity.subject.Subject;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * <a href="http://jsecurity.org">JSecurity</a> {@link PasswordAuthenticator}.
+ *
+ * @version $Rev: 722797 $ $Date: 2008-12-03 08:18:16 +0100 (Wed, 03 Dec 2008) $
+ */
+public class JSecurityPasswordAuthenticator
+ implements PasswordAuthenticator
+{
+ private final Logger log = LoggerFactory.getLogger(getClass());
+
+ private final SecurityManager securityManager;
+
+ public JSecurityPasswordAuthenticator(final SecurityManager securityManager) {
+ // securityManager can be null
+ this.securityManager = securityManager;
+ }
+
+ public JSecurityPasswordAuthenticator() {
+ this(null);
+ }
+
+ public Object authenticate(final String username, final String password) {
+ assert username != null;
+ assert password != null;
+
+ log.debug("Authenticating: {}/{}", username, password);
+
+ Subject currentUser;
+
+ if (securityManager != null) {
+ currentUser = securityManager.getSubject();
+ }
+ else {
+ currentUser = SecurityUtils.getSubject();
+ }
+
+ if (currentUser.isAuthenticated()) {
+ log.debug("Logging out current user: {}", currentUser.getPrincipal());
+ currentUser.logout();
+ }
+
+ try {
+ UsernamePasswordToken token = new UsernamePasswordToken(username, password);
+ currentUser.login(token);
+ Object principal = currentUser.getPrincipal();
+ log.info("User [{}] logged in successfully", principal);
+ return principal;
+ }
+ catch (AuthenticationException e) {
+ log.error("Authentication failed: " + e, e);
+ return null;
+ }
+ }
+}
diff --git a/karaf/gshell/gshell-core/src/main/java/org/apache/geronimo/gshell/commands/ssh/ShellFactoryImpl.java b/karaf/gshell/gshell-core/src/main/java/org/apache/geronimo/gshell/commands/ssh/ShellFactoryImpl.java
new file mode 100644
index 0000000..9795f01
--- /dev/null
+++ b/karaf/gshell/gshell-core/src/main/java/org/apache/geronimo/gshell/commands/ssh/ShellFactoryImpl.java
@@ -0,0 +1,267 @@
+/*
+ * 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.geronimo.gshell.commands.ssh;
+
+import org.apache.sshd.server.ShellFactory;
+import jline.Completor;
+import jline.History;
+import org.apache.geronimo.gshell.command.Variables;
+import org.apache.geronimo.gshell.commandline.CommandLineExecutor;
+import org.apache.geronimo.gshell.console.Console;
+import org.apache.geronimo.gshell.console.JLineConsole;
+import org.apache.geronimo.gshell.console.completer.AggregateCompleter;
+import org.apache.geronimo.gshell.io.Closer;
+import org.apache.geronimo.gshell.io.IO;
+import org.apache.geronimo.gshell.notification.ExitNotification;
+import org.apache.geronimo.gshell.shell.ShellContext;
+import org.apache.geronimo.gshell.shell.ShellContextHolder;
+import org.apache.geronimo.gshell.registry.CommandResolver;
+import org.apache.geronimo.gshell.application.Application;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * SSHD {@link ShellFactory} which provides access to GShell.
+ *
+ * @version $Rev: 731517 $ $Date: 2009-01-05 11:25:19 +0100 (Mon, 05 Jan 2009) $
+ */
+public class ShellFactoryImpl
+ implements ShellFactory
+{
+ private final Logger log = LoggerFactory.getLogger(getClass());
+
+ private Application application;
+
+ private Console.Prompter prompter;
+
+ private CommandLineExecutor executor;
+
+ private History history;
+
+ private List<Completor> completers;
+
+ private Console.ErrorHandler errorHandler;
+
+ public Console.Prompter getPrompter() {
+ return prompter;
+ }
+
+ public void setPrompter(final Console.Prompter prompter) {
+ this.prompter = prompter;
+ }
+
+ public CommandLineExecutor getExecutor() {
+ return executor;
+ }
+
+ public void setExecutor(final CommandLineExecutor executor) {
+ this.executor = executor;
+ }
+
+ public History getHistory() {
+ return history;
+ }
+
+ public void setHistory(final History history) {
+ this.history = history;
+ }
+
+ public List<Completor> getCompleters() {
+ return completers;
+ }
+
+ public void setCompleters(final List<Completor> completers) {
+ this.completers = completers;
+ }
+
+ public Console.ErrorHandler getErrorHandler() {
+ return errorHandler;
+ }
+
+ public void setErrorHandler(final Console.ErrorHandler errorHandler) {
+ this.errorHandler = errorHandler;
+ }
+
+ public Application getApplication() {
+ return application;
+ }
+
+ public void setApplication(Application application) {
+ this.application = application;
+ }
+
+ public Shell createShell() {
+ return new ShellImpl();
+ }
+
+ public class ShellImpl
+ implements ShellFactory.Shell, org.apache.geronimo.gshell.shell.Shell, ShellContext, Runnable
+ {
+ private InputStream in;
+
+ private OutputStream out;
+
+ private OutputStream err;
+
+ private ExitCallback callback;
+
+ private IO io;
+
+ private Variables variables;
+
+ private boolean closed;
+
+ public void setInputStream(final InputStream in) {
+ this.in = in;
+ }
+
+ public void setOutputStream(final OutputStream out) {
+ this.out = out;
+ }
+
+ public void setErrorStream(final OutputStream err) {
+ this.err = err;
+ }
+
+ public void setExitCallback(ExitCallback callback) {
+ this.callback = callback;
+ }
+
+ public void start(final Map<String,String> env) throws IOException {
+ this.io = new IO(in, out, err, false);
+
+ // Create variables, inheriting the application ones
+ this.variables = new Variables(application.getVariables());
+ // Set up additional env
+ if (env != null) {
+ for (Map.Entry<String,String> entry : env.entrySet()) {
+ this.variables.set(entry.getKey(), entry.getValue());
+ }
+ }
+ this.variables.set("gshell.prompt", application.getModel().getBranding().getPrompt());
+ this.variables.set(CommandResolver.GROUP, "/");
+ this.variables.set("gshell.username", env.get("USER"));
+ this.variables.set("gshell.hostname", application.getLocalHost());
+ // HACK: Add history for the 'history' command, since its not part of the Shell intf it can't really access it
+ this.variables.set("gshell.internal.history", getHistory(), true);
+ new Thread(this).start();
+ }
+
+ public void destroy() {
+ close();
+ }
+
+ public ShellContext getContext() {
+ return this;
+ }
+
+ public Object execute(final String line) throws Exception {
+
+ return executor.execute(getContext(), line);
+ }
+
+ public Object execute(final String command, final Object[] args) throws Exception {
+ return executor.execute(getContext(), args);
+ }
+
+ public Object execute(final Object... args) throws Exception {
+ return executor.execute(getContext(), args);
+ }
+
+ public boolean isOpened() {
+ return !closed;
+ }
+
+ public void close() {
+ closed = true;
+ Closer.close(in, out, err);
+ callback.onExit(0);
+ }
+
+ public boolean isInteractive() {
+ return false;
+ }
+
+ public void run(final Object... args) throws Exception {
+ Console.Executor executor = new Console.Executor()
+ {
+ public Result execute(final String line) throws Exception {
+ assert line != null;
+ try {
+ ShellImpl.this.execute(line);
+ }
+ catch (ExitNotification n) {
+ return Result.STOP;
+ }
+ return Result.CONTINUE;
+ }
+ };
+
+ IO io = getContext().getIo();
+
+ // Setup the console runner
+ JLineConsole console = new JLineConsole(executor, io);
+ console.setPrompter(getPrompter());
+ console.setErrorHandler(getErrorHandler());
+ console.setHistory(getHistory());
+
+ if (completers != null) {
+ // Have to use aggregate here to get the completion list to update properly
+ console.addCompleter(new AggregateCompleter(completers));
+ }
+
+ console.run();
+ }
+
+ public org.apache.geronimo.gshell.shell.Shell getShell() {
+ return this;
+ }
+
+ public IO getIo() {
+ return io;
+ }
+
+ public Variables getVariables() {
+ return variables;
+ }
+
+ public void run() {
+ ShellContext ctx = ShellContextHolder.get(true);
+
+ try {
+ ShellContextHolder.set(getContext());
+ run(new Object[0]);
+ }
+ catch (Exception e) {
+ log.error("Unhandled failure: " + e, e);
+ }
+ finally {
+ ShellContextHolder.set(ctx);
+ close();
+ }
+ }
+ }
+}
diff --git a/karaf/gshell/gshell-core/src/main/java/org/apache/geronimo/gshell/commands/ssh/SshAction.java b/karaf/gshell/gshell-core/src/main/java/org/apache/geronimo/gshell/commands/ssh/SshAction.java
new file mode 100644
index 0000000..cafc437
--- /dev/null
+++ b/karaf/gshell/gshell-core/src/main/java/org/apache/geronimo/gshell/commands/ssh/SshAction.java
@@ -0,0 +1,169 @@
+/*
+ * 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.geronimo.gshell.commands.ssh;
+
+import org.apache.sshd.ClientChannel;
+import org.apache.sshd.ClientSession;
+import org.apache.sshd.SshClient;
+import org.apache.sshd.client.future.ConnectFuture;
+import org.apache.sshd.common.util.NoCloseInputStream;
+import org.apache.sshd.common.util.NoCloseOutputStream;
+import org.apache.geronimo.gshell.clp.Argument;
+import org.apache.geronimo.gshell.clp.Option;
+import org.apache.geronimo.gshell.command.CommandAction;
+import org.apache.geronimo.gshell.command.CommandContext;
+import org.apache.geronimo.gshell.i18n.MessageSource;
+import org.apache.geronimo.gshell.io.IO;
+import org.apache.geronimo.gshell.io.PromptReader;
+import org.apache.geronimo.gshell.spring.BeanContainer;
+import org.apache.geronimo.gshell.spring.BeanContainerAware;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Connect to a SSH server.
+ *
+ * @version $Rev: 721244 $ $Date: 2008-11-27 18:19:56 +0100 (Thu, 27 Nov 2008) $
+ */
+public class SshAction
+ implements CommandAction, BeanContainerAware
+{
+ private final Logger log = LoggerFactory.getLogger(getClass());
+
+ @Option(name="-l", aliases={"--username"})
+ private String username;
+
+ @Option(name="-P", aliases={"--password"})
+ private String password;
+
+ @Argument(required=true)
+ private String hostname;
+
+ @Option(name="-p", aliases={"--port"})
+ private int port = 22;
+
+ private BeanContainer container;
+
+ private ClientSession session;
+
+ public void setBeanContainer(final BeanContainer container) {
+ assert container != null;
+ this.container = container;
+ }
+
+ /**
+ * Helper to validate that prompted username or password is not null or empty.
+ */
+ private class UsernamePasswordValidator
+ implements PromptReader.Validator
+ {
+ private String type;
+
+ private int count = 0;
+
+ private int max = 3;
+
+ public UsernamePasswordValidator(final String type) {
+ assert type != null;
+
+ this.type = type;
+ }
+
+ public boolean isValid(final String value) {
+ count++;
+
+ if (value != null && value.trim().length() > 0) {
+ return true;
+ }
+
+ if (count >= max) {
+ throw new RuntimeException("Too many attempts; failed to prompt user for " + type + " after " + max + " tries");
+ }
+
+ return false;
+ }
+ }
+
+ public Object execute(final CommandContext context) throws Exception {
+ assert context != null;
+ IO io = context.getIo();
+ MessageSource messages = context.getCommand().getMessages();
+
+ //
+ // TODO: Parse hostname for <username>@<hostname>
+ //
+
+ io.info(messages.format("info.connecting", hostname, port));
+
+ // If the username/password was not configured via cli, then prompt the user for the values
+ if (username == null || password == null) {
+ PromptReader prompter = new PromptReader(io);
+ String text;
+
+ log.debug("Prompting user for credentials");
+
+ if (username == null) {
+ text = messages.getMessage("prompt.username");
+ username = prompter.readLine(text + ": ", new UsernamePasswordValidator(text));
+ }
+
+ if (password == null) {
+ text = messages.getMessage("prompt.password");
+ password = prompter.readPassword(text + ": ", new UsernamePasswordValidator(text));
+ }
+ }
+
+ // Create the client from prototype
+ SshClient client = container.getBean(SshClient.class);
+ log.debug("Created client: {}", client);
+ client.start();;
+
+ try {
+ ConnectFuture future = client.connect(hostname, port);
+ future.await();
+ session = future.getSession();
+ try {
+ io.info(messages.getMessage("info.connected"));
+
+ session.authPassword(username, password);
+ int ret = session.waitFor(ClientSession.WAIT_AUTH | ClientSession.CLOSED | ClientSession.AUTHED, 0);
+ if ((ret & ClientSession.AUTHED) == 0) {
+ io.err.println("Authentication failed");
+ return Result.FAILURE;
+ }
+
+ ClientChannel channel = session.createChannel("shell");
+ channel.setIn(new NoCloseInputStream(io.inputStream));
+ channel.setOut(new NoCloseOutputStream(io.outputStream));
+ channel.setErr(new NoCloseOutputStream(io.errorStream));
+ channel.open();
+ channel.waitFor(ClientChannel.CLOSED, 0);
+ } finally {
+ session.close(false);
+ }
+ } finally {
+ client.stop();
+ }
+
+ io.verbose(messages.getMessage("verbose.disconnected"));
+
+ return Result.SUCCESS;
+ }
+}
diff --git a/karaf/gshell/gshell-core/src/main/java/org/apache/geronimo/gshell/commands/ssh/SshServerAction.java b/karaf/gshell/gshell-core/src/main/java/org/apache/geronimo/gshell/commands/ssh/SshServerAction.java
new file mode 100644
index 0000000..db1cfb0
--- /dev/null
+++ b/karaf/gshell/gshell-core/src/main/java/org/apache/geronimo/gshell/commands/ssh/SshServerAction.java
@@ -0,0 +1,84 @@
+/*
+ * 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.geronimo.gshell.commands.ssh;
+
+import org.apache.sshd.SshServer;
+import org.apache.geronimo.gshell.clp.Option;
+import org.apache.geronimo.gshell.command.CommandAction;
+import org.apache.geronimo.gshell.command.CommandContext;
+import org.apache.geronimo.gshell.i18n.MessageSource;
+import org.apache.geronimo.gshell.io.IO;
+import org.apache.geronimo.gshell.spring.BeanContainer;
+import org.apache.geronimo.gshell.spring.BeanContainerAware;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Start a SSH server.
+ *
+ * @version $Rev: 720411 $ $Date: 2008-11-25 05:32:43 +0100 (Tue, 25 Nov 2008) $
+ */
+public class SshServerAction
+ implements CommandAction, BeanContainerAware
+{
+ private final Logger log = LoggerFactory.getLogger(getClass());
+
+ @Option(name="-p", aliases={ "--port" })
+ private int port=8101;
+
+ @Option(name="-b", aliases={ "--background"})
+ private boolean background = true;
+
+ private BeanContainer container;
+
+ public void setBeanContainer(final BeanContainer container) {
+ assert container != null;
+
+ this.container = container;
+ }
+
+ public Object execute(final CommandContext context) throws Exception {
+ assert context != null;
+ IO io = context.getIo();
+ MessageSource messages = context.getCommand().getMessages();
+
+ SshServer server = container.getBean("sshServer", SshServer.class);
+
+ log.debug("Created server: {}", server);
+
+ server.setPort(port);
+
+ server.start();
+
+ io.info(messages.format("info.listening", port));
+
+ if (!background) {
+ synchronized (this) {
+ log.debug("Waiting for server to shutdown");
+
+ wait();
+ }
+
+ server.stop();
+ }
+
+ return Result.SUCCESS;
+ }
+}
diff --git a/karaf/gshell/gshell-core/src/main/java/org/apache/geronimo/gshell/commands/text/SortAction.java b/karaf/gshell/gshell-core/src/main/java/org/apache/geronimo/gshell/commands/text/SortAction.java
new file mode 100644
index 0000000..e81b247
--- /dev/null
+++ b/karaf/gshell/gshell-core/src/main/java/org/apache/geronimo/gshell/commands/text/SortAction.java
@@ -0,0 +1,391 @@
+/*
+ * 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.geronimo.gshell.commands.text;
+
+import java.io.BufferedInputStream;
+import java.io.BufferedReader;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.apache.commons.vfs.FileObject;
+import org.apache.geronimo.gshell.clp.Argument;
+import org.apache.geronimo.gshell.clp.Option;
+import org.apache.geronimo.gshell.command.CommandContext;
+import org.apache.geronimo.gshell.io.Closer;
+import org.apache.geronimo.gshell.vfs.FileObjects;
+import org.apache.geronimo.gshell.vfs.support.VfsActionSupport;
+
+/**
+ * Sort lines of text
+ *
+ * TODO: remove this file when gshell is upgraded
+ *
+ */
+public class SortAction extends VfsActionSupport {
+
+ @Option(name = "-f")
+ private boolean caseInsensitive;
+
+ @Option(name = "-r")
+ private boolean reverse;
+
+ @Option(name = "-u")
+ private boolean unique;
+
+ @Option(name = "-t")
+ private String separator;
+
+ @Option(name = "-b")
+ private boolean ignoreBlanks;
+
+ @Option(name = "-k", argumentRequired = true, multiValued = true)
+ private List<String> sortFields;
+
+ @Option(name = "-n")
+ private boolean numeric;
+
+ @Argument(index = 0, required=false)
+ private String path;
+
+
+ public Object execute(CommandContext context) throws Exception {
+ assert context != null;
+
+ if (path != null) {
+ FileObject file = resolveFile(context, path);
+
+ try {
+ sort(context, file);
+ }
+ finally {
+ FileObjects.close(file);
+ }
+ }
+ else {
+ sort(context.getIo().inputStream, context.getIo().out);
+ }
+ return Result.SUCCESS;
+ }
+
+ protected void sort(final CommandContext context, final FileObject file) throws Exception {
+ assert context != null;
+ assert file != null;
+
+ ensureFileExists(file);
+ ensureFileHasContent(file);
+ ensureFileIsReadable(file);
+
+ BufferedInputStream input = new BufferedInputStream(file.getContent().getInputStream());
+ try {
+ sort(input, context.getIo().out);
+ }
+ finally {
+ Closer.close(input);
+ }
+ }
+
+ protected void sort(InputStream input, PrintWriter out) throws Exception {
+ BufferedReader r = new BufferedReader(new InputStreamReader(input));
+ List<String> strings = new ArrayList<String>();
+ for (String s = r.readLine(); s != null; s = r.readLine()) {
+ strings.add(s);
+ }
+ char sep = (separator == null || separator.length() == 0) ? '\0' : separator.charAt(0);
+ Collections.sort(strings, new SortComparator(caseInsensitive, reverse, ignoreBlanks, numeric, sep, sortFields));
+ String last = null;
+ for (String s : strings) {
+ if (last == null) {
+ last = s;
+ } else if (!unique || !s.equals(last)) {
+ out.println(s);
+ }
+ }
+ }
+
+ public static class SortComparator implements Comparator<String> {
+
+ private boolean caseInsensitive;
+ private boolean reverse;
+ private boolean ignoreBlanks;
+ private boolean numeric;
+ private char separator;
+ private List<Key> sortKeys;
+
+ private static Pattern fpPattern;
+ static {
+ final String Digits = "(\\p{Digit}+)";
+ final String HexDigits = "(\\p{XDigit}+)";
+ final String Exp = "[eE][+-]?" + Digits;
+ final String fpRegex = "([\\x00-\\x20]*[+-]?(NaN|Infinity|(((" + Digits + "(\\.)?(" + Digits + "?)(" + Exp + ")?)|(\\.(" + Digits + ")(" + Exp + ")?)|(((0[xX]" + HexDigits + "(\\.)?)|(0[xX]" + HexDigits + "?(\\.)" + HexDigits + "))[pP][+-]?" + Digits + "))" + "[fFdD]?))[\\x00-\\x20]*)(.*)";
+ fpPattern = Pattern.compile(fpRegex);
+ }
+
+ public SortComparator(boolean caseInsensitive,
+ boolean reverse,
+ boolean ignoreBlanks,
+ boolean numeric,
+ char separator,
+ List<String> sortFields) {
+ this.caseInsensitive = caseInsensitive;
+ this.reverse = reverse;
+ this.separator = separator;
+ this.ignoreBlanks = ignoreBlanks;
+ this.numeric = numeric;
+ if (sortFields == null || sortFields.size() == 0) {
+ sortFields = new ArrayList<String>();
+ sortFields.add("1");
+ }
+ sortKeys = new ArrayList<Key>();
+ for (String f : sortFields) {
+ sortKeys.add(new Key(f));
+ }
+ }
+
+ public int compare(String o1, String o2) {
+ int res = 0;
+
+ List<Integer> fi1 = getFieldIndexes(o1);
+ List<Integer> fi2 = getFieldIndexes(o2);
+ for (Key key : sortKeys) {
+ int[] k1 = getSortKey(o1, fi1, key);
+ int[] k2 = getSortKey(o2, fi2, key);
+ if (key.numeric) {
+ Double d1 = getDouble(o1, k1[0], k1[1]);
+ Double d2 = getDouble(o2, k2[0], k2[1]);
+ res = d1.compareTo(d2);
+ } else {
+ res = compareRegion(o1, k1[0], k1[1], o2, k2[0], k2[1], key.caseInsensitive);
+ }
+ if (res != 0) {
+ if (key.reverse) {
+ res = - res;
+ }
+ break;
+ }
+ }
+ return res;
+ }
+
+ protected Double getDouble(String s, int start, int end) {
+ Matcher m = fpPattern.matcher(s.substring(start, end));
+ m.find();
+ return new Double(s.substring(0, m.end(1)));
+ }
+
+ protected int compareRegion(String s1, int start1, int end1, String s2, int start2, int end2, boolean caseInsensitive) {
+ int n1 = end1, n2 = end2;
+ for (int i1 = start1, i2 = start2; i1 < end1 && i2 < n2; i1++, i2++) {
+ char c1 = s1.charAt(i1);
+ char c2 = s2.charAt(i2);
+ if (c1 != c2) {
+ if (caseInsensitive) {
+ c1 = Character.toUpperCase(c1);
+ c2 = Character.toUpperCase(c2);
+ if (c1 != c2) {
+ c1 = Character.toLowerCase(c1);
+ c2 = Character.toLowerCase(c2);
+ if (c1 != c2) {
+ return c1 - c2;
+ }
+ }
+ } else {
+ return c1 - c2;
+ }
+ }
+ }
+ return n1 - n2;
+ }
+
+ protected int[] getSortKey(String str, List<Integer> fields, Key key) {
+ int start;
+ int end;
+ if (key.startField * 2 < fields.size()) {
+ start = fields.get((key.startField - 1) * 2);
+ if (key.ignoreBlanksStart) {
+ while (start < fields.get((key.startField - 1) * 2 + 1) && Character.isWhitespace(str.charAt(start))) {
+ start++;
+ }
+ }
+ if (key.startChar > 0) {
+ start = Math.min(start + key.startChar - 1, fields.get((key.startField - 1) * 2 + 1));
+ }
+ } else {
+ start = 0;
+ }
+ if (key.endField > 0 && key.endField * 2 < fields.size()) {
+ end = fields.get((key.endField - 1) * 2);
+ if (key.ignoreBlanksEnd) {
+ while (end < fields.get((key.endField - 1) * 2 + 1) && Character.isWhitespace(str.charAt(end))) {
+ end++;
+ }
+ }
+ if (key.endChar > 0) {
+ end = Math.min(end + key.endChar - 1, fields.get((key.endField - 1) * 2 + 1));
+ }
+ } else {
+ end = str.length();
+ }
+ return new int[] { start, end };
+ }
+
+ protected List<Integer> getFieldIndexes(String o) {
+ List<Integer> fields = new ArrayList<Integer>();
+ if (o.length() > 0) {
+ if (separator == '\0') {
+ int i = 0;
+ fields.add(0);
+ for (int idx = 1; idx < o.length(); idx++) {
+ if (Character.isWhitespace(o.charAt(idx)) && !Character.isWhitespace(o.charAt(idx - 1))) {
+ fields.add(idx - 1);
+ fields.add(idx);
+ }
+ }
+ fields.add(o.length() - 1);
+ } else {
+ int last = -1;
+ for (int idx = o.indexOf(separator); idx >= 0; idx = o.indexOf(separator, idx + 1)) {
+ if (last >= 0) {
+ fields.add(last);
+ fields.add(idx - 1);
+ } else if (idx > 0) {
+ fields.add(0);
+ fields.add(idx - 1);
+ }
+ last = idx + 1;
+ }
+ if (last < o.length()) {
+ fields.add(last < 0 ? 0 : last);
+ fields.add(o.length() - 1);
+ }
+ }
+ }
+ return fields;
+ }
+
+ public class Key {
+ int startField;
+ int startChar;
+ int endField;
+ int endChar;
+ boolean ignoreBlanksStart;
+ boolean ignoreBlanksEnd;
+ boolean caseInsensitive;
+ boolean reverse;
+ boolean numeric;
+
+ public Key(String str) {
+ boolean modifiers = false;
+ boolean startPart = true;
+ boolean inField = true;
+ boolean inChar = false;
+ for (char c : str.toCharArray()) {
+ switch (c) {
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ if (!inField && !inChar) {
+ throw new IllegalArgumentException("Bad field syntax: " + str);
+ }
+ if (startPart) {
+ if (inChar) {
+ startChar = startChar * 10 + (c - '0');
+ } else {
+ startField = startField * 10 + (c - '0');
+ }
+ } else {
+ if (inChar) {
+ endChar = endChar * 10 + (c - '0');
+ } else {
+ endField = endField * 10 + (c - '0');
+ }
+ }
+ break;
+ case '.':
+ if (!inField) {
+ throw new IllegalArgumentException("Bad field syntax: " + str);
+ }
+ inField = false;
+ inChar = true;
+ break;
+ case 'n':
+ inField = false;
+ inChar = false;
+ modifiers = true;
+ numeric = true;
+ break;
+ case 'f':
+ inField = false;
+ inChar = false;
+ modifiers = true;
+ caseInsensitive = true;
+ break;
+ case 'r':
+ inField = false;
+ inChar = false;
+ modifiers = true;
+ reverse = true;
+ break;
+ case 'b':
+ inField = false;
+ inChar = false;
+ modifiers = true;
+ if (startPart) {
+ ignoreBlanksStart = true;
+ } else {
+ ignoreBlanksEnd = true;
+ }
+ break;
+ case ',':
+ inField = true;
+ inChar = false;
+ startPart = false;
+ break;
+ default:
+ throw new IllegalArgumentException("Bad field syntax: " + str);
+ }
+ }
+ if (!modifiers) {
+ ignoreBlanksStart = ignoreBlanksEnd = SortComparator.this.ignoreBlanks;
+ reverse = SortComparator.this.reverse;
+ caseInsensitive = SortComparator.this.caseInsensitive;
+ numeric = SortComparator.this.numeric;
+ }
+ if (startField < 1) {
+ throw new IllegalArgumentException("Bad field syntax: " + str);
+ }
+ }
+ }
+ }
+
+}
diff --git a/karaf/gshell/gshell-core/src/main/java/org/apache/geronimo/gshell/vfs/provider/meta/MetaFileObject.java b/karaf/gshell/gshell-core/src/main/java/org/apache/geronimo/gshell/vfs/provider/meta/MetaFileObject.java
new file mode 100644
index 0000000..7e71328
--- /dev/null
+++ b/karaf/gshell/gshell-core/src/main/java/org/apache/geronimo/gshell/vfs/provider/meta/MetaFileObject.java
@@ -0,0 +1,144 @@
+/*
+ * 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.geronimo.gshell.vfs.provider.meta;
+
+import org.apache.commons.vfs.FileContentInfoFactory;
+import org.apache.commons.vfs.FileName;
+import org.apache.commons.vfs.FileType;
+import org.apache.commons.vfs.FileContent;
+import org.apache.commons.vfs.FileSystemException;
+import org.apache.commons.vfs.provider.AbstractFileObject;
+import org.apache.commons.vfs.provider.DefaultFileContent;
+import org.apache.geronimo.gshell.vfs.provider.meta.data.MetaData;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+import java.util.Map;
+
+/**
+ * Meta file object.
+ *
+ * TODO: remove this file when gshell version is upgraded
+ *
+ * @version $Rev: 706033 $ $Date: 2008-10-19 17:36:15 +0200 (Sun, 19 Oct 2008) $
+ */
+public class MetaFileObject
+ extends AbstractFileObject
+{
+ private final MetaFileSystem fileSystem;
+
+ private MetaData data;
+ private FileContent content;
+
+ public MetaFileObject(final FileName fileName, final MetaFileSystem fileSystem) {
+ super(fileName, fileSystem);
+
+ // Save for uncasted typed access
+ this.fileSystem = fileSystem;
+ }
+
+ public MetaData getData() {
+ if (data == null) {
+ throw new IllegalStateException("Meta data has not been attached");
+ }
+
+ return data;
+ }
+
+ @Override
+ protected FileType doGetType() throws Exception {
+ return getData().getType();
+ }
+
+ @Override
+ protected long doGetLastModifiedTime() throws Exception {
+ return getData().getLastModified();
+ }
+
+ @Override
+ protected boolean doIsReadable() throws Exception {
+ return data.getBuffer() != null;
+ }
+
+ @Override
+ protected boolean doIsWriteable() throws Exception {
+ return false;
+ }
+
+ @Override
+ protected FileContentInfoFactory getFileContentInfoFactory() {
+ return fileSystem.getFileContentInfoFactory();
+ }
+
+ @Override
+ protected long doGetContentSize() throws Exception {
+ byte[] bytes = data.getBuffer();
+ return bytes != null ? bytes.length : 0;
+ }
+
+ @Override
+ protected InputStream doGetInputStream() throws Exception {
+ byte[] bytes = data.getBuffer();
+ if (bytes != null) {
+ return new ByteArrayInputStream(bytes);
+ }
+
+ return null;
+ }
+
+ @Override
+ protected Map<String,Object> doGetAttributes() {
+ return getData().getAttributes();
+ }
+
+ @Override
+ protected void doSetAttribute(final String name, final Object value) {
+ getData().getAttributes().put(name, value);
+ }
+
+ protected void doRemoveAttribute(final String name) {
+ getData().getAttributes().remove(name);
+ }
+
+ @Override
+ protected String[] doListChildren() throws Exception {
+ return fileSystem.listChildren(getName());
+ }
+
+ @Override
+ protected void doAttach() throws Exception {
+ if (data == null) {
+ data = fileSystem.lookupData(this);
+ }
+ content = new DefaultFileContent(this, getFileContentInfoFactory());
+ }
+
+ @Override
+ protected void doDetach() throws Exception {
+ data = null;
+ content = null;
+ }
+
+ @Override
+ public FileContent getContent() throws FileSystemException {
+ super.getContent();
+ return content;
+ }
+}
\ No newline at end of file
diff --git a/karaf/gshell/gshell-core/src/main/java/org/apache/servicemix/kernel/gshell/core/ApplicationImpl.java b/karaf/gshell/gshell-core/src/main/java/org/apache/servicemix/kernel/gshell/core/ApplicationImpl.java
new file mode 100644
index 0000000..350fd63
--- /dev/null
+++ b/karaf/gshell/gshell-core/src/main/java/org/apache/servicemix/kernel/gshell/core/ApplicationImpl.java
@@ -0,0 +1,143 @@
+/*
+ * 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.servicemix.kernel.gshell.core;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.InetAddress;
+import java.net.URL;
+import java.util.Properties;
+
+import org.apache.geronimo.gshell.application.Application;
+import org.apache.geronimo.gshell.application.ClassPath;
+import org.apache.geronimo.gshell.application.model.ApplicationModel;
+import org.apache.geronimo.gshell.artifact.Artifact;
+import org.apache.geronimo.gshell.command.Variables;
+import org.apache.geronimo.gshell.io.IO;
+import org.springframework.beans.factory.InitializingBean;
+
+public class ApplicationImpl implements Application, InitializingBean {
+
+ private static final String EMBEDDED_PROPS = "org/apache/servicemix/kernel/version/embedded.properties";
+ private static final String SERVICEMIX_VERSION ="org/apache/servicemix/kernel/gshell/core/servicemix-version.properties";
+ private static final String VERSION_PROPERTY = "version";
+
+ private String id;
+ private IO io;
+ private ApplicationModel model;
+ private Variables variables;
+ private InetAddress localHost;
+ private File homeDir;
+ private URL embeddedResource = null;
+
+ public ApplicationImpl() throws Exception {
+ this.localHost = InetAddress.getLocalHost();
+ this.homeDir = detectHomeDir();
+ }
+
+ public void afterPropertiesSet() throws Exception {
+ Properties props = new Properties();
+ props.load(getClass().getClassLoader().getResourceAsStream(SERVICEMIX_VERSION));
+ String kernelVersion = props.getProperty(VERSION_PROPERTY);
+ this.model.setVersion(kernelVersion);
+ ServiceMixBranding smxBranding = (ServiceMixBranding) this.model.getBranding();
+ smxBranding.setVersion(kernelVersion);
+
+ if (this.getClass().getClassLoader().getResource(EMBEDDED_PROPS) != null) {
+ embeddedResource = this.getClass().getClassLoader().getResource(EMBEDDED_PROPS);
+ smxBranding.setEmbeddedResource(embeddedResource);
+ }
+ }
+
+ public URL getEmbeddedResource() {
+ return embeddedResource;
+ }
+
+ public String getId() {
+ return id;
+ }
+
+ public void setId(String id) {
+ this.id = id;
+ }
+
+ public IO getIo() {
+ return io;
+ }
+
+ public void setIo(IO io) {
+ this.io = io;
+ }
+
+ public Variables getVariables() {
+ return variables;
+ }
+
+ public void setVariables(Variables variables) {
+ this.variables = variables;
+ }
+
+ public ApplicationModel getModel() {
+ return model;
+ }
+
+ public void setModel(ApplicationModel model) {
+ this.model = model;
+ }
+
+ public ClassPath getClassPath() {
+ throw new UnsupportedOperationException();
+ }
+
+ public File getHomeDir() {
+ if (homeDir == null) {
+ throw new IllegalStateException();
+ }
+ return homeDir;
+ }
+
+ public InetAddress getLocalHost() {
+ return localHost;
+ }
+
+ public String getUserName() {
+ return System.getProperty("user.name");
+ }
+
+ public Artifact getArtifact() {
+ return null;
+ }
+
+ private File detectHomeDir() {
+ String homePath = System.getProperty("user.home");
+ // And now lets resolve this sucker
+ File dir;
+ try {
+ dir = new File(homePath).getCanonicalFile();
+ }
+ catch (IOException e) {
+ throw new RuntimeException("Failed to resolve home directory: " + homePath, e);
+ }
+ // And some basic sanity too
+ if (!dir.exists() || !dir.isDirectory()) {
+ throw new RuntimeException("Home directory configured but is not a valid directory: " + dir);
+ }
+
+ return dir;
+ }
+
+}
diff --git a/karaf/gshell/gshell-core/src/main/java/org/apache/servicemix/kernel/gshell/core/ApplicationManagerImpl.java b/karaf/gshell/gshell-core/src/main/java/org/apache/servicemix/kernel/gshell/core/ApplicationManagerImpl.java
new file mode 100644
index 0000000..7465900
--- /dev/null
+++ b/karaf/gshell/gshell-core/src/main/java/org/apache/servicemix/kernel/gshell/core/ApplicationManagerImpl.java
@@ -0,0 +1,81 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.servicemix.kernel.gshell.core;
+
+import org.apache.geronimo.gshell.application.Application;
+import org.apache.geronimo.gshell.application.ApplicationConfiguration;
+import org.apache.geronimo.gshell.application.ApplicationManager;
+import org.apache.geronimo.gshell.event.EventPublisher;
+import org.apache.geronimo.gshell.io.SystemOutputHijacker;
+import org.apache.geronimo.gshell.shell.Shell;
+import org.apache.geronimo.gshell.wisdom.application.ShellCreatedEvent;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.DisposableBean;
+import org.springframework.beans.factory.InitializingBean;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.ApplicationContextAware;
+
+public class ApplicationManagerImpl implements ApplicationManager, ApplicationContextAware, InitializingBean, DisposableBean {
+
+ private final Logger log = LoggerFactory.getLogger(getClass());
+
+ private EventPublisher eventPublisher;
+
+ private Application application;
+
+ private ApplicationContext applicationContext;
+
+ public ApplicationManagerImpl(EventPublisher eventPublisher, Application application) {
+ this.eventPublisher = eventPublisher;
+ this.application = application;
+ }
+
+ public void afterPropertiesSet() throws Exception {
+ if (!SystemOutputHijacker.isInstalled()) {
+ SystemOutputHijacker.install();
+ }
+ //SystemOutputHijacker.register(application.getIo().outputStream, application.getIo().errorStream);
+ }
+
+ public void destroy() {
+ SystemOutputHijacker.uninstall();
+ }
+
+ public void setApplicationContext(ApplicationContext applicationContext) {
+ this.applicationContext = applicationContext;
+ }
+
+ public void configure(ApplicationConfiguration applicationConfiguration) throws Exception {
+ throw new UnsupportedOperationException();
+ }
+
+ public Application getApplication() {
+ return application;
+ }
+
+ public Shell create() throws Exception {
+ final Shell shell = (Shell) applicationContext.getBean("shell");
+
+ log.debug("Created shell instance: {}", shell);
+
+ eventPublisher.publish(new ShellCreatedEvent(shell));
+
+ return shell;
+ }
+
+}
diff --git a/karaf/gshell/gshell-core/src/main/java/org/apache/servicemix/kernel/gshell/core/BeanContainerAwareProcessor.java b/karaf/gshell/gshell-core/src/main/java/org/apache/servicemix/kernel/gshell/core/BeanContainerAwareProcessor.java
new file mode 100644
index 0000000..7deacb1
--- /dev/null
+++ b/karaf/gshell/gshell-core/src/main/java/org/apache/servicemix/kernel/gshell/core/BeanContainerAwareProcessor.java
@@ -0,0 +1,55 @@
+/*
+ * 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.servicemix.kernel.gshell.core;
+
+import org.apache.geronimo.gshell.spring.BeanContainer;
+import org.apache.geronimo.gshell.spring.BeanContainerAware;
+import org.springframework.beans.BeansException;
+import org.springframework.beans.factory.InitializingBean;
+import org.springframework.beans.factory.config.BeanPostProcessor;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.ApplicationContextAware;
+
+public class BeanContainerAwareProcessor implements InitializingBean, BeanPostProcessor, ApplicationContextAware {
+
+ private ApplicationContext applicationContext;
+ private BeanContainer container;
+
+ public void setApplicationContext(ApplicationContext applicationContext) {
+ this.applicationContext = applicationContext;
+ }
+
+ public void afterPropertiesSet() throws Exception {
+ this.container = new BeanContainerWrapper(applicationContext);
+ }
+
+ public Object postProcessBeforeInitialization(final Object bean, final String beanName) throws BeansException {
+ assert bean != null;
+
+ if (bean instanceof BeanContainerAware) {
+ ((BeanContainerAware)bean).setBeanContainer(container);
+ }
+
+ return bean;
+ }
+
+ public Object postProcessAfterInitialization(final Object bean, final String beanName) throws BeansException {
+ return bean;
+ }
+}
\ No newline at end of file
diff --git a/karaf/gshell/gshell-core/src/main/java/org/apache/servicemix/kernel/gshell/core/BeanContainerWrapper.java b/karaf/gshell/gshell-core/src/main/java/org/apache/servicemix/kernel/gshell/core/BeanContainerWrapper.java
new file mode 100644
index 0000000..edc15d7
--- /dev/null
+++ b/karaf/gshell/gshell-core/src/main/java/org/apache/servicemix/kernel/gshell/core/BeanContainerWrapper.java
@@ -0,0 +1,109 @@
+/*
+ * 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.servicemix.kernel.gshell.core;
+
+import java.net.URL;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Map;
+
+import org.apache.geronimo.gshell.spring.BeanContainer;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.NoSuchBeanDefinitionException;
+import org.springframework.context.ApplicationContext;
+
+public class BeanContainerWrapper implements BeanContainer {
+
+ private final Logger log = LoggerFactory.getLogger(getClass());
+
+ private ApplicationContext context;
+
+ public BeanContainerWrapper(ApplicationContext context) {
+ this.context = context;
+ }
+
+ public BeanContainer getParent() {
+ return null;
+ }
+
+ public ClassLoader getClassLoader() {
+ return context.getClassLoader();
+ }
+
+ public void loadBeans(String[] strings) throws Exception {
+ throw new UnsupportedOperationException();
+ }
+
+ public <T> T getBean(Class<T> type) {
+ assert type != null;
+
+ log.trace("Getting bean of type: {}", type);
+
+ String[] names = context.getBeanNamesForType(type);
+
+ if (names.length == 0) {
+ throw new NoSuchBeanDefinitionException(type, "No bean defined for type: " + type);
+ }
+ if (names.length > 1) {
+ throw new NoSuchBeanDefinitionException(type, "No unique bean defined for type: " + type + ", found matches: " + Arrays.asList(names));
+ }
+
+ return getBean(names[0], type);
+ }
+
+ public <T> T getBean(String name, Class<T> requiredType) {
+ assert name != null;
+ assert requiredType != null;
+
+ log.trace("Getting bean named '{}' of type: {}", name, requiredType);
+
+ return (T) context.getBean(name, requiredType);
+ }
+
+ public <T> Map<String, T> getBeans(Class<T> type) {
+ assert type != null;
+
+ log.trace("Getting beans of type: {}", type);
+
+ return (Map<String,T>) context.getBeansOfType(type);
+ }
+
+ public String[] getBeanNames() {
+ log.trace("Getting bean names");
+
+ return context.getBeanDefinitionNames();
+ }
+
+ public String[] getBeanNames(Class type) {
+ assert type != null;
+
+ log.trace("Getting bean names of type: {}", type);
+
+ return context.getBeanNamesForType(type);
+ }
+
+ public BeanContainer createChild(Collection<URL> urls) {
+ throw new UnsupportedOperationException();
+ }
+
+ public BeanContainer createChild() {
+ throw new UnsupportedOperationException();
+ }
+}
diff --git a/karaf/gshell/gshell-core/src/main/java/org/apache/servicemix/kernel/gshell/core/CommandBundle.java b/karaf/gshell/gshell-core/src/main/java/org/apache/servicemix/kernel/gshell/core/CommandBundle.java
new file mode 100644
index 0000000..2111072
--- /dev/null
+++ b/karaf/gshell/gshell-core/src/main/java/org/apache/servicemix/kernel/gshell/core/CommandBundle.java
@@ -0,0 +1,175 @@
+/*
+ * 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.servicemix.kernel.gshell.core;
+
+import java.util.ArrayList;
+import java.util.Dictionary;
+import java.util.List;
+import java.util.Properties;
+
+import org.apache.geronimo.gshell.command.Alias;
+import org.apache.geronimo.gshell.command.Command;
+import org.apache.geronimo.gshell.command.Link;
+import org.apache.geronimo.gshell.registry.AliasRegistry;
+import org.apache.geronimo.gshell.registry.CommandRegistry;
+import org.apache.geronimo.gshell.wisdom.command.LinkCommand;
+import org.apache.geronimo.gshell.wisdom.registry.CommandLocationImpl;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceRegistration;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.DisposableBean;
+import org.springframework.beans.factory.InitializingBean;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.ApplicationContextAware;
+import org.springframework.osgi.context.BundleContextAware;
+
+public class CommandBundle implements BundleContextAware, InitializingBean, DisposableBean, ApplicationContextAware {
+
+ private final Logger log = LoggerFactory.getLogger(getClass());
+
+ private CommandRegistry commandRegistry;
+
+ private AliasRegistry aliasRegistry;
+
+ private BundleContext bundleContext;
+
+ private List<Command> commands;
+
+ private List<Link> links;
+
+ private List<Alias> aliases;
+
+ private ApplicationContext applicationContext;
+
+ private List<ServiceRegistration> registrations = new ArrayList<ServiceRegistration>();
+
+ public CommandBundle() {
+ }
+
+ public void setApplicationContext(ApplicationContext applicationContext) {
+ this.applicationContext = applicationContext;
+ }
+
+ public List<Command> getCommands() {
+ return commands;
+ }
+
+ public void setCommands(final List<Command> commands) {
+ assert commands != null;
+
+ this.commands = commands;
+ }
+
+ public List<Link> getLinks() {
+ return links;
+ }
+
+ public void setLinks(List<Link> links) {
+ assert links != null;
+
+ this.links = links;
+ }
+
+ public List<Alias> getAliases() {
+ return aliases;
+ }
+
+ public void setAliases(List<Alias> aliases) {
+ assert aliases != null;
+
+ this.aliases = aliases;
+ }
+
+ public void setBundleContext(BundleContext bundleContext) {
+ this.bundleContext = bundleContext;
+ }
+
+ public void afterPropertiesSet() throws Exception {
+ log.debug("Initializing command bundle");
+ if (commandRegistry == null) {
+ String[] names = applicationContext.getBeanNamesForType(CommandRegistry.class);
+ if (names.length == 1) {
+ commandRegistry = (CommandRegistry) applicationContext.getBean(names[0], CommandRegistry.class);
+ }
+ }
+ if (aliasRegistry == null) {
+ String[] names = applicationContext.getBeanNamesForType(AliasRegistry.class);
+ if (names.length == 1) {
+ aliasRegistry = (AliasRegistry) applicationContext.getBean(names[0], AliasRegistry.class);
+ }
+ }
+ if (commandRegistry != null && aliasRegistry != null) {
+ log.debug("Command bundle is using the auto wired command/alias registry");
+ if (commands != null) {
+ for (Command command : commands) {
+ log.debug("Registering command: {}", command.getLocation());
+ commandRegistry.registerCommand(command);
+ }
+ }
+ if (links != null) {
+ for (Link link : links) {
+ log.debug("Registering link: {}", link.getName());
+ LinkCommand cmd = new LinkCommand(commandRegistry, link.getTarget());
+ cmd.setLocation(new CommandLocationImpl(link.getName()));
+ commandRegistry.registerCommand(cmd);
+ }
+ }
+ if (aliases != null) {
+ for (Alias alias : aliases) {
+ log.debug("Registering alias: {}", alias.getName());
+ aliasRegistry.registerAlias(alias.getName(), alias.getAlias());
+ }
+ }
+ } else if (bundleContext != null) {
+ log.debug("Command bundle is using the OSGi registry");
+ if (commands != null) {
+ for (Command command : commands) {
+ log.debug("Registering command: {}", command.getLocation());
+ Dictionary props = new Properties();
+ props.put(OsgiCommandRegistry.NAME, command.getLocation().getFullPath());
+ registrations.add(bundleContext.registerService(Command.class.getName(), command, props));
+ }
+ }
+ if (links != null) {
+ for (Link link : links) {
+ log.debug("Registering link: {}", link.getName());
+ registrations.add(bundleContext.registerService(Link.class.getName(), link, new Properties()));
+ }
+ }
+ if (aliases != null) {
+ for (Alias alias : aliases) {
+ log.debug("Registering alias: {}", alias.getName());
+ Dictionary props = new Properties();
+ registrations.add(bundleContext.registerService(Alias.class.getName(), alias, new Properties()));
+ }
+ }
+ } else {
+ throw new Exception("Command bundle should be wired to the command/alias registry or be used in an OSGi context");
+ }
+ }
+
+ public void destroy() {
+ log.debug("Destroying command bundle");
+ for (ServiceRegistration reg : registrations) {
+ reg.unregister();
+ }
+ }
+
+}
diff --git a/karaf/gshell/gshell-core/src/main/java/org/apache/servicemix/kernel/gshell/core/LocalConsole.java b/karaf/gshell/gshell-core/src/main/java/org/apache/servicemix/kernel/gshell/core/LocalConsole.java
new file mode 100644
index 0000000..98c7193
--- /dev/null
+++ b/karaf/gshell/gshell-core/src/main/java/org/apache/servicemix/kernel/gshell/core/LocalConsole.java
@@ -0,0 +1,172 @@
+/*
+ * 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.servicemix.kernel.gshell.core;
+
+import java.util.Arrays;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+import org.apache.geronimo.gshell.notification.ExitNotification;
+import org.apache.geronimo.gshell.shell.Shell;
+import org.apache.servicemix.kernel.main.spi.MainService;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.BundleException;
+import org.osgi.framework.FrameworkEvent;
+import org.osgi.framework.FrameworkListener;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.osgi.context.BundleContextAware;
+
+public class LocalConsole implements Runnable, BundleContextAware {
+
+ private final Logger log = LoggerFactory.getLogger(getClass());
+
+ private Shell shell;
+
+ private boolean createLocalShell;
+
+ private BundleContext bundleContext;
+
+ private MainService mainService;
+
+ private CountDownLatch frameworkStarted;
+
+ public BundleContext getBundleContext() {
+ return bundleContext;
+ }
+
+ public void setBundleContext(BundleContext bundleContext) {
+ this.bundleContext = bundleContext;
+ }
+
+ public MainService getMainService() {
+ return mainService;
+ }
+
+ public void setMainService(MainService mainService) {
+ this.mainService = mainService;
+ }
+
+ public Shell getShell() {
+ return shell;
+ }
+
+ public void setShell(Shell shell) {
+ this.shell = shell;
+ }
+
+ public boolean isCreateLocalShell() {
+ return createLocalShell;
+ }
+
+ public void setCreateLocalShell(boolean createLocalShell) {
+ this.createLocalShell = createLocalShell;
+ }
+
+ public void init() {
+ shell.getContext().getVariables().set("gshell.username", "smx");
+ frameworkStarted = new CountDownLatch(1);
+ getBundleContext().addFrameworkListener(new FrameworkListener(){
+ public void frameworkEvent(FrameworkEvent event) {
+ log.debug("Got event: " + event.getType());
+ if( event.getType() == FrameworkEvent.STARTED ) {
+ frameworkStarted.countDown();
+ }
+ }
+ });
+ if (createLocalShell) {
+ new Thread(this, "localShell").start();
+ }
+ }
+
+ public void destroy() {
+ if (createLocalShell) {
+ shell.close();
+ }
+ }
+
+ public void run() {
+ try {
+ String[] args = mainService.getArgs();
+ // If a command was specified on the command line, then just execute that command.
+ if (args != null && args.length > 0) {
+ waitForFrameworkToStart();
+ log.info("Executing Shell with arguments: " + Arrays.toString(args));
+ StringBuilder sb = new StringBuilder();
+ for (String arg : args) {
+ sb.append(arg).append(" ");
+ }
+ Object value = shell.execute(sb.toString());
+ if (mainService != null) {
+ if (value instanceof Number) {
+ mainService.setExitCode(((Number) value).intValue());
+ } else {
+ mainService.setExitCode(value != null ? 1 : 0);
+ }
+ log.info("Exiting shell due to terminated command");
+ }
+ } else {
+ shell.run();
+ }
+ } catch (ExitNotification e) {
+ if (mainService != null) {
+ mainService.setExitCode(0);
+ }
+ log.info("Exiting shell due received exit notification");
+ } catch (Throwable e) {
+ if (mainService != null) {
+ mainService.setExitCode(-1);
+ }
+ log.error("Exiting shell due to caught exception " + e, e);
+ } finally {
+ try {
+ shell.close();
+ } catch (Throwable t) {}
+ asyncShutdown();
+ }
+ }
+
+ /**
+ * Blocks until the framework has finished starting. We do this so that any installed
+ * bundles for commands get fully registered.
+ *
+ * @throws InterruptedException
+ */
+ private void waitForFrameworkToStart() throws InterruptedException {
+ log.info("Waiting from framework to start.");
+ if (frameworkStarted.await(60, TimeUnit.SECONDS)) {
+ log.info("System completed startup.");
+ } else {
+ log.warn("System took too long startup... continuing");
+ }
+ }
+
+ private void asyncShutdown() {
+ new Thread() {
+ public void run() {
+ try {
+ getBundleContext().getBundle(0).stop();
+ } catch (BundleException e) {
+ log.info("Caught exception while shutting down framework: " + e, e);
+ }
+ }
+ }.start();
+ }
+
+}
diff --git a/karaf/gshell/gshell-core/src/main/java/org/apache/servicemix/kernel/gshell/core/OsgiAliasRegistry.java b/karaf/gshell/gshell-core/src/main/java/org/apache/servicemix/kernel/gshell/core/OsgiAliasRegistry.java
new file mode 100644
index 0000000..a09ce0b
--- /dev/null
+++ b/karaf/gshell/gshell-core/src/main/java/org/apache/servicemix/kernel/gshell/core/OsgiAliasRegistry.java
@@ -0,0 +1,45 @@
+/*
+ * 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.servicemix.kernel.gshell.core;
+
+import java.util.Map;
+
+import org.apache.geronimo.gshell.command.Alias;
+import org.apache.geronimo.gshell.registry.AliasRegistry;
+
+public class OsgiAliasRegistry {
+
+ public static final String NAME = "name";
+ public static final String ALIAS = "alias";
+
+ private AliasRegistry aliasRegistry;
+
+ public OsgiAliasRegistry(AliasRegistry aliasRegistry) {
+ this.aliasRegistry = aliasRegistry;
+ }
+
+ public void register(final Alias alias, Map<String, ?> properties) throws Exception {
+ aliasRegistry.registerAlias(alias.getName(), alias.getAlias());
+ }
+
+ public void unregister(final Alias alias, Map<String, ?> properties) throws Exception {
+ aliasRegistry.removeAlias(alias.getName());
+ }
+
+}
diff --git a/karaf/gshell/gshell-core/src/main/java/org/apache/servicemix/kernel/gshell/core/OsgiCommandRegistry.java b/karaf/gshell/gshell-core/src/main/java/org/apache/servicemix/kernel/gshell/core/OsgiCommandRegistry.java
new file mode 100644
index 0000000..c6817e8
--- /dev/null
+++ b/karaf/gshell/gshell-core/src/main/java/org/apache/servicemix/kernel/gshell/core/OsgiCommandRegistry.java
@@ -0,0 +1,58 @@
+/*
+ * 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.servicemix.kernel.gshell.core;
+
+import java.util.Map;
+
+import org.apache.geronimo.gshell.command.Command;
+import org.apache.geronimo.gshell.command.Link;
+import org.apache.geronimo.gshell.registry.CommandRegistry;
+import org.apache.geronimo.gshell.wisdom.command.LinkCommand;
+import org.apache.geronimo.gshell.wisdom.registry.CommandLocationImpl;
+
+public class OsgiCommandRegistry {
+
+ public static final String NAME = "name";
+ public static final String TARGET = "target";
+
+ private CommandRegistry commandRegistry;
+
+ public OsgiCommandRegistry(CommandRegistry commandRegistry) {
+ this.commandRegistry = commandRegistry;
+ }
+
+ public void register(final Command command, Map<String, ?> properties) throws Exception {
+ commandRegistry.registerCommand(command);
+ }
+
+ public void unregister(final Command command, Map<String, ?> properties) throws Exception {
+ commandRegistry.removeCommand(command);
+ }
+
+ public void register(final Link link, Map<String, ?> properties) throws Exception {
+ LinkCommand cmd = new LinkCommand(commandRegistry, link.getTarget());
+ cmd.setLocation(new CommandLocationImpl(link.getName()));
+ commandRegistry.registerCommand(cmd);
+ }
+
+ public void unregister(final Link link, Map<String, ?> properties) throws Exception {
+ commandRegistry.removeCommand(commandRegistry.getCommand(link.getName()));
+ }
+
+}
diff --git a/karaf/gshell/gshell-core/src/main/java/org/apache/servicemix/kernel/gshell/core/OsgiCommandSupport.java b/karaf/gshell/gshell-core/src/main/java/org/apache/servicemix/kernel/gshell/core/OsgiCommandSupport.java
new file mode 100644
index 0000000..e13940a
--- /dev/null
+++ b/karaf/gshell/gshell-core/src/main/java/org/apache/servicemix/kernel/gshell/core/OsgiCommandSupport.java
@@ -0,0 +1,96 @@
+/*
+ * 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.servicemix.kernel.gshell.core;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.geronimo.gshell.command.CommandAction;
+import org.apache.geronimo.gshell.command.CommandContext;
+import org.apache.geronimo.gshell.command.Variables;
+import org.apache.geronimo.gshell.io.IO;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceReference;
+import org.springframework.osgi.context.BundleContextAware;
+
+public abstract class OsgiCommandSupport implements CommandAction, BundleContextAware {
+
+ protected Log log = LogFactory.getLog(getClass());
+ protected BundleContext bundleContext;
+ protected CommandContext commandContext;
+ protected IO io;
+ protected Variables variables;
+ protected List<ServiceReference> usedReferences;
+
+ public Object execute(CommandContext commandContext) throws Exception {
+ this.commandContext = commandContext;
+ this.io = commandContext.getIo();
+ this.variables = commandContext.getVariables();
+ try {
+ return doExecute();
+ } finally {
+ ungetServices();
+ }
+ }
+
+ protected abstract Object doExecute() throws Exception;
+
+ public BundleContext getBundleContext() {
+ return bundleContext;
+ }
+
+ public void setBundleContext(BundleContext bundleContext) {
+ this.bundleContext = bundleContext;
+ }
+
+ protected <T> List<T> getAllServices(Class<T> clazz, String filter) throws Exception {
+ ServiceReference[] references = getBundleContext().getAllServiceReferences(clazz.getName(), filter);
+ if (references == null) {
+ return null;
+ }
+ List<T> services = new ArrayList<T>();
+ for (ServiceReference ref : references) {
+ T t = getService(clazz, ref);
+ services.add(t);
+ }
+ return services;
+ }
+
+ protected <T> T getService(Class<T> clazz, ServiceReference reference) {
+ T t = (T) getBundleContext().getService(reference);
+ if (t != null) {
+ if (usedReferences == null) {
+ usedReferences = new ArrayList<ServiceReference>();
+ }
+ usedReferences.add(reference);
+ }
+ return t;
+ }
+
+ protected void ungetServices() {
+ if (usedReferences != null) {
+ for (ServiceReference ref : usedReferences) {
+ getBundleContext().ungetService(ref);
+ }
+ }
+ }
+
+}
diff --git a/karaf/gshell/gshell-core/src/main/java/org/apache/servicemix/kernel/gshell/core/ServiceMixBranding.java b/karaf/gshell/gshell-core/src/main/java/org/apache/servicemix/kernel/gshell/core/ServiceMixBranding.java
new file mode 100644
index 0000000..803b511
--- /dev/null
+++ b/karaf/gshell/gshell-core/src/main/java/org/apache/servicemix/kernel/gshell/core/ServiceMixBranding.java
@@ -0,0 +1,188 @@
+/*
+ * 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.servicemix.kernel.gshell.core;
+
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.net.URL;
+import java.util.Properties;
+import java.util.StringTokenizer;
+
+import org.apache.geronimo.gshell.ansi.AnsiBuffer;
+import org.apache.geronimo.gshell.ansi.AnsiCode;
+import org.apache.geronimo.gshell.ansi.AnsiRenderWriter;
+import org.apache.geronimo.gshell.application.model.Branding;
+
+public class ServiceMixBranding extends Branding {
+
+ private String prompt;
+ private String[] banner;
+ private String displayName;
+ private String displayVersion;
+ private String displayLocation;
+ private String applicationName;
+ private String applicationVersion;
+ private String applicationLocation;
+
+ private String[] kernelBanner = {
+ " ____ _ __ __ _ ",
+ "/ ___| ___ _ ____ _(_) ___ ___| \\/ (_)_ __",
+ "\\___ \\ / _ \\ '__\\ \\ / / |/ __/ _ \\ |\\/| | \\ \\/ /",
+ " ___) | __/ | \\ V /| | (_| __/ | | | |> < ",
+ "|____/ \\___|_| \\_/ |_|\\___\\___|_| |_|_/_/\\_\\",
+ };
+
+ public ServiceMixBranding() {
+ banner = kernelBanner;
+ displayName = "ServiceMix Kernel";
+ displayLocation = "http://servicemix.apache.org/kernel/";
+ }
+
+ public void setEmbeddedResource(URL embeddedResource) {
+ Properties brandProps = loadPropertiesFile(embeddedResource);
+ String brandBanner = brandProps.getProperty("banner");
+ int i = 0;
+ char quot = '"';
+
+ StringTokenizer st = new StringTokenizer(brandBanner, ",");
+ banner = new String[st.countTokens()];
+
+ while (st.hasMoreTokens()) {
+ banner[i] = st.nextToken();
+ banner[i] = banner[i].substring(1, banner[i].lastIndexOf(quot));
+ i++;
+ }
+
+ applicationName = brandProps.getProperty("application.name");
+ applicationVersion = brandProps.getProperty("application.version");
+ applicationLocation = brandProps.getProperty("application.location");
+ }
+
+ public String getName() {
+ return "servicemix";
+ }
+
+ public String getDisplayName() {
+ return displayName;
+ }
+
+ public void setVersion(String version) {
+ displayVersion = version;
+ }
+
+ public String getVersion() {
+ return displayVersion;
+ }
+
+ public String getApplicationName() {
+ return applicationName;
+ }
+
+ public String getApplicationVersion() {
+ return applicationVersion;
+ }
+
+ public String getProgramName() {
+ throw new UnsupportedOperationException();
+ }
+
+ public String getPrompt() {
+ return prompt;
+ }
+
+ public void setPrompt(String prompt) {
+ this.prompt = prompt;
+ }
+
+ public String getAboutMessage() {
+ StringWriter writer = new StringWriter();
+ PrintWriter out = new AnsiRenderWriter(writer);
+
+ out.println("For information about @|cyan " + displayName + "|, visit:");
+ out.println(" @|bold " + displayLocation + "| ");
+ out.flush();
+
+ if (applicationName != null && applicationVersion != null) {
+ out.println();
+ out.println(applicationName + " " + applicationVersion);
+ out.println();
+ if (applicationLocation != null) {
+ out.println("For information about @|cyan " + applicationName + "|, visit:");
+ out.println(" @|bold " + applicationLocation + "| ");
+ out.flush();
+ }
+ }
+
+ return writer.toString();
+ }
+
+ public String getWelcomeMessage() {
+ StringWriter writer = new StringWriter();
+ PrintWriter out = new AnsiRenderWriter(writer);
+
+ AnsiBuffer buff = new AnsiBuffer();
+
+ for (String line : banner) {
+ buff.attrib(line, AnsiCode.CYAN);
+ out.println(buff);
+ }
+
+ out.println();
+ out.println(" @|bold " + displayName + "| (" + displayVersion + ")");
+ if (applicationName != null && applicationVersion != null) {
+ out.println(" @|bold " + applicationName + "| (" + applicationVersion + ")");
+ }
+ out.println();
+ out.println("Type '@|bold help|' for more information.");
+ out.flush();
+
+ return writer.toString();
+ }
+
+ private static Properties loadPropertiesFile(URL brandPropURL) {
+ // Read the properties file.
+ Properties brandProps = new Properties();
+ InputStream is = null;
+ try {
+ is = brandPropURL.openConnection().getInputStream();
+ brandProps.load(is);
+ is.close();
+ }
+ catch (FileNotFoundException ex) {
+ // Ignore file not found.
+ }
+ catch (Exception ex) {
+ System.err.println(
+ "Error loading embedded properties from " + brandPropURL);
+ System.err.println("ServicemixBranding: " + ex);
+ try {
+ if (is != null) is.close();
+ }
+ catch (IOException ex2) {
+ // Nothing we can do.
+ }
+ return null;
+ }
+
+ return brandProps;
+ }
+
+}
+
diff --git a/karaf/gshell/gshell-core/src/main/java/org/apache/servicemix/kernel/gshell/core/ShellWrapper.java b/karaf/gshell/gshell-core/src/main/java/org/apache/servicemix/kernel/gshell/core/ShellWrapper.java
new file mode 100644
index 0000000..ae86534
--- /dev/null
+++ b/karaf/gshell/gshell-core/src/main/java/org/apache/servicemix/kernel/gshell/core/ShellWrapper.java
@@ -0,0 +1,86 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.servicemix.kernel.gshell.core;
+
+import org.apache.geronimo.gshell.shell.Shell;
+import org.apache.geronimo.gshell.shell.ShellContext;
+import org.apache.geronimo.gshell.shell.ShellContextHolder;
+
+public class ShellWrapper implements Shell {
+
+ private Shell delegate;
+
+ public ShellWrapper(Shell delegate) {
+ this.delegate = delegate;
+ }
+
+ public ShellContext getContext() {
+ return delegate.getContext();
+ }
+
+ public Object execute(String s) throws Exception {
+ ShellContext ctx = ShellContextHolder.get(true);
+ try {
+ ShellContextHolder.set(getContext());
+ return delegate.execute(s);
+ } finally {
+ ShellContextHolder.set(ctx);
+ }
+ }
+
+ public Object execute(String s, Object[] objects) throws Exception {
+ ShellContext ctx = ShellContextHolder.get(true);
+ try {
+ ShellContextHolder.set(getContext());
+ return delegate.execute(s, objects);
+ } finally {
+ ShellContextHolder.set(ctx);
+ }
+ }
+
+ public Object execute(Object... objects) throws Exception {
+ ShellContext ctx = ShellContextHolder.get(true);
+ try {
+ ShellContextHolder.set(getContext());
+ return delegate.execute(objects);
+ } finally {
+ ShellContextHolder.set(ctx);
+ }
+ }
+
+ public boolean isOpened() {
+ return delegate.isOpened();
+ }
+
+ public void close() {
+ delegate.close();
+ }
+
+ public boolean isInteractive() {
+ return delegate.isInteractive();
+ }
+
+ public void run(Object... objects) throws Exception {
+ ShellContext ctx = ShellContextHolder.get(true);
+ try {
+ ShellContextHolder.set(getContext());
+ delegate.run(objects);
+ } finally {
+ ShellContextHolder.set(ctx);
+ }
+ }
+}
diff --git a/karaf/gshell/gshell-core/src/main/java/org/apache/servicemix/kernel/gshell/core/WorkAroundAliasCommand.java b/karaf/gshell/gshell-core/src/main/java/org/apache/servicemix/kernel/gshell/core/WorkAroundAliasCommand.java
new file mode 100644
index 0000000..1e52177
--- /dev/null
+++ b/karaf/gshell/gshell-core/src/main/java/org/apache/servicemix/kernel/gshell/core/WorkAroundAliasCommand.java
@@ -0,0 +1,118 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.servicemix.kernel.gshell.core;
+
+import java.util.Iterator;
+import java.util.List;
+
+import org.apache.geronimo.gshell.clp.Argument;
+import org.apache.geronimo.gshell.command.CommandAction;
+import org.apache.geronimo.gshell.command.CommandContext;
+import org.apache.geronimo.gshell.command.CommandResult;
+import org.apache.geronimo.gshell.command.Variables;
+import org.apache.geronimo.gshell.commandline.CommandLineExecutor;
+import org.apache.geronimo.gshell.io.IO;
+import org.apache.geronimo.gshell.shell.Shell;
+import org.apache.geronimo.gshell.shell.ShellContext;
+import org.apache.geronimo.gshell.shell.ShellContextHolder;
+import org.apache.geronimo.gshell.wisdom.command.AliasCommand;
+
+public class WorkAroundAliasCommand extends AliasCommand {
+
+ private final CommandLineExecutor executor;
+
+ public WorkAroundAliasCommand(CommandLineExecutor executor) {
+ super(executor);
+ this.executor = executor;
+ setAction(new AliasCommandAction());
+ }
+
+ @Override
+ protected void prepareAction(final ShellContext context, final Object[] args) {
+ // HACK: Reset state for proper appendArgs muck
+ assert context != null;
+ assert args != null;
+
+ setAction(new AliasCommandAction());
+ log.trace("Preparing action");
+
+ IO io = context.getIo();
+ CommandAction action = getAction();
+
+ // Setup the command action
+ try {
+ // Process command line options/arguments
+ processArguments(io, action, args);
+ }
+ catch (Exception e) {
+ // Abort if preparation caused a failure
+ throw new AbortExecutionNotification(new CommandResult.FailureResult(e));
+ }
+ }
+
+ private class AliasCommandAction
+ implements CommandAction
+ {
+ @Argument
+ private List<String> appendArgs = null;
+
+ public Object execute(final CommandContext context) throws Exception {
+ assert context != null;
+
+ StringBuilder buff = new StringBuilder();
+ buff.append(getAlias());
+
+ // If we have args to append, then do it
+ if (appendArgs != null && !appendArgs.isEmpty()) {
+ buff.append(" ");
+
+ // Append args quoted as they have already been processed by the parser
+ Iterator iter = appendArgs.iterator();
+ while (iter.hasNext()) {
+ //
+ // HACK: Using double quote instead of single quote for now as the parser's handling of single quote is broken
+ //
+
+ buff.append('"').append(iter.next()).append('"');
+ if (iter.hasNext()) {
+ buff.append(" ");
+ }
+ }
+ }
+
+ log.debug("Executing alias: {}", buff);
+
+ final Shell shell = ShellContextHolder.get().getShell();
+ ShellContext shellContext = new ShellContext() {
+ public Shell getShell() {
+ return shell;
+ }
+ public IO getIo() {
+ return context.getIo();
+ }
+ public Variables getVariables() {
+ return context.getVariables();
+ }
+ };
+ Object result = executor.execute(shellContext, buff.toString());
+
+ log.debug("Alias result: {}", result);
+
+ return result;
+ }
+ }
+}
diff --git a/karaf/gshell/gshell-core/src/main/java/org/apache/servicemix/kernel/gshell/core/commands/InfoAction.java b/karaf/gshell/gshell-core/src/main/java/org/apache/servicemix/kernel/gshell/core/commands/InfoAction.java
new file mode 100644
index 0000000..8f3b580
--- /dev/null
+++ b/karaf/gshell/gshell-core/src/main/java/org/apache/servicemix/kernel/gshell/core/commands/InfoAction.java
@@ -0,0 +1,177 @@
+/*
+ * 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.servicemix.kernel.gshell.core.commands;
+
+import java.lang.management.ClassLoadingMXBean;
+import java.lang.management.GarbageCollectorMXBean;
+import java.lang.management.ManagementFactory;
+import java.lang.management.MemoryMXBean;
+import java.lang.management.OperatingSystemMXBean;
+import java.lang.management.RuntimeMXBean;
+import java.lang.management.ThreadMXBean;
+import java.lang.reflect.Method;
+import java.text.DecimalFormat;
+import java.text.DecimalFormatSymbols;
+import java.text.NumberFormat;
+import java.util.Locale;
+
+import org.apache.geronimo.gshell.ansi.AnsiCode;
+import org.apache.geronimo.gshell.ansi.AnsiRenderer;
+import org.apache.geronimo.gshell.command.CommandAction;
+import org.apache.geronimo.gshell.command.CommandContext;
+import org.apache.geronimo.gshell.io.IO;
+import org.apache.servicemix.kernel.gshell.core.ServiceMixBranding;
+import org.codehaus.plexus.util.StringUtils;
+
+public class InfoAction implements CommandAction {
+
+ private ServiceMixBranding branding;
+
+ private IO io;
+
+ private AnsiRenderer renderer = new AnsiRenderer();
+ private NumberFormat fmtI = new DecimalFormat("###,###", new DecimalFormatSymbols(Locale.ENGLISH));
+ private NumberFormat fmtD = new DecimalFormat("###,##0.000", new DecimalFormatSymbols(Locale.ENGLISH));
+
+ public InfoAction(ServiceMixBranding branding) {
+ this.branding = branding;
+ }
+
+ public Object execute(CommandContext context) throws Exception {
+ int maxNameLen;
+
+ RuntimeMXBean runtime = ManagementFactory.getRuntimeMXBean();
+ OperatingSystemMXBean os = ManagementFactory.getOperatingSystemMXBean();
+ ThreadMXBean threads = ManagementFactory.getThreadMXBean();
+ MemoryMXBean mem = ManagementFactory.getMemoryMXBean();
+ ClassLoadingMXBean cl = ManagementFactory.getClassLoadingMXBean();
+ io = context.getIo();
+
+ //
+ // print ServiceMix informations
+ //
+ maxNameLen = 25;
+ io.out.println("ServiceMix");
+ printValue("ServiceMix home", maxNameLen, System.getProperty("servicemix.home"));
+ printValue("ServiceMix base", maxNameLen, System.getProperty("servicemix.base"));
+ printValue("ServiceMix Kernel version", maxNameLen, branding.getParent().getVersion());
+
+ if (branding.getApplicationName() != null && branding.getApplicationVersion() != null) {
+ printValue(branding.getApplicationName() + " version", maxNameLen, branding.getApplicationVersion());
+ }
+ io.out.println();
+
+ io.out.println("JVM");
+ printValue("Java Virtual Machine", maxNameLen, runtime.getVmName() + " version " + runtime.getVmVersion());
+ printValue("Vendor", maxNameLen, runtime.getVmVendor());
+ printValue("Uptime", maxNameLen, printDuration(runtime.getUptime()));
+ try {
+ printValue("Process CPU time", maxNameLen, printDuration(getSunOsValueAsLong(os, "getProcessCpuTime") / 1000000));
+ } catch (Throwable t) {}
+ printValue("Total compile time", maxNameLen, printDuration(ManagementFactory.getCompilationMXBean().getTotalCompilationTime()));
+
+ io.out.println("Threads");
+ printValue("Live threads", maxNameLen, Integer.toString(threads.getThreadCount()));
+ printValue("Daemon threads", maxNameLen, Integer.toString(threads.getDaemonThreadCount()));
+ printValue("Peak", maxNameLen, Integer.toString(threads.getPeakThreadCount()));
+ printValue("Total started", maxNameLen, Long.toString(threads.getTotalStartedThreadCount()));
+
+ io.out.println("Memory");
+ printValue("Current heap size", maxNameLen, printSizeInKb(mem.getHeapMemoryUsage().getUsed()));
+ printValue("Maximum heap size", maxNameLen, printSizeInKb(mem.getHeapMemoryUsage().getMax()));
+ printValue("Committed heap size", maxNameLen, printSizeInKb(mem.getHeapMemoryUsage().getCommitted()));
+ printValue("Pending objects", maxNameLen, Integer.toString(mem.getObjectPendingFinalizationCount()));
+ for (GarbageCollectorMXBean gc : ManagementFactory.getGarbageCollectorMXBeans()) {
+ String val = "Name = '" + gc.getName() + "', Collections = " + gc.getCollectionCount() + ", Time = " + printDuration(gc.getCollectionTime());
+ printValue("Garbage collector", maxNameLen, val);
+ }
+
+ io.out.println("Classes");
+ printValue("Current classes loaded", maxNameLen, printLong(cl.getLoadedClassCount()));
+ printValue("Total classes loaded", maxNameLen, printLong(cl.getTotalLoadedClassCount()));
+ printValue("Total classes unloaded", maxNameLen, printLong(cl.getUnloadedClassCount()));
+
+ io.out.println("Operating system");
+ printValue("Name", maxNameLen, os.getName() + " version " + os.getVersion());
+ printValue("Architecture", maxNameLen, os.getArch());
+ printValue("Processors", maxNameLen, Integer.toString(os.getAvailableProcessors()));
+ try {
+ printValue("Total physical memory", maxNameLen, printSizeInKb(getSunOsValueAsLong(os, "getTotalPhysicalMemorySize")));
+ printValue("Free physical memory", maxNameLen, printSizeInKb(getSunOsValueAsLong(os, "getFreePhysicalMemorySize")));
+ printValue("Committed virtual memory", maxNameLen, printSizeInKb(getSunOsValueAsLong(os, "getCommittedVirtualMemorySize")));
+ printValue("Total swap space", maxNameLen, printSizeInKb(getSunOsValueAsLong(os, "getTotalSwapSpaceSize")));
+ printValue("Free swap space", maxNameLen, printSizeInKb(getSunOsValueAsLong(os, "getFreeSwapSpaceSize")));
+ } catch (Throwable t) {}
+
+ return null;
+ }
+
+ private long getSunOsValueAsLong(OperatingSystemMXBean os, String name) throws Exception {
+ Method mth = os.getClass().getMethod(name);
+ return (Long) mth.invoke(os);
+ }
+
+ private String printLong(long i) {
+ return fmtI.format(i);
+ }
+
+ private String printSizeInKb(double size) {
+ return fmtI.format((long) (size / 1024)) + " kbytes";
+ }
+
+ private String printDuration(double uptime) {
+ uptime /= 1000;
+ if (uptime < 60) {
+ return fmtD.format(uptime) + " seconds";
+ }
+ uptime /= 60;
+ if (uptime < 60) {
+ long minutes = (long) uptime;
+ String s = fmtI.format(minutes) + (minutes > 1 ? " minutes" : " minute");
+ return s;
+ }
+ uptime /= 60;
+ if (uptime < 24) {
+ long hours = (long) uptime;
+ long minutes = (long) ((uptime - hours) * 60);
+ String s = fmtI.format(hours) + (hours > 1 ? " hours" : " hour");
+ if (minutes != 0) {
+ s += " " + fmtI.format(minutes) + (minutes > 1 ? " minutes" : "minute");
+ }
+ return s;
+ }
+ uptime /= 24;
+ long days = (long) uptime;
+ long hours = (long) ((uptime - days) * 60);
+ String s = fmtI.format(days) + (days > 1 ? " days" : " day");
+ if (hours != 0) {
+ s += " " + fmtI.format(hours) + (hours > 1 ? " hours" : "hour");
+ }
+ return s;
+ }
+
+ void printSysValue(String prop, int pad) {
+ printValue(prop, pad, System.getProperty(prop));
+ }
+
+ void printValue(String name, int pad, String value) {
+ io.out.println(" " + renderer.render(AnsiRenderer.encode(StringUtils.rightPad(name, pad), AnsiCode.BOLD)) + " " + value);
+ }
+
+}
diff --git a/karaf/gshell/gshell-core/src/main/java/org/apache/servicemix/kernel/gshell/core/config/CommandParser.java b/karaf/gshell/gshell-core/src/main/java/org/apache/servicemix/kernel/gshell/core/config/CommandParser.java
new file mode 100644
index 0000000..45d9d7d
--- /dev/null
+++ b/karaf/gshell/gshell-core/src/main/java/org/apache/servicemix/kernel/gshell/core/config/CommandParser.java
@@ -0,0 +1,474 @@
+/*
+ * 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.servicemix.kernel.gshell.core.config;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.w3c.dom.Element;
+
+import org.apache.geronimo.gshell.command.Alias;
+import org.apache.geronimo.gshell.command.Link;
+import org.apache.geronimo.gshell.wisdom.command.AliasImpl;
+import org.apache.geronimo.gshell.wisdom.command.ConfigurableCommandCompleter;
+import org.apache.geronimo.gshell.wisdom.command.LinkImpl;
+import org.apache.geronimo.gshell.wisdom.registry.CommandLocationImpl;
+import org.apache.servicemix.kernel.gshell.core.CommandBundle;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.BeanDefinitionStoreException;
+import org.springframework.beans.factory.config.BeanDefinition;
+import org.springframework.beans.factory.config.BeanDefinitionHolder;
+import org.springframework.beans.factory.config.RuntimeBeanReference;
+import org.springframework.beans.factory.support.AbstractBeanDefinition;
+import org.springframework.beans.factory.support.BeanDefinitionBuilder;
+import org.springframework.beans.factory.support.GenericBeanDefinition;
+import org.springframework.beans.factory.support.ManagedList;
+import org.springframework.beans.factory.xml.AbstractBeanDefinitionParser;
+import org.springframework.beans.factory.xml.BeanDefinitionParserDelegate;
+import org.springframework.beans.factory.xml.ParserContext;
+import org.springframework.util.StringUtils;
+import org.springframework.util.xml.DomUtils;
+
+public class CommandParser extends AbstractBeanDefinitionParser {
+
+ public static final String ID = ID_ATTRIBUTE;
+
+ public static final String DESCRIPTION = "description";
+
+ public static final String PLUGIN_TEMPLATE = "pluginTemplate";
+
+ public static final String ACTION = "action";
+
+ public static final String ACTION_ID = "actionId";
+
+ public static final String COMMAND_TEMPLATE_SUFFIX = "CommandTemplate";
+
+ public static final String COMMAND_BUNDLE = "command-bundle";
+
+ public static final String NAME = "name";
+
+ public static final String LOCATION = "location";
+
+ public static final String COMMANDS = "commands";
+
+ public static final String COMMAND = "command";
+
+ public static final String TYPE = "type";
+
+ public static final String DOCUMENTER = "documenter";
+
+ public static final String COMPLETER = "completer";
+
+ public static final String COMPLETERS = "completers";
+
+ public static final String BEAN = "bean";
+
+ public static final String REF = "ref";
+
+ public static final String NULL = "null";
+
+ public static final String MESSAGE_SOURCE = "message-source";
+
+ public static final String MESSAGES = "messages";
+
+ public static final String PROTOTYPE = "prototype";
+
+ public static final String ALIAS = "alias";
+
+ public static final String ALIASES = "aliases";
+
+ public static final String LINK = "link";
+
+ public static final String LINKS = "links";
+
+ public static final String TARGET = "target";
+
+ @Override
+ protected boolean shouldGenerateId() {
+ return true;
+ }
+
+ @Override
+ protected boolean shouldGenerateIdAsFallback() {
+ return true;
+ }
+
+ protected AbstractBeanDefinition parseInternal(final Element element, final ParserContext context) {
+ assert element != null;
+ assert context != null;
+
+ Builder builder = new Builder(context);
+ BeanDefinitionBuilder plugin = builder.parseCommandBundle(element);
+ return plugin.getBeanDefinition();
+ }
+
+ /**
+ * Helper to deal with command type.
+ */
+ private enum CommandType
+ {
+ STATELESS,
+ STATEFUL;
+
+ public static CommandType parse(final String text) {
+ assert text != null;
+
+ return valueOf(text.toUpperCase());
+ }
+
+ public String getTemplateName() {
+ return name().toLowerCase() + COMMAND_TEMPLATE_SUFFIX;
+ }
+
+ public void wire(final BeanDefinitionBuilder command, final BeanDefinitionHolder action) {
+ assert command != null;
+ assert action != null;
+
+ switch (this) {
+ case STATELESS:
+ command.addPropertyReference(ACTION, action.getBeanName());
+ break;
+
+ case STATEFUL:
+ command.addPropertyValue(ACTION_ID, action.getBeanName());
+ break;
+ }
+ }
+ }
+
+ /**
+ * Helper to build plugin related bean definitions.
+ */
+ private class Builder
+ {
+ private final Logger log = LoggerFactory.getLogger(getClass());
+
+ private ParserContext context;
+
+ public Builder(final ParserContext context) {
+ assert context != null;
+
+ this.context = context;
+ }
+
+ private String resolveId(final Element element, final BeanDefinition def) throws BeanDefinitionStoreException {
+ assert element != null;
+ assert def != null;
+
+ if (shouldGenerateId()) {
+ return context.getReaderContext().generateBeanName(def);
+ }
+
+ String id = element.getAttribute(ID_ATTRIBUTE);
+
+ if (!StringUtils.hasText(id) && shouldGenerateIdAsFallback()) {
+ id = context.getReaderContext().generateBeanName(def);
+ }
+
+ return id;
+ }
+
+ @SuppressWarnings({"unchecked"})
+ private List<Element> getChildElements(final Element element, final String name) {
+ assert element != null;
+ assert name != null;
+
+ return DomUtils.getChildElementsByTagName(element, name);
+ }
+
+ @SuppressWarnings({"unchecked"})
+ private List<Element> getChildElements(final Element element, final String[] names) {
+ assert element != null;
+ assert names != null;
+
+ return DomUtils.getChildElementsByTagName(element, names);
+ }
+
+ @SuppressWarnings({"unchecked"})
+ private Element getChildElement(final Element element, final String name) {
+ assert element != null;
+ assert name != null;
+
+ List<Element> elements = DomUtils.getChildElementsByTagName(element, name);
+ if (elements != null && !elements.isEmpty()) {
+ return elements.get(0);
+ }
+ return null;
+ }
+
+ private BeanDefinitionParserDelegate createBeanDefinitionParserDelegate(final Element element) {
+ assert element != null;
+
+ BeanDefinitionParserDelegate parser = new BeanDefinitionParserDelegate(context.getReaderContext());
+ parser.initDefaults(element.getOwnerDocument().getDocumentElement());
+ return parser;
+ }
+
+ private BeanDefinitionHolder parseBeanDefinitionElement(final Element element) {
+ assert element != null;
+
+ BeanDefinitionParserDelegate parser = createBeanDefinitionParserDelegate(element);
+ return parser.parseBeanDefinitionElement(element);
+ }
+
+ private void parseAndApplyDescription(final Element element, final BeanDefinition def) {
+ assert element != null;
+ assert def != null;
+
+ Element desc = getChildElement(element, DESCRIPTION);
+ if (desc != null) {
+ if (def instanceof AbstractBeanDefinition) {
+ ((AbstractBeanDefinition)def).setDescription(desc.getTextContent());
+ }
+ }
+ }
+
+ private void parseAndApplyDescription(final Element element, final BeanDefinitionBuilder builder) {
+ assert element != null;
+ assert builder != null;
+
+ parseAndApplyDescription(element, builder.getRawBeanDefinition());
+ }
+
+ private BeanDefinitionHolder register(final BeanDefinitionHolder holder) {
+ assert holder != null;
+
+ registerBeanDefinition(holder, context.getRegistry());
+ return holder;
+ }
+
+ private BeanDefinitionHolder register(final BeanDefinition def, final String id) {
+ assert def != null;
+ assert id != null;
+
+ BeanDefinitionHolder holder = new BeanDefinitionHolder(def, id);
+ return register(holder);
+ }
+
+ //
+ // <gshell:command-bundle>
+ //
+
+ private BeanDefinitionBuilder parseCommandBundle(final Element element) {
+ assert element != null;
+
+ log.trace("Parse command bundle; element; {}", element);
+
+ BeanDefinitionBuilder bundle = BeanDefinitionBuilder.rootBeanDefinition(CommandBundle.class);
+ parseAndApplyDescription(element, bundle);
+
+ //
+ // TODO: Figure out how we can save the order of <gshell:command> and <gshell:link> so that 'help' displays them in the order they are defined
+ //
+
+ ManagedList commands = new ManagedList();
+ commands.addAll(parseCommands(element));
+ bundle.addPropertyValue(COMMANDS, commands);
+
+ ManagedList links = new ManagedList();
+ links.addAll(parseLinks(element));
+ bundle.addPropertyValue(LINKS, links);
+
+ ManagedList aliases = new ManagedList();
+ aliases.addAll(parseAliases(element));
+ bundle.addPropertyValue(ALIASES, aliases);
+
+ return bundle;
+ }
+
+ //
+ // <gshell:command>
+ //
+
+ private List<BeanDefinition> parseCommands(final Element element) {
+ assert element != null;
+
+ log.trace("Parse commands; element; {}", element);
+
+ List<BeanDefinition> commands = new ArrayList<BeanDefinition>();
+
+ List<Element> children = getChildElements(element, COMMAND);
+
+ for (Element child : children) {
+ BeanDefinitionBuilder command = parseCommand(child);
+ commands.add(command.getBeanDefinition());
+ }
+
+ return commands;
+ }
+
+ private BeanDefinitionBuilder parseCommand(final Element element) {
+ assert element != null;
+
+ log.trace("Parse command; element; {}", element);
+
+ CommandType type = CommandType.parse(element.getAttribute(TYPE));
+ BeanDefinitionBuilder command = BeanDefinitionBuilder.childBeanDefinition(type.getTemplateName());
+ parseAndApplyDescription(element, command);
+
+ Element child;
+
+ // Required children elements
+
+ String name = element.getAttribute(NAME);
+ BeanDefinition def = new GenericBeanDefinition();
+ def.setBeanClassName(CommandLocationImpl.class.getName());
+ def.getConstructorArgumentValues().addGenericArgumentValue(name);
+ command.addPropertyValue(LOCATION, def);
+
+ child = getChildElement(element, ACTION);
+ BeanDefinitionHolder action = parseCommandAction(child);
+ type.wire(command, action);
+
+ // Optional children elements
+
+ child = getChildElement(element, DOCUMENTER);
+ if (child != null) {
+ BeanDefinitionHolder holder = parseBeanDefinitionElement(child);
+ command.addPropertyValue(DOCUMENTER, holder.getBeanDefinition());
+ }
+
+ child = getChildElement(element, COMPLETER);
+ if (child != null) {
+ BeanDefinitionHolder holder = parseBeanDefinitionElement(child);
+ command.addPropertyValue(COMPLETER, holder.getBeanDefinition());
+ }
+
+ child = getChildElement(element, COMPLETERS);
+ if (child != null) {
+ BeanDefinitionBuilder completer = parseCommandCompleters(child);
+ command.addPropertyValue(COMPLETER, completer.getBeanDefinition());
+ }
+
+ child = getChildElement(element, MESSAGE_SOURCE);
+ if (child != null) {
+ BeanDefinitionHolder holder = parseBeanDefinitionElement(child);
+ command.addPropertyValue(MESSAGES, holder.getBeanDefinition());
+ }
+
+ //String id = resolveId(element, command.getBeanDefinition());
+ //BeanDefinitionHolder holder = register(command.getBeanDefinition(), id);
+
+ return command;
+ }
+
+ //
+ // <gshell:completers>
+ //
+
+ private BeanDefinitionBuilder parseCommandCompleters(final Element element) {
+ assert element != null;
+
+ BeanDefinitionBuilder completer = BeanDefinitionBuilder.rootBeanDefinition(ConfigurableCommandCompleter.class);
+
+ ManagedList completers = new ManagedList();
+
+ List<Element> children = getChildElements(element, new String[] {BEAN, REF, NULL});
+
+ for (Element child : children) {
+ if (DomUtils.nodeNameEquals(child, BEAN)) {
+ BeanDefinitionHolder holder = parseBeanDefinitionElement(child);
+ // noinspection unchecked
+ completers.add(holder.getBeanDefinition());
+ }
+ else if (DomUtils.nodeNameEquals(child, REF)) {
+ BeanDefinitionParserDelegate parser = createBeanDefinitionParserDelegate(child);
+ RuntimeBeanReference ref = (RuntimeBeanReference) parser.parsePropertySubElement(child, completer.getRawBeanDefinition());
+ // noinspection unchecked
+ completers.add(ref);
+ }
+ else if (DomUtils.nodeNameEquals(child, NULL)) {
+ // noinspection unchecked
+ completers.add(null);
+ }
+ }
+
+ completer.addConstructorArgValue(completers);
+
+ return completer;
+ }
+
+ //
+ // <gshell:action>
+ //
+
+ private BeanDefinitionHolder parseCommandAction(final Element element) {
+ assert element != null;
+
+ log.trace("Parse command action; element; {}", element);
+
+ // Construct the action
+ BeanDefinition action = parseBeanDefinitionElement(element).getBeanDefinition();
+
+ // All actions are configured as prototypes
+ action.setScope(PROTOTYPE);
+
+ // Generate id and register the bean
+ String id = resolveId(element, action);
+ return register(action, id);
+ }
+
+ //
+ // <gshell:link>
+ //
+
+ private List<Link> parseLinks(final Element element) {
+ assert element != null;
+
+ log.trace("Parse links; element; {}", element);
+
+ List<Link> links = new ArrayList<Link>();
+
+ List<Element> children = getChildElements(element, LINK);
+
+ for (Element child : children) {
+ String name = child.getAttribute(NAME);
+ String target = child.getAttribute(TARGET);
+
+ links.add(new LinkImpl(name, target));
+ }
+
+ return links;
+ }
+
+ //
+ // <gshell:alias>
+ //
+
+ private List<Alias> parseAliases(final Element element) {
+ assert element != null;
+
+ log.trace("Parse aliases; element; {}", element);
+
+ List<Alias> aliases = new ArrayList<Alias>();
+
+ List<Element> children = getChildElements(element, ALIAS);
+
+ for (Element child : children) {
+ String name = child.getAttribute(NAME);
+ String alias = child.getAttribute(ALIAS);
+
+ aliases.add(new AliasImpl(name, alias));
+ }
+
+ return aliases;
+ }
+ }
+}
diff --git a/karaf/gshell/gshell-core/src/main/java/org/apache/servicemix/kernel/gshell/core/config/NamespaceHandler.java b/karaf/gshell/gshell-core/src/main/java/org/apache/servicemix/kernel/gshell/core/config/NamespaceHandler.java
new file mode 100644
index 0000000..3e464d3
--- /dev/null
+++ b/karaf/gshell/gshell-core/src/main/java/org/apache/servicemix/kernel/gshell/core/config/NamespaceHandler.java
@@ -0,0 +1,29 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.servicemix.kernel.gshell.core.config;
+
+import org.springframework.beans.factory.xml.NamespaceHandlerSupport;
+
+public class NamespaceHandler extends NamespaceHandlerSupport {
+
+ public void init() {
+ registerBeanDefinitionParser(CommandParser.COMMAND_BUNDLE, new CommandParser());
+ }
+
+}
diff --git a/karaf/gshell/gshell-core/src/main/java/org/apache/servicemix/kernel/gshell/core/sshd/BogusPasswordAuthenticator.java b/karaf/gshell/gshell-core/src/main/java/org/apache/servicemix/kernel/gshell/core/sshd/BogusPasswordAuthenticator.java
new file mode 100644
index 0000000..34e2527
--- /dev/null
+++ b/karaf/gshell/gshell-core/src/main/java/org/apache/servicemix/kernel/gshell/core/sshd/BogusPasswordAuthenticator.java
@@ -0,0 +1,29 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.servicemix.kernel.gshell.core.sshd;
+
+import org.apache.sshd.server.PasswordAuthenticator;
+
+public class BogusPasswordAuthenticator implements PasswordAuthenticator {
+
+ public Object authenticate(String username, String password) {
+ return (username != null && username.equals(password)) ? username : null;
+ }
+
+}
diff --git a/karaf/gshell/gshell-core/src/main/java/org/apache/servicemix/kernel/gshell/core/sshd/SshServerFactory.java b/karaf/gshell/gshell-core/src/main/java/org/apache/servicemix/kernel/gshell/core/sshd/SshServerFactory.java
new file mode 100644
index 0000000..fbf9041
--- /dev/null
+++ b/karaf/gshell/gshell-core/src/main/java/org/apache/servicemix/kernel/gshell/core/sshd/SshServerFactory.java
@@ -0,0 +1,58 @@
+/*
+ * 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.servicemix.kernel.gshell.core.sshd;
+
+import org.apache.sshd.SshServer;
+
+public class SshServerFactory {
+
+ private SshServer server;
+
+ private boolean start;
+
+ public SshServerFactory(SshServer server) {
+ this.server = server;
+ }
+
+ public boolean isStart() {
+ return start;
+ }
+
+ public void setStart(boolean start) {
+ this.start = start;
+ }
+
+ public void start() throws Exception {
+ if (start) {
+ try {
+ server.start();
+ } catch (Exception e) {
+ e.printStackTrace();
+ throw e;
+ }
+ }
+ }
+
+ public void stop() throws Exception {
+ if (start) {
+ server.stop();
+ }
+ }
+
+}
diff --git a/karaf/gshell/gshell-core/src/main/java/org/apache/servicemix/kernel/gshell/core/vfs/mvn/MvnFileObject.java b/karaf/gshell/gshell-core/src/main/java/org/apache/servicemix/kernel/gshell/core/vfs/mvn/MvnFileObject.java
new file mode 100644
index 0000000..41a2bb8
--- /dev/null
+++ b/karaf/gshell/gshell-core/src/main/java/org/apache/servicemix/kernel/gshell/core/vfs/mvn/MvnFileObject.java
@@ -0,0 +1,56 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.servicemix.kernel.gshell.core.vfs.mvn;
+
+import java.net.MalformedURLException;
+import java.net.URL;
+
+import org.apache.commons.httpclient.URIException;
+import org.apache.commons.vfs.FileName;
+import org.apache.commons.vfs.FileSystemException;
+import org.apache.commons.vfs.provider.URLFileName;
+import org.apache.commons.vfs.provider.url.UrlFileObject;
+
+public class MvnFileObject extends UrlFileObject {
+
+ public MvnFileObject(MvnFileSystem fs, FileName fileName) {
+ super(fs, fileName);
+ }
+
+ protected URL createURL(final FileName name) throws MalformedURLException, FileSystemException, URIException
+ {
+ String url;
+ if (name instanceof URLFileName)
+ {
+ URLFileName urlName = (URLFileName) getName();
+
+ // TODO: charset
+ url = urlName.getURIEncoded(null);
+ }
+ else
+ {
+ url = getName().getURI();
+ }
+ if (url.startsWith("mvn:///")) {
+ url = "mvn:" + url.substring("mvn:///".length());
+ }
+ return new URL(url);
+ }
+
+}
diff --git a/karaf/gshell/gshell-core/src/main/java/org/apache/servicemix/kernel/gshell/core/vfs/mvn/MvnFileProvider.java b/karaf/gshell/gshell-core/src/main/java/org/apache/servicemix/kernel/gshell/core/vfs/mvn/MvnFileProvider.java
new file mode 100644
index 0000000..7d88cd6
--- /dev/null
+++ b/karaf/gshell/gshell-core/src/main/java/org/apache/servicemix/kernel/gshell/core/vfs/mvn/MvnFileProvider.java
@@ -0,0 +1,66 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.servicemix.kernel.gshell.core.vfs.mvn;
+
+import java.net.MalformedURLException;
+import java.net.URL;
+
+import org.apache.commons.vfs.FileName;
+import org.apache.commons.vfs.FileObject;
+import org.apache.commons.vfs.FileSystem;
+import org.apache.commons.vfs.FileSystemException;
+import org.apache.commons.vfs.FileSystemOptions;
+import org.apache.commons.vfs.provider.url.UrlFileProvider;
+
+public class MvnFileProvider extends UrlFileProvider {
+
+ /**
+ * Locates a file object, by absolute URI.
+ */
+ public synchronized FileObject findFile(final FileObject baseFile,
+ final String uri,
+ final FileSystemOptions fileSystemOptions)
+ throws FileSystemException
+ {
+ try
+ {
+ final URL url = new URL(uri);
+
+ URL rootUrl = new URL(url, "/");
+ final String key = this.getClass().getName() + rootUrl.toString();
+ FileSystem fs = findFileSystem(key, fileSystemOptions);
+ if (fs == null)
+ {
+ String extForm = rootUrl.toExternalForm();
+ final FileName rootName = getContext().parseURI(extForm);
+ // final FileName rootName =
+ // new BasicFileName(rootUrl, FileName.ROOT_PATH);
+ fs = new MvnFileSystem(rootName, fileSystemOptions);
+ addFileSystem(key, fs);
+ }
+ return fs.resolveFile(url.getPath());
+ }
+ catch (final MalformedURLException e)
+ {
+ throw new FileSystemException("vfs.provider.url/badly-formed-uri.error", uri, e);
+ }
+ }
+
+
+}
diff --git a/karaf/gshell/gshell-core/src/main/java/org/apache/servicemix/kernel/gshell/core/vfs/mvn/MvnFileSystem.java b/karaf/gshell/gshell-core/src/main/java/org/apache/servicemix/kernel/gshell/core/vfs/mvn/MvnFileSystem.java
new file mode 100644
index 0000000..7583eb5
--- /dev/null
+++ b/karaf/gshell/gshell-core/src/main/java/org/apache/servicemix/kernel/gshell/core/vfs/mvn/MvnFileSystem.java
@@ -0,0 +1,35 @@
+/*
+ * 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.servicemix.kernel.gshell.core.vfs.mvn;
+
+import org.apache.commons.vfs.FileName;
+import org.apache.commons.vfs.FileObject;
+import org.apache.commons.vfs.FileSystemOptions;
+import org.apache.commons.vfs.provider.url.UrlFileSystem;
+
+public class MvnFileSystem extends UrlFileSystem {
+
+ protected MvnFileSystem(FileName fileName, FileSystemOptions fileSystemOptions) {
+ super(fileName, fileSystemOptions);
+ }
+
+ protected FileObject createFile(FileName fileName) {
+ return new MvnFileObject(this, fileName);
+ }
+}
diff --git a/karaf/gshell/gshell-core/src/main/resources/META-INF/spring.handlers b/karaf/gshell/gshell-core/src/main/resources/META-INF/spring.handlers
new file mode 100644
index 0000000..2315764
--- /dev/null
+++ b/karaf/gshell/gshell-core/src/main/resources/META-INF/spring.handlers
@@ -0,0 +1,24 @@
+##
+## 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.
+##
+
+##
+## $Rev: 697807 $ $Date: 2008-09-22 20:12:04 +0700 (Mon, 22 Sep 2008) $
+##
+
+http\://servicemix.apache.org/schema/servicemix-gshell=org.apache.servicemix.kernel.gshell.core.config.NamespaceHandler
\ No newline at end of file
diff --git a/karaf/gshell/gshell-core/src/main/resources/META-INF/spring.schemas b/karaf/gshell/gshell-core/src/main/resources/META-INF/spring.schemas
new file mode 100644
index 0000000..67eca68
--- /dev/null
+++ b/karaf/gshell/gshell-core/src/main/resources/META-INF/spring.schemas
@@ -0,0 +1,24 @@
+##
+## 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.
+##
+
+##
+## $Rev: 697807 $ $Date: 2008-09-22 20:12:04 +0700 (Mon, 22 Sep 2008) $
+##
+
+http\://servicemix.apache.org/schema/servicemix-gshell/servicemix-gshell.xsd=org/apache/servicemix/kernel/gshell/core/servicemix-gshell.xsd
diff --git a/karaf/gshell/gshell-core/src/main/resources/META-INF/spring/gshell-commands.xml b/karaf/gshell/gshell-core/src/main/resources/META-INF/spring/gshell-commands.xml
new file mode 100644
index 0000000..dbcafd3
--- /dev/null
+++ b/karaf/gshell/gshell-core/src/main/resources/META-INF/spring/gshell-commands.xml
@@ -0,0 +1,277 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ 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.
+
+-->
+<beans xmlns="http://www.springframework.org/schema/beans"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:util="http://www.springframework.org/schema/util"
+ xmlns:gshell="http://servicemix.apache.org/schema/servicemix-gshell"
+ xsi:schemaLocation="
+ http://www.springframework.org/schema/beans
+ http://www.springframework.org/schema/beans/spring-beans.xsd
+ http://www.springframework.org/schema/util
+ http://www.springframework.org/schema/util/spring-util.xsd
+ http://servicemix.apache.org/schema/servicemix-gshell
+ http://servicemix.apache.org/schema/servicemix-gshell/servicemix-gshell.xsd"
+ default-autowire="no"
+ default-dependency-check="none"
+ default-init-method="init"
+ default-destroy-method="destroy">
+
+ <import resource="classpath:org/apache/servicemix/kernel/gshell/core/commands.xml" />
+
+ <bean id="vfsCommandActionTemplate" abstract="true">
+ <property name="fileSystemAccess" ref="fileSystemAccess"/>
+ </bean>
+
+ <gshell:command-bundle>
+ <gshell:command name="about">
+ <gshell:action class="org.apache.geronimo.gshell.commands.builtin.AboutAction">
+ <constructor-arg ref="application"/>
+ </gshell:action>
+ </gshell:command>
+
+ <gshell:command name="help">
+ <gshell:action class="org.apache.geronimo.gshell.commands.builtin.HelpAction">
+ <constructor-arg ref="commandResolver"/>
+ </gshell:action>
+ <gshell:completers>
+ <bean class="org.apache.geronimo.gshell.console.completer.AggregateCompleter">
+ <constructor-arg>
+ <list>
+ <ref bean="aliasNameCompleter"/>
+ <ref bean="commandNameCompleter"/>
+ </list>
+ </constructor-arg>
+ </bean>
+ <null/>
+ </gshell:completers>
+ </gshell:command>
+
+ <gshell:command name="exit">
+ <gshell:action class="org.apache.geronimo.gshell.commands.builtin.ExitAction"/>
+ </gshell:command>
+
+ <gshell:link name="quit" target="exit"/>
+
+ <gshell:command name="echo">
+ <gshell:action class="org.apache.geronimo.gshell.commands.builtin.EchoAction"/>
+ </gshell:command>
+
+ <gshell:command name="clear" type="stateless">
+ <gshell:action class="org.apache.geronimo.gshell.commands.builtin.ClearAction"/>
+ </gshell:command>
+
+ <gshell:command name="source">
+ <gshell:action class="org.apache.geronimo.gshell.commands.builtin.SourceAction">
+ <constructor-arg ref="commandLineExecutor"/>
+ <constructor-arg ref="fileSystemAccess"/>
+ </gshell:action>
+ <gshell:completers>
+ <ref bean="fileObjectNameCompleter"/>
+ <null/>
+ </gshell:completers>
+ </gshell:command>
+
+ <gshell:command name="set">
+ <gshell:action class="org.apache.geronimo.gshell.commands.builtin.SetAction"/>
+ </gshell:command>
+
+ <gshell:command name="unset">
+ <gshell:action class="org.apache.geronimo.gshell.commands.builtin.UnsetAction"/>
+ <gshell:completers>
+ <ref bean="variableNameCompleter"/>
+ <null/>
+ </gshell:completers>
+ </gshell:command>
+
+ <gshell:command name="alias">
+ <gshell:action class="org.apache.geronimo.gshell.commands.builtin.AliasAction">
+ <constructor-arg ref="aliasRegistry"/>
+ </gshell:action>
+ </gshell:command>
+
+ <gshell:command name="unalias">
+ <gshell:action class="org.apache.geronimo.gshell.commands.builtin.UnaliasAction">
+ <constructor-arg ref="aliasRegistry"/>
+ </gshell:action>
+ <gshell:completers>
+ <ref bean="aliasNameCompleter"/>
+ <null/>
+ </gshell:completers>
+ </gshell:command>
+
+ <gshell:command name="history">
+ <gshell:action class="org.apache.geronimo.gshell.commands.builtin.HistoryAction"/>
+ </gshell:command>
+
+ <gshell:command name="info">
+ <gshell:action class="org.apache.servicemix.kernel.gshell.core.commands.InfoAction">
+ <constructor-arg ref="branding" />
+ </gshell:action>
+ </gshell:command>
+ </gshell:command-bundle>
+
+ <gshell:command-bundle>
+ <gshell:command name="ssh">
+ <gshell:action class="org.apache.geronimo.gshell.commands.ssh.SshAction"/>
+ </gshell:command>
+
+ <gshell:command name="sshd">
+ <gshell:action class="org.apache.geronimo.gshell.commands.ssh.SshServerAction"/>
+ </gshell:command>
+ </gshell:command-bundle>
+
+ <gshell:command-bundle>
+ <gshell:command name="exec">
+ <gshell:action class="org.apache.geronimo.gshell.commands.shell.ExecuteAction"/>
+ </gshell:command>
+
+ <gshell:command name="java">
+ <gshell:action class="org.apache.geronimo.gshell.commands.shell.JavaAction"/>
+ </gshell:command>
+
+ <gshell:command name="sleep">
+ <gshell:action class="org.apache.geronimo.gshell.commands.shell.SleepAction"/>
+ </gshell:command>
+
+ <gshell:command name="date">
+ <gshell:action class="org.apache.geronimo.gshell.commands.shell.DateAction"/>
+ </gshell:command>
+
+ <gshell:command name="edit">
+ <gshell:action class="org.apache.geronimo.gshell.commands.shell.EditAction">
+ <property name="fileSystemAccess" ref="fileSystemAccess"/>
+ </gshell:action>
+ <gshell:completers>
+ <ref bean="fileObjectNameCompleter"/>
+ <null/>
+ </gshell:completers>
+ </gshell:command>
+
+ <gshell:command name="find">
+ <gshell:action class="org.apache.geronimo.gshell.commands.shell.FindAction">
+ <property name="fileSystemAccess" ref="fileSystemAccess"/>
+ </gshell:action>
+ <gshell:completers>
+ <ref bean="fileObjectNameCompleter"/>
+ <null/>
+ </gshell:completers>
+ </gshell:command>
+
+ <gshell:command name="sort">
+ <gshell:action class="org.apache.geronimo.gshell.commands.text.SortAction">
+ <property name="fileSystemAccess" ref="fileSystemAccess"/>
+ </gshell:action>
+ <gshell:completers>
+ <ref bean="fileObjectNameCompleter"/>
+ <null/>
+ </gshell:completers>
+ </gshell:command>
+ </gshell:command-bundle>
+
+ <gshell:command-bundle>
+ <gshell:command name="hostname">
+ <gshell:action class="org.apache.geronimo.gshell.commands.network.HostnameAction"/>
+ </gshell:command>
+ </gshell:command-bundle>
+
+ <gshell:command-bundle>
+ <gshell:link name="print" target="echo"/>
+
+ <gshell:command name="printf">
+ <gshell:action class="org.apache.geronimo.gshell.commands.text.PrintfAction"/>
+ </gshell:command>
+
+ <gshell:command name="cat">
+ <gshell:action class="org.apache.geronimo.gshell.commands.text.CatAction">
+ <property name="fileSystemAccess" ref="fileSystemAccess"/>
+ </gshell:action>
+ <gshell:completers>
+ <ref bean="fileObjectNameCompleter"/>
+ <null/>
+ </gshell:completers>
+ </gshell:command>
+
+ <gshell:command name="grep">
+ <gshell:action class="org.apache.geronimo.gshell.commands.text.GrepAction"/>
+ </gshell:command>
+ </gshell:command-bundle>
+
+ <gshell:command-bundle>
+ <gshell:command name="cd">
+ <gshell:action class="org.apache.geronimo.gshell.commands.file.ChangeDirectoryAction" parent="vfsCommandActionTemplate"/>
+ <gshell:completers>
+ <ref bean="fileObjectNameCompleter"/>
+ <null/>
+ </gshell:completers>
+ </gshell:command>
+
+ <gshell:command name="pwd" type="stateless">
+ <gshell:action class="org.apache.geronimo.gshell.commands.file.CurrentDirectoryAction" parent="vfsCommandActionTemplate"/>
+ </gshell:command>
+
+ <gshell:command name="ls">
+ <gshell:action class="org.apache.geronimo.gshell.commands.file.ListDirectoryAction" parent="vfsCommandActionTemplate"/>
+ <gshell:completers>
+ <ref bean="fileObjectNameCompleter"/>
+ <null/>
+ </gshell:completers>
+ </gshell:command>
+
+ <gshell:link name="dir" target="ls"/>
+
+ <gshell:command name="cp">
+ <gshell:action class="org.apache.geronimo.gshell.commands.file.CopyAction" parent="vfsCommandActionTemplate"/>
+ <gshell:completers>
+ <ref bean="fileObjectNameCompleter"/>
+ <ref bean="fileObjectNameCompleter"/>
+ <null/>
+ </gshell:completers>
+ </gshell:command>
+
+ <gshell:link name="copy" target="cp"/>
+
+ <gshell:command name="rm">
+ <gshell:action class="org.apache.geronimo.gshell.commands.file.RemoveAction" parent="vfsCommandActionTemplate"/>
+ <gshell:completers>
+ <ref bean="fileObjectNameCompleter"/>
+ <null/>
+ </gshell:completers>
+ </gshell:command>
+
+ <gshell:link name="del" target="rm"/>
+
+ <gshell:command name="fileinfo">
+ <gshell:action class="org.apache.geronimo.gshell.commands.file.FileInfoAction" parent="vfsCommandActionTemplate"/>
+ <gshell:completers>
+ <ref bean="fileObjectNameCompleter"/>
+ <null/>
+ </gshell:completers>
+ </gshell:command>
+
+ <gshell:command name="touch">
+ <gshell:action class="org.apache.geronimo.gshell.commands.file.TouchAction" parent="vfsCommandActionTemplate"/>
+ <gshell:completers>
+ <ref bean="fileObjectNameCompleter"/>
+ <null/>
+ </gshell:completers>
+ </gshell:command>
+ </gshell:command-bundle>
+
+</beans>
diff --git a/karaf/gshell/gshell-core/src/main/resources/META-INF/spring/gshell-local.xml b/karaf/gshell/gshell-core/src/main/resources/META-INF/spring/gshell-local.xml
new file mode 100644
index 0000000..a047339
--- /dev/null
+++ b/karaf/gshell/gshell-core/src/main/resources/META-INF/spring/gshell-local.xml
@@ -0,0 +1,50 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ 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.
+
+-->
+<beans xmlns="http://www.springframework.org/schema/beans"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:util="http://www.springframework.org/schema/util"
+ xmlns:osgi="http://www.springframework.org/schema/osgi"
+ xsi:schemaLocation="
+ http://www.springframework.org/schema/beans
+ http://www.springframework.org/schema/beans/spring-beans.xsd
+ http://www.springframework.org/schema/util
+ http://www.springframework.org/schema/util/spring-util.xsd
+ http://www.springframework.org/schema/osgi
+ http://www.springframework.org/schema/osgi/spring-osgi.xsd"
+ default-autowire="no"
+ default-dependency-check="none"
+ default-init-method="init"
+ default-destroy-method="destroy">
+
+ <bean id="localShellWrapped" parent="shell" init-method="init" destroy-method="close"/>
+
+ <bean id="localShell" class="org.apache.servicemix.kernel.gshell.core.ShellWrapper">
+ <constructor-arg ref="localShellWrapped" />
+ </bean>
+
+ <osgi:reference id="mainService" interface="org.apache.servicemix.kernel.main.spi.MainService"/>
+
+ <bean id="localConsole" class="org.apache.servicemix.kernel.gshell.core.LocalConsole">
+ <property name="createLocalShell" value="${servicemix.startLocalConsole}"/>
+ <property name="shell" ref="localShell"/>
+ <property name="mainService" ref="mainService" />
+ </bean>
+
+</beans>
\ No newline at end of file
diff --git a/karaf/gshell/gshell-core/src/main/resources/META-INF/spring/gshell-osgi.xml b/karaf/gshell/gshell-core/src/main/resources/META-INF/spring/gshell-osgi.xml
new file mode 100644
index 0000000..b99626a
--- /dev/null
+++ b/karaf/gshell/gshell-core/src/main/resources/META-INF/spring/gshell-osgi.xml
@@ -0,0 +1,76 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ 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.
+
+-->
+<beans xmlns="http://www.springframework.org/schema/beans"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:ctx="http://www.springframework.org/schema/context"
+ xmlns:osgi="http://www.springframework.org/schema/osgi"
+ xmlns:osgix="http://www.springframework.org/schema/osgi-compendium"
+ xmlns:util="http://www.springframework.org/schema/util"
+ xsi:schemaLocation="
+ http://www.springframework.org/schema/beans
+ http://www.springframework.org/schema/beans/spring-beans.xsd
+ http://www.springframework.org/schema/context
+ http://www.springframework.org/schema/context/spring-context.xsd
+ http://www.springframework.org/schema/util
+ http://www.springframework.org/schema/util/spring-util.xsd
+ http://www.springframework.org/schema/osgi
+ http://www.springframework.org/schema/osgi/spring-osgi.xsd
+ http://www.springframework.org/schema/osgi-compendium
+ http://www.springframework.org/schema/osgi-compendium/spring-osgi-compendium.xsd"
+ default-autowire="no"
+ default-dependency-check="none"
+ default-init-method="init"
+ default-destroy-method="destroy">
+
+ <bean id="osgiCommandRegistry" class="org.apache.servicemix.kernel.gshell.core.OsgiCommandRegistry">
+ <constructor-arg ref="commandRegistry" />
+ </bean>
+
+ <bean id="osgiAliasRegistry" class="org.apache.servicemix.kernel.gshell.core.OsgiAliasRegistry">
+ <constructor-arg ref="aliasRegistry" />
+ </bean>
+
+ <osgi:list id="osgiCommands" interface="org.apache.geronimo.gshell.command.Command" cardinality="0..N">
+ <osgi:listener ref="osgiCommandRegistry" bind-method="register" unbind-method="unregister" />
+ </osgi:list>
+
+ <osgi:list id="osgiLinkCommands" interface="org.apache.geronimo.gshell.command.Link" cardinality="0..N">
+ <osgi:listener ref="osgiCommandRegistry" bind-method="register" unbind-method="unregister" />
+ </osgi:list>
+
+ <osgi:list id="osgiAliases" interface="org.apache.geronimo.gshell.command.Alias" cardinality="0..N">
+ <osgi:listener ref="osgiAliasRegistry" bind-method="register" unbind-method="unregister" />
+ </osgi:list>
+
+ <osgi:service ref="localShell" interface="org.apache.geronimo.gshell.shell.Shell">
+ </osgi:service>
+
+ <osgi:service ref="commandLineExecutor" interface="org.apache.geronimo.gshell.commandline.CommandLineExecutor">
+ </osgi:service>
+
+ <osgix:cm-properties id="cmProps" persistent-id="org.apache.servicemix.shell">
+ <prop key="sshPort">8101</prop>
+ <prop key="sshRealm">servicemix</prop>
+ <prop key="hostKey">${servicemix.base}/etc/host.key</prop>
+ </osgix:cm-properties>
+
+ <ctx:property-placeholder properties-ref="cmProps" />
+
+</beans>
\ No newline at end of file
diff --git a/karaf/gshell/gshell-core/src/main/resources/META-INF/spring/gshell-remote.xml b/karaf/gshell/gshell-core/src/main/resources/META-INF/spring/gshell-remote.xml
new file mode 100644
index 0000000..d68ee51
--- /dev/null
+++ b/karaf/gshell/gshell-core/src/main/resources/META-INF/spring/gshell-remote.xml
@@ -0,0 +1,91 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ 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.
+
+-->
+<beans xmlns="http://www.springframework.org/schema/beans"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:util="http://www.springframework.org/schema/util"
+ xmlns:osgi="http://www.springframework.org/schema/osgi"
+ xmlns:jaas="http://servicemix.apache.org/jaas"
+ xsi:schemaLocation="
+ http://www.springframework.org/schema/beans
+ http://www.springframework.org/schema/beans/spring-beans.xsd
+ http://www.springframework.org/schema/util
+ http://www.springframework.org/schema/util/spring-util.xsd
+ http://www.springframework.org/schema/osgi
+ http://www.springframework.org/schema/osgi/spring-osgi.xsd
+ http://servicemix.apache.org/jaas
+ http://servicemix.apache.org/schema/servicemix-jaas.xsd"
+ default-autowire="no"
+ default-dependency-check="none"
+ default-init-method="init"
+ default-destroy-method="destroy">
+
+ <bean name="sshClient" class="org.apache.sshd.SshClient" factory-method="setUpDefaultClient" init-method="start" destroy-method="stop">
+ </bean>
+
+ <bean name="sshServer" class="org.apache.sshd.SshServer" factory-method="setUpDefaultServer" scope="prototype">
+ <property name="port" value="${sshPort}" />
+ <property name="shellFactory">
+ <bean class="org.apache.geronimo.gshell.commands.ssh.ShellFactoryImpl">
+ <property name="application" ref="application" />
+ <property name="completers">
+ <list>
+ <ref bean="commandsCompleter"/>
+ <ref bean="aliasNameCompleter"/>
+ </list>
+ </property>
+ <property name="executor" ref="commandLineExecutor" />
+ <property name="prompter">
+ <bean class="org.apache.geronimo.gshell.wisdom.shell.ConsolePrompterImpl">
+ <constructor-arg ref="application"/>
+ </bean>
+ </property>
+ <property name="errorHandler">
+ <bean class="org.apache.geronimo.gshell.wisdom.shell.ConsoleErrorHandlerImpl" />
+ </property>
+ <property name="history">
+ <bean class="org.apache.geronimo.gshell.wisdom.shell.HistoryImpl">
+ <constructor-arg ref="application"/>
+ </bean>
+ </property>
+ </bean>
+ </property>
+ <property name="keyPairProvider" ref="keyPairProvider" />
+ <property name="passwordAuthenticator" ref="passwordAuthenticator" />
+ </bean>
+
+ <bean name="keyPairProvider" class="org.apache.sshd.server.keyprovider.SimpleGeneratorHostKeyProvider">
+ <property name="path" value="${hostKey}" />
+ </bean>
+ <bean name="passwordAuthenticator" class="org.apache.sshd.server.jaas.JaasPasswordAuthenticator">
+ <property name="domain" value="${sshRealm}" />
+ </bean>
+
+ <bean id="sshServerFactory" class="org.apache.servicemix.kernel.gshell.core.sshd.SshServerFactory" init-method="start" destroy-method="stop">
+ <constructor-arg ref="sshServer" />
+ <property name="start" value="${servicemix.startRemoteShell}" />
+ </bean>
+
+ <!--
+ <jaas:config id="SshServer" rank="-1">
+ <jaas:module className="org.apache.geronimo.gshell.remote.server.auth.BogusLoginModule" flags="required" />
+ </jaas:config>
+ -->
+
+</beans>
\ No newline at end of file
diff --git a/karaf/gshell/gshell-core/src/main/resources/META-INF/spring/gshell-vfs.xml b/karaf/gshell/gshell-core/src/main/resources/META-INF/spring/gshell-vfs.xml
new file mode 100644
index 0000000..3992f54
--- /dev/null
+++ b/karaf/gshell/gshell-core/src/main/resources/META-INF/spring/gshell-vfs.xml
@@ -0,0 +1,133 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ 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.
+
+-->
+<beans xmlns="http://www.springframework.org/schema/beans"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:util="http://www.springframework.org/schema/util"
+ xsi:schemaLocation="
+ http://www.springframework.org/schema/beans
+ http://www.springframework.org/schema/beans/spring-beans.xsd
+ http://www.springframework.org/schema/util
+ http://www.springframework.org/schema/util/spring-util.xsd
+ http://servicemix.apache.org/schema/servicemix-gshell
+ http://servicemix.apache.org/schema/servicemix-gshell/servicemix-gshell.xsd"
+ default-autowire="no"
+ default-dependency-check="none"
+ default-init-method="init"
+ default-destroy-method="destroy">
+
+ <bean id="fileSystemAccess" class="org.apache.geronimo.gshell.vfs.FileSystemAccessImpl">
+ <constructor-arg ref="fileSystemManager"/>
+ </bean>
+
+ <bean id="fileObjectNameCompleter" class="org.apache.geronimo.gshell.vfs.FileObjectNameCompleter">
+ <constructor-arg ref="fileSystemAccess"/>
+ </bean>
+
+ <bean class="org.springframework.beans.factory.config.CustomEditorConfigurer">
+ <property name="customEditors">
+ <map>
+ <entry key="org.apache.commons.vfs.CacheStrategy">
+ <bean class="org.apache.geronimo.gshell.vfs.config.CacheStrategyEditor"/>
+ </entry>
+ </map>
+ </property>
+ </bean>
+
+ <!--
+ TODO: Set tempDir File arg in constructor to set the temporary location, may need 2 replicators?
+ -->
+ <bean id="defaultFileReplicator" class="org.apache.commons.vfs.impl.DefaultFileReplicator"/>
+
+ <bean id="fileSystemManager" class="org.apache.geronimo.gshell.vfs.config.FileSystemManagerFactoryBean">
+ <property name="filesCache">
+ <bean class="org.apache.commons.vfs.cache.SoftRefFilesCache"/>
+ </property>
+
+ <property name="cacheStrategy" value="ON_RESOLVE"/>
+
+ <property name="fileReplicator">
+ <bean class="org.apache.commons.vfs.impl.PrivilegedFileReplicator">
+ <constructor-arg ref="defaultFileReplicator"/>
+ </bean>
+ </property>
+
+ <!--
+ TODO: Try and root the temporary store under ${gshell.home}/tmp or something
+ -->
+ <property name="temporaryFileStore">
+ <ref bean="defaultFileReplicator"/>
+ </property>
+
+ <property name="fileContentInfoFactory">
+ <bean class="org.apache.commons.vfs.impl.FileContentInfoFilenameFactory"/>
+ </property>
+
+ <property name="defaultProvider">
+ <bean class="org.apache.commons.vfs.provider.url.UrlFileProvider"/>
+ </property>
+ </bean>
+
+ <bean class="org.apache.geronimo.gshell.vfs.config.FileProviderConfigurer">
+ <property name="fileSystemManager" ref="fileSystemManager"/>
+ <property name="scheme" value="tmp"/>
+ <property name="provider">
+ <bean class="org.apache.commons.vfs.provider.temp.TemporaryFileProvider"/>
+ </property>
+ </bean>
+
+ <bean class="org.apache.geronimo.gshell.vfs.config.FileProviderConfigurer">
+ <property name="fileSystemManager" ref="fileSystemManager"/>
+ <property name="scheme" value="ram"/>
+ <property name="provider">
+ <bean class="org.apache.commons.vfs.provider.ram.RamFileProvider"/>
+ </property>
+ </bean>
+
+ <bean class="org.apache.geronimo.gshell.vfs.config.FileProviderConfigurer">
+ <property name="fileSystemManager" ref="fileSystemManager"/>
+ <property name="scheme" value="file"/>
+ <property name="provider">
+ <bean class="org.apache.commons.vfs.provider.local.DefaultLocalFileProvider"/>
+ </property>
+ </bean>
+
+ <bean class="org.apache.geronimo.gshell.vfs.config.FileProviderConfigurer">
+ <property name="fileSystemManager" ref="fileSystemManager"/>
+ <property name="scheme" value="mvn"/>
+ <property name="provider">
+ <bean class="org.apache.servicemix.kernel.gshell.core.vfs.mvn.MvnFileProvider"/>
+ </property>
+ </bean>
+
+ <bean id="metaDataRegistry" class="org.apache.geronimo.gshell.vfs.provider.meta.data.MetaDataRegistryImpl">
+ <constructor-arg ref="eventManager" />
+ </bean>
+
+ <bean id="metaFileProviderConfigurer" class="org.apache.geronimo.gshell.vfs.config.FileProviderConfigurer">
+ <property name="fileSystemManager" ref="fileSystemManager"/>
+ <property name="scheme" value="meta"/>
+ <property name="provider">
+ <bean class="org.apache.geronimo.gshell.vfs.provider.meta.MetaFileProvider">
+ <constructor-arg ref="metaDataRegistry"/>
+ </bean>
+ </property>
+ </bean>
+
+</beans>
\ No newline at end of file
diff --git a/karaf/gshell/gshell-core/src/main/resources/META-INF/spring/gshell.xml b/karaf/gshell/gshell-core/src/main/resources/META-INF/spring/gshell.xml
new file mode 100644
index 0000000..8bc494e
--- /dev/null
+++ b/karaf/gshell/gshell-core/src/main/resources/META-INF/spring/gshell.xml
@@ -0,0 +1,155 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ 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.
+
+-->
+<beans xmlns="http://www.springframework.org/schema/beans"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:util="http://www.springframework.org/schema/util" xmlns:osgi="http://www.springframework.org/schema/osgi"
+ xsi:schemaLocation="http://www.springframework.org/schema/beans
+ http://www.springframework.org/schema/beans/spring-beans.xsd
+ http://www.springframework.org/schema/util
+ http://www.springframework.org/schema/util/spring-util.xsd
+ http://servicemix.apache.org/schema/servicemix-gshell
+ http://servicemix.apache.org/schema/servicemix-gshell/servicemix-gshell.xsd
+ http://www.springframework.org/schema/osgi
+ http://www.springframework.org/schema/osgi/spring-osgi-1.0.xsd"
+ default-autowire="no"
+ default-dependency-check="none"
+ default-init-method="init"
+ default-destroy-method="destroy">
+
+ <bean id="io" class="org.apache.geronimo.gshell.io.IO">
+ <property name="verbosity" value="DEBUG"/>
+ </bean>
+
+ <bean id="branding" class="org.apache.servicemix.kernel.gshell.core.ServiceMixBranding">
+ <property name="prompt" value="@|bold %{gshell.username}|@%{application.id}:@|bold %{gshell.group}|> " />
+ </bean>
+
+ <bean id="application" class="org.apache.servicemix.kernel.gshell.core.ApplicationImpl">
+ <property name="id" value="${servicemix.name}"/>
+ <property name="io" ref="io"/>
+ <property name="model">
+ <bean class="org.apache.geronimo.gshell.application.model.ApplicationModel">
+ <property name="branding" ref="branding"/>
+ </bean>
+ </property>
+ <property name="variables">
+ <bean class="org.apache.geronimo.gshell.command.Variables"/>
+ </property>
+ </bean>
+
+ <bean id="eventManager" class="org.apache.geronimo.gshell.event.EventManagerImpl"/>
+
+ <bean id="applicationManager" class="org.apache.servicemix.kernel.gshell.core.ApplicationManagerImpl">
+ <constructor-arg ref="eventManager" />
+ <constructor-arg ref="application" />
+ </bean>
+
+ <bean id="commandLineParser" class="org.apache.geronimo.gshell.parser.CommandLineParser"/>
+
+ <bean id="aliasRegistry" class="org.apache.geronimo.gshell.wisdom.registry.AliasRegistryImpl">
+ <constructor-arg ref="eventManager"/>
+ </bean>
+
+ <bean id="aliasMetaMapper" class="org.apache.geronimo.gshell.wisdom.registry.AliasMetaMapper">
+ <constructor-arg ref="eventManager"/>
+ <constructor-arg ref="metaDataRegistry"/>
+ <constructor-arg ref="aliasRegistry"/>
+ </bean>
+
+ <bean id="commandRegistry" class="org.apache.geronimo.gshell.wisdom.registry.CommandRegistryImpl">
+ <constructor-arg ref="eventManager"/>
+ </bean>
+
+ <bean id="commandMetaMapper" class="org.apache.geronimo.gshell.wisdom.registry.CommandMetaMapper">
+ <constructor-arg ref="eventManager"/>
+ <constructor-arg ref="metaDataRegistry"/>
+ <constructor-arg ref="commandRegistry"/>
+ </bean>
+
+ <bean id="groupDirResolver" class="org.apache.geronimo.gshell.wisdom.registry.GroupDirectoryResolver">
+ <constructor-arg ref="fileSystemAccess"/>
+ </bean>
+
+ <bean id="commandResolver" class="org.apache.geronimo.gshell.wisdom.registry.CommandResolverImpl">
+ <constructor-arg ref="fileSystemAccess"/>
+ <constructor-arg ref="groupDirResolver"/>
+ </bean>
+
+ <bean class="org.apache.servicemix.kernel.gshell.core.WorkAroundAliasCommand" scope="prototype">
+ <constructor-arg ref="commandLineExecutor"/>
+ </bean>
+
+ <bean class="org.apache.geronimo.gshell.wisdom.command.GroupCommand" scope="prototype"/>
+
+ <bean id="commandLineBuilder" class="org.apache.geronimo.gshell.wisdom.shell.CommandLineBuilderImpl">
+ <constructor-arg ref="commandLineParser"/>
+ </bean>
+
+ <bean id="commandLineExecutor" class="org.apache.geronimo.gshell.wisdom.shell.CommandLineExecutorImpl">
+ <constructor-arg ref="commandResolver"/>
+ <constructor-arg ref="commandLineBuilder"/>
+ </bean>
+
+ <bean id="shell" class="org.apache.geronimo.gshell.wisdom.shell.ShellImpl" scope="prototype" init-method="init" destroy-method="close">
+ <constructor-arg ref="application"/>
+ <constructor-arg ref="commandLineExecutor"/>
+
+ <property name="completers">
+ <list>
+ <ref bean="commandsCompleter"/>
+ <ref bean="aliasNameCompleter"/>
+ </list>
+ </property>
+ <property name="prompter">
+ <bean class="org.apache.geronimo.gshell.wisdom.shell.ConsolePrompterImpl">
+ <constructor-arg ref="application"/>
+ </bean>
+ </property>
+ <property name="errorHandler">
+ <bean class="org.apache.geronimo.gshell.wisdom.shell.ConsoleErrorHandlerImpl" />
+ </property>
+ <property name="history">
+ <bean class="org.apache.geronimo.gshell.wisdom.shell.HistoryImpl">
+ <constructor-arg ref="application"/>
+ </bean>
+ </property>
+ </bean>
+
+ <bean id="commandNameCompleter" class="org.apache.geronimo.gshell.wisdom.completer.CommandNameCompleter"
+ lazy-init="true">
+ <constructor-arg ref="eventManager"/>
+ <constructor-arg ref="commandRegistry"/>
+ </bean>
+
+ <bean id="aliasNameCompleter" class="org.apache.geronimo.gshell.wisdom.completer.AliasNameCompleter"
+ lazy-init="true">
+ <constructor-arg ref="eventManager"/>
+ <constructor-arg ref="aliasRegistry"/>
+ </bean>
+
+ <bean id="commandsCompleter" class="org.apache.geronimo.gshell.wisdom.completer.CommandsCompleter" lazy-init="true">
+ <constructor-arg ref="eventManager"/>
+ <constructor-arg ref="commandRegistry"/>
+ </bean>
+
+ <bean id="variableNameCompleter" class="org.apache.geronimo.gshell.wisdom.completer.VariableNameCompleter" lazy-init="true">
+ </bean>
+
+</beans>
\ No newline at end of file
diff --git a/karaf/gshell/gshell-core/src/main/resources/org/apache/geronimo/gshell/commands/text/SortAction.properties b/karaf/gshell/gshell-core/src/main/resources/org/apache/geronimo/gshell/commands/text/SortAction.properties
new file mode 100644
index 0000000..e4e787d
--- /dev/null
+++ b/karaf/gshell/gshell-core/src/main/resources/org/apache/geronimo/gshell/commands/text/SortAction.properties
@@ -0,0 +1,27 @@
+##
+## 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.
+##
+
+##
+## $Rev: 703511 $ $Date: 2008-10-10 18:07:36 +0200 (Fri, 10 Oct 2008) $
+##
+
+command.description=Sort lines of text.
+
+command.manual=\
+ TODO: about manual
\ No newline at end of file
diff --git a/karaf/gshell/gshell-core/src/main/resources/org/apache/servicemix/kernel/gshell/core/commands.xml b/karaf/gshell/gshell-core/src/main/resources/org/apache/servicemix/kernel/gshell/core/commands.xml
new file mode 100644
index 0000000..8b91ee1
--- /dev/null
+++ b/karaf/gshell/gshell-core/src/main/resources/org/apache/servicemix/kernel/gshell/core/commands.xml
@@ -0,0 +1,51 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ 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.
+
+-->
+<beans xmlns="http://www.springframework.org/schema/beans"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:util="http://www.springframework.org/schema/util"
+ xsi:schemaLocation="
+ http://www.springframework.org/schema/beans
+ http://www.springframework.org/schema/beans/spring-beans.xsd
+ http://www.springframework.org/schema/util
+ http://www.springframework.org/schema/util/spring-util.xsd">
+
+ <bean class="org.apache.servicemix.kernel.gshell.core.BeanContainerAwareProcessor" />
+
+ <bean id="statelessCommandTemplate" class="org.apache.geronimo.gshell.wisdom.command.StatelessCommand" abstract="true">
+ <property name="documenter">
+ <bean class="org.apache.geronimo.gshell.wisdom.command.MessageSourceCommandDocumenter"/>
+ </property>
+
+ <property name="messages">
+ <bean class="org.apache.geronimo.gshell.wisdom.command.CommandMessageSource"/>
+ </property>
+ </bean>
+
+ <bean id="statefulCommandTemplate" class="org.apache.geronimo.gshell.wisdom.command.StatefulCommand" abstract="true">
+ <property name="documenter">
+ <bean class="org.apache.geronimo.gshell.wisdom.command.MessageSourceCommandDocumenter"/>
+ </property>
+
+ <property name="messages">
+ <bean class="org.apache.geronimo.gshell.wisdom.command.CommandMessageSource"/>
+ </property>
+ </bean>
+
+</beans>
\ No newline at end of file
diff --git a/karaf/gshell/gshell-core/src/main/resources/org/apache/servicemix/kernel/gshell/core/commands/InfoAction.properties b/karaf/gshell/gshell-core/src/main/resources/org/apache/servicemix/kernel/gshell/core/commands/InfoAction.properties
new file mode 100644
index 0000000..755f0c8
--- /dev/null
+++ b/karaf/gshell/gshell-core/src/main/resources/org/apache/servicemix/kernel/gshell/core/commands/InfoAction.properties
@@ -0,0 +1,27 @@
+##
+## 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.
+##
+
+##
+## $Rev: 703511 $ $Date: 2008-10-10 18:07:36 +0200 (Fri, 10 Oct 2008) $
+##
+
+command.description=Display JVM informations about the current application.
+
+command.manual=\
+ TODO: about manual
\ No newline at end of file
diff --git a/karaf/gshell/gshell-core/src/main/resources/org/apache/servicemix/kernel/gshell/core/servicemix-gshell.xsd b/karaf/gshell/gshell-core/src/main/resources/org/apache/servicemix/kernel/gshell/core/servicemix-gshell.xsd
new file mode 100644
index 0000000..36a1e1d
--- /dev/null
+++ b/karaf/gshell/gshell-core/src/main/resources/org/apache/servicemix/kernel/gshell/core/servicemix-gshell.xsd
@@ -0,0 +1,270 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+-->
+
+<!-- $Rev: 699828 $ $Date: 2008-09-28 16:35:27 +0200 (Sun, 28 Sep 2008) $ -->
+
+<xsd:schema xmlns="http://servicemix.apache.org/schema/servicemix-gshell"
+ xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+ xmlns:beans="http://www.springframework.org/schema/beans"
+ targetNamespace="http://servicemix.apache.org/schema/servicemix-gshell"
+ elementFormDefault="qualified"
+ attributeFormDefault="unqualified">
+
+ <xsd:import namespace="http://www.springframework.org/schema/beans"/>
+
+ <xsd:annotation>
+ <xsd:documentation>
+ Defines the configuration elements for Apache ServiceMix Kernel commands support.
+ </xsd:documentation>
+ </xsd:annotation>
+
+ <xsd:element name="command-bundle">
+ <xsd:complexType>
+ <xsd:annotation>
+ <xsd:documentation>
+ Defines a command bundle.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:sequence>
+ <xsd:element ref="beans:description" minOccurs="0" maxOccurs="1"/>
+ <xsd:choice minOccurs="0" maxOccurs="unbounded">
+ <xsd:element ref="command"/>
+ <xsd:element ref="alias"/>
+ <xsd:element ref="link"/>
+ </xsd:choice>
+ </xsd:sequence>
+ </xsd:complexType>
+ </xsd:element>
+
+ <xsd:element name="command">
+ <xsd:complexType>
+ <xsd:annotation>
+ <xsd:documentation>
+ Defines a command.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:sequence>
+ <xsd:element ref="beans:description" minOccurs="0" maxOccurs="1"/>
+ <!--
+ NOTE: Not using an xsd:choice here, as I can't seem to figure out how to get it to properly
+ validate the min/max of the containted elements. W/o the xsd:choice the validation
+ works, though have to define elements in order :-(
+ -->
+ <xsd:element ref="action" minOccurs="1" maxOccurs="1"/>
+ <xsd:element ref="documenter" minOccurs="0" maxOccurs="1"/>
+ <xsd:choice minOccurs="0" maxOccurs="1">
+ <xsd:element ref="completer"/>
+ <xsd:element ref="completers"/>
+ </xsd:choice>
+ <xsd:element ref="message-source" minOccurs="0" maxOccurs="1"/>
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required"/>
+ <xsd:attribute name="type" use="optional" default="stateful">
+ <xsd:annotation>
+ <xsd:documentation>
+ The command type.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:simpleType>
+ <xsd:restriction base="xsd:string">
+ <xsd:enumeration value="stateless"/>
+ <xsd:enumeration value="stateful"/>
+ </xsd:restriction>
+ </xsd:simpleType>
+ </xsd:attribute>
+ </xsd:complexType>
+ </xsd:element>
+
+ <xsd:element name="link">
+ <xsd:complexType>
+ <xsd:annotation>
+ <xsd:documentation>
+ Defines a link command.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:sequence>
+ <xsd:element ref="beans:description" minOccurs="0" maxOccurs="1"/>
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required"/>
+ <xsd:attribute name="target" type="xsd:string" use="required"/>
+ </xsd:complexType>
+ </xsd:element>
+
+ <xsd:group name="commandComponentElements">
+ <xsd:annotation>
+ <xsd:documentation>
+ Defines the valid elements for command components. This is based on beans:beanElements,
+ stripping off the bits which are not valid in the command component context.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:sequence>
+ <xsd:element ref="beans:description" minOccurs="0"/>
+ <xsd:choice minOccurs="0" maxOccurs="unbounded">
+ <xsd:element ref="beans:meta"/>
+ <xsd:element ref="beans:constructor-arg"/>
+ <xsd:element ref="beans:property"/>
+ <xsd:element ref="beans:qualifier"/>
+ <xsd:element ref="beans:lookup-method"/>
+ <xsd:element ref="beans:replaced-method"/>
+ <!--
+ NOTE: This seems to cause schema validation problems... not really sure why
+ <xsd:any namespace="##other" processContents="strict" minOccurs="0" maxOccurs="unbounded"/>
+ -->
+ </xsd:choice>
+ </xsd:sequence>
+ </xsd:group>
+
+ <xsd:attributeGroup name="commandComponentAttributes">
+ <xsd:annotation>
+ <xsd:documentation>
+ Defines the valid attributes for command components. This is based on beans:beanAttributes,
+ stripping off the bits which are not valid in the command component context.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:attribute name="class" type="xsd:string"/>
+ <xsd:attribute name="parent" type="xsd:string"/>
+ <xsd:attribute name="autowire" default="default">
+ <xsd:simpleType>
+ <xsd:restriction base="xsd:NMTOKEN">
+ <xsd:enumeration value="default"/>
+ <xsd:enumeration value="no"/>
+ <xsd:enumeration value="byName"/>
+ <xsd:enumeration value="byType"/>
+ <xsd:enumeration value="constructor"/>
+ <xsd:enumeration value="autodetect"/>
+ </xsd:restriction>
+ </xsd:simpleType>
+ </xsd:attribute>
+ <xsd:attribute name="dependency-check" default="default">
+ <xsd:simpleType>
+ <xsd:restriction base="xsd:NMTOKEN">
+ <xsd:enumeration value="default"/>
+ <xsd:enumeration value="none"/>
+ <xsd:enumeration value="simple"/>
+ <xsd:enumeration value="objects"/>
+ <xsd:enumeration value="all"/>
+ </xsd:restriction>
+ </xsd:simpleType>
+ </xsd:attribute>
+ <xsd:attribute name="depends-on" type="xsd:string"/>
+ <xsd:attribute name="autowire-candidate" default="default" type="beans:defaultable-boolean"/>
+ <xsd:attribute name="primary" type="xsd:boolean"/>
+ <xsd:attribute name="init-method" type="xsd:string"/>
+ <xsd:attribute name="destroy-method" type="xsd:string"/>
+ <xsd:attribute name="factory-method" type="xsd:string"/>
+ <xsd:attribute name="factory-bean" type="xsd:string"/>
+ <xsd:anyAttribute namespace="##other" processContents="lax"/>
+ </xsd:attributeGroup>
+
+ <xsd:complexType name="commandComponent" abstract="true">
+ <xsd:annotation>
+ <xsd:documentation>
+ Support for command component elements, which are all basically just beans.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:group ref="commandComponentElements"/>
+ <xsd:attributeGroup ref="commandComponentAttributes"/>
+ </xsd:complexType>
+
+ <xsd:element name="action">
+ <xsd:complexType>
+ <xsd:annotation>
+ <xsd:documentation>
+ Defines a command action.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexContent>
+ <xsd:extension base="commandComponent"/>
+ </xsd:complexContent>
+ </xsd:complexType>
+ </xsd:element>
+
+ <xsd:element name="documenter">
+ <xsd:complexType>
+ <xsd:annotation>
+ <xsd:documentation>
+ Defines a command documenter.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexContent>
+ <xsd:extension base="commandComponent"/>
+ </xsd:complexContent>
+ </xsd:complexType>
+ </xsd:element>
+
+ <xsd:element name="completer">
+ <xsd:complexType>
+ <xsd:annotation>
+ <xsd:documentation>
+ Defines a command completer.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexContent>
+ <xsd:extension base="commandComponent"/>
+ </xsd:complexContent>
+ </xsd:complexType>
+ </xsd:element>
+
+ <xsd:element name="completers">
+ <xsd:complexType>
+ <xsd:annotation>
+ <xsd:documentation>
+ Defines a configurable command completer with a set of completers.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:sequence>
+ <xsd:choice minOccurs="1" maxOccurs="unbounded">
+ <xsd:element ref="beans:bean"/>
+ <xsd:element ref="beans:ref"/>
+ <xsd:element ref="beans:null"/>
+ </xsd:choice>
+ </xsd:sequence>
+ </xsd:complexType>
+ </xsd:element>
+
+ <xsd:element name="message-source">
+ <xsd:complexType>
+ <xsd:annotation>
+ <xsd:documentation>
+ Defines a command message source.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexContent>
+ <xsd:extension base="commandComponent"/>
+ </xsd:complexContent>
+ </xsd:complexType>
+ </xsd:element>
+
+ <xsd:element name="alias">
+ <xsd:complexType>
+ <xsd:annotation>
+ <xsd:documentation>
+ Defines a command alias.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:sequence>
+ <xsd:element ref="beans:description" minOccurs="0" maxOccurs="1"/>
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required"/>
+ <xsd:attribute name="alias" type="xsd:string" use="required"/>
+ </xsd:complexType>
+ </xsd:element>
+
+</xsd:schema>
\ No newline at end of file
diff --git a/karaf/gshell/gshell-core/src/test/java/org/apache/geronimo/gshell/commands/text/SortTest.java b/karaf/gshell/gshell-core/src/test/java/org/apache/geronimo/gshell/commands/text/SortTest.java
new file mode 100644
index 0000000..90e405e
--- /dev/null
+++ b/karaf/gshell/gshell-core/src/test/java/org/apache/geronimo/gshell/commands/text/SortTest.java
@@ -0,0 +1,63 @@
+/*
+ * 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.geronimo.gshell.commands.text;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.Collections;
+
+import junit.framework.TestCase;
+
+/**
+ * TODO: remove this file when gshell is upgraded
+ */
+public class SortTest extends TestCase {
+
+ public void testFieldIndexesDefaultSep() {
+ SortAction.SortComparator comparator = new SortAction.SortComparator(false, false, false, false, '\0', null);
+ List<Integer> indexes = comparator.getFieldIndexes(" ad re t ");
+ assertTrue(Arrays.asList(0, 2, 3, 6, 7, 9, 10, 10).equals(indexes));
+ }
+
+ public void testFieldIndexesWithSep() {
+ SortAction.SortComparator comparator = new SortAction.SortComparator(false, false, false, false, '[', null);
+ List<Integer> indexes = comparator.getFieldIndexes("[ 10] [Active ] [ ] [ 8] OPS4J Pax Logging - Service (1.3.0)");
+ assertTrue(Arrays.asList(1, 6, 8, 20, 22, 30, 32, 73 ).equals(indexes));
+
+ indexes = comparator.getFieldIndexes(" ad re t ");
+ assertTrue(Arrays.asList(0, 10).equals(indexes));
+ }
+
+ public void testSort() {
+ String s0 = "0321 abcd ddcba a";
+ String s1 = " 57t bcad ddacb b";
+ String s2 = " 128 cab ddbac c";
+ List<String> strings = Arrays.asList(s0, s1, s2);
+
+ Collections.sort(strings, new SortAction.SortComparator(false, false, false, false, '\0', Arrays.asList("2")));
+ assertTrue(Arrays.asList(s0, s1, s2).equals(strings));
+
+ Collections.sort(strings, new SortAction.SortComparator(false, false, false, false, '\0', Arrays.asList("2.2b")));
+ assertTrue(Arrays.asList(s2, s0, s1).equals(strings));
+
+ Collections.sort(strings, new SortAction.SortComparator(false, false, false, true, '\0', null));
+ assertTrue(Arrays.asList(s1, s2, s0).equals(strings));
+ }
+
+}
diff --git a/karaf/gshell/gshell-core/src/test/java/org/apache/servicemix/kernel/gshell/core/Test.java b/karaf/gshell/gshell-core/src/test/java/org/apache/servicemix/kernel/gshell/core/Test.java
new file mode 100644
index 0000000..0983b12
--- /dev/null
+++ b/karaf/gshell/gshell-core/src/test/java/org/apache/servicemix/kernel/gshell/core/Test.java
@@ -0,0 +1,154 @@
+/*
+ * 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.servicemix.kernel.gshell.core;
+
+import junit.framework.TestCase;
+import org.apache.geronimo.gshell.application.ApplicationManager;
+import org.apache.geronimo.gshell.shell.Shell;
+import org.springframework.context.support.ClassPathXmlApplicationContext;
+
+public class Test extends TestCase {
+
+ public void test() throws Exception {
+ System.setProperty("startLocalConsole", "true");
+ System.setProperty("servicemix.name", "root");
+
+ ClassPathXmlApplicationContext context = null;
+ try {
+ context = new ClassPathXmlApplicationContext(
+ new String[] { "META-INF/spring/gshell.xml",
+ "META-INF/spring/gshell-vfs.xml",
+ "META-INF/spring/gshell-commands.xml",
+ "org/apache/servicemix/kernel/gshell/core/gshell-test.xml" });
+ ApplicationManager appMgr = (ApplicationManager) context.getBean("applicationManager");
+ assertNotNull(appMgr);
+ Shell shell = appMgr.create();
+ assertNotNull(shell);
+ shell.execute("help");
+ } finally {
+ if (context != null) {
+ context.destroy();
+ }
+ }
+ }
+
+ public void testBanner() throws Exception {
+ System.setProperty("startLocalConsole", "true");
+ System.setProperty("servicemix.name", "root");
+
+ ClassPathXmlApplicationContext context = null;
+ try {
+ context = new ClassPathXmlApplicationContext(
+ new String[] { "META-INF/spring/gshell.xml",
+ "META-INF/spring/gshell-vfs.xml",
+ "META-INF/spring/gshell-commands.xml",
+ "org/apache/servicemix/kernel/gshell/core/gshell-test.xml"});
+ ApplicationManager appMgr = (ApplicationManager) context.getBean("applicationManager");
+ assertNotNull(appMgr);
+ Shell shell = appMgr.create();
+ ServiceMixBranding smxBrandng = (ServiceMixBranding)appMgr.getApplication().getModel().getBranding();
+ assertNotNull(smxBrandng.getWelcomeMessage());
+ System.out.println(smxBrandng.getWelcomeMessage());
+ assertNotNull(shell);
+ shell.execute("about");
+ } finally {
+ if (context != null) {
+ context.destroy();
+ }
+ }
+ }
+
+ public void testLs() throws Exception {
+ System.setProperty("startLocalConsole", "true");
+ System.setProperty("servicemix.name", "root");
+
+ ClassPathXmlApplicationContext context = null;
+ try {
+ context = new ClassPathXmlApplicationContext(
+ new String[] { "META-INF/spring/gshell.xml",
+ "META-INF/spring/gshell-vfs.xml",
+ "org/apache/servicemix/kernel/gshell/core/gshell-test-commands.xml",
+ "org/apache/servicemix/kernel/gshell/core/gshell-test.xml"});
+ ApplicationManager appMgr = (ApplicationManager) context.getBean("applicationManager");
+ assertNotNull(appMgr);
+ Shell shell = appMgr.create();
+ ServiceMixBranding smxBrandng = (ServiceMixBranding)appMgr.getApplication().getModel().getBranding();
+ assertNotNull(smxBrandng.getWelcomeMessage());
+ System.out.println(smxBrandng.getWelcomeMessage());
+ assertNotNull(shell);
+ shell.execute("vfs/ls meta:/commands/");
+ } finally {
+ if (context != null) {
+ context.destroy();
+ }
+ }
+ }
+
+ public void testCommandGroups() throws Exception {
+ System.setProperty("startLocalConsole", "true");
+ System.setProperty("servicemix.name", "root");
+
+ ClassPathXmlApplicationContext context = null;
+ try {
+ context = new ClassPathXmlApplicationContext(
+ new String[] { "META-INF/spring/gshell.xml",
+ "META-INF/spring/gshell-vfs.xml",
+ "org/apache/servicemix/kernel/gshell/core/gshell-test-commands.xml",
+ "org/apache/servicemix/kernel/gshell/core/gshell-test.xml"});
+ ApplicationManager appMgr = (ApplicationManager) context.getBean("applicationManager");
+ assertNotNull(appMgr);
+ Shell shell = appMgr.create();
+ ServiceMixBranding smxBrandng = (ServiceMixBranding)appMgr.getApplication().getModel().getBranding();
+ assertNotNull(smxBrandng.getWelcomeMessage());
+ System.out.println(smxBrandng.getWelcomeMessage());
+ assertNotNull(shell);
+
+ shell.execute("vfs");
+ shell.execute("help");
+ shell.execute("..");
+ } finally {
+ if (context != null) {
+ context.destroy();
+ }
+ }
+ }
+
+ public void testFileAccessCommands() throws Exception {
+ System.setProperty("startLocalConsole", "true");
+ System.setProperty("servicemix.name", "root");
+
+ ClassPathXmlApplicationContext context = null;
+ try {
+ context = new ClassPathXmlApplicationContext(
+ new String[] { "META-INF/spring/gshell.xml",
+ "META-INF/spring/gshell-vfs.xml",
+ "org/apache/servicemix/kernel/gshell/core/gshell-test-commands.xml",
+ "org/apache/servicemix/kernel/gshell/core/gshell-test.xml"});
+ ApplicationManager appMgr = (ApplicationManager) context.getBean("applicationManager");
+ assertNotNull(appMgr);
+ Shell shell = appMgr.create();
+ assertNotNull(shell);
+ shell.execute("optional/cat src/test/resources/org/apache/servicemix/kernel/gshell/core/gshell-test.xml");
+ shell.execute("optional/find src/test/resources/org/apache/servicemix/kernel/gshell/core/gshell-test.xml");
+ } finally {
+ if (context != null) {
+ context.destroy();
+ }
+ }
+ }
+
+}
diff --git a/karaf/gshell/gshell-core/src/test/resources/log4j.properties b/karaf/gshell/gshell-core/src/test/resources/log4j.properties
new file mode 100644
index 0000000..8cc85f8
--- /dev/null
+++ b/karaf/gshell/gshell-core/src/test/resources/log4j.properties
@@ -0,0 +1,33 @@
+################################################################################
+#
+# 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.
+#
+################################################################################
+
+# Root logger
+log4j.rootLogger=INFO, stdout
+
+# CONSOLE appender not used by default
+log4j.appender.stdout=org.apache.log4j.ConsoleAppender
+log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
+log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} | %-5.5p | %-16.16t | %-32.32c{1} | %-32.32C %4L | %m%n
+
+# File appender
+log4j.appender.out=org.apache.log4j.FileAppender
+log4j.appender.out.layout=org.apache.log4j.PatternLayout
+log4j.appender.out.layout.ConversionPattern=%d{ABSOLUTE} | %-5.5p | %-16.16t | %-32.32c{1} | %-32.32C %4L | %m%n
+log4j.appender.out.file=${servicemix.base}/data/log/servicemix.log
+log4j.appender.out.append=true
diff --git a/karaf/gshell/gshell-core/src/test/resources/org/apache/servicemix/kernel/gshell/core/gshell-test-commands.xml b/karaf/gshell/gshell-core/src/test/resources/org/apache/servicemix/kernel/gshell/core/gshell-test-commands.xml
new file mode 100644
index 0000000..25e4de1
--- /dev/null
+++ b/karaf/gshell/gshell-core/src/test/resources/org/apache/servicemix/kernel/gshell/core/gshell-test-commands.xml
@@ -0,0 +1,162 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ 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.
+
+-->
+<beans xmlns="http://www.springframework.org/schema/beans"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:util="http://www.springframework.org/schema/util"
+ xmlns:gshell="http://servicemix.apache.org/schema/servicemix-gshell"
+ xsi:schemaLocation="
+ http://www.springframework.org/schema/beans
+ http://www.springframework.org/schema/beans/spring-beans.xsd
+ http://www.springframework.org/schema/util
+ http://www.springframework.org/schema/util/spring-util.xsd
+ http://servicemix.apache.org/schema/servicemix-gshell
+ http://servicemix.apache.org/schema/servicemix-gshell/servicemix-gshell.xsd"
+ default-autowire="no"
+ default-dependency-check="none"
+ default-init-method="init"
+ default-destroy-method="destroy">
+
+ <import resource="classpath:org/apache/servicemix/kernel/gshell/core/commands.xml" />
+
+ <bean id="vfsCommandActionTemplate" abstract="true">
+ <property name="fileSystemAccess" ref="fileSystemAccess"/>
+ </bean>
+
+ <gshell:command-bundle>
+ <gshell:command name="about">
+ <gshell:action class="org.apache.geronimo.gshell.commands.builtin.AboutAction">
+ <constructor-arg ref="application"/>
+ </gshell:action>
+ </gshell:command>
+
+ <gshell:command name="help">
+ <gshell:action class="org.apache.geronimo.gshell.commands.builtin.HelpAction">
+ <constructor-arg ref="commandResolver"/>
+ </gshell:action>
+ <gshell:completers>
+ <bean class="org.apache.geronimo.gshell.console.completer.AggregateCompleter">
+ <constructor-arg>
+ <list>
+ <ref bean="aliasNameCompleter"/>
+ <ref bean="commandNameCompleter"/>
+ </list>
+ </constructor-arg>
+ </bean>
+ <null/>
+ </gshell:completers>
+ </gshell:command>
+
+ <gshell:command name="exit">
+ <gshell:action class="org.apache.geronimo.gshell.commands.builtin.ExitAction"/>
+ </gshell:command>
+
+ <gshell:link name="quit" target="exit"/>
+
+ <gshell:command name="echo">
+ <gshell:action class="org.apache.geronimo.gshell.commands.builtin.EchoAction"/>
+ </gshell:command>
+
+ <gshell:command name="clear" type="stateless">
+ <gshell:action class="org.apache.geronimo.gshell.commands.builtin.ClearAction"/>
+ </gshell:command>
+
+ <gshell:command name="source">
+ <gshell:action class="org.apache.geronimo.gshell.commands.builtin.SourceAction">
+ <constructor-arg ref="commandLineExecutor"/>
+ <constructor-arg ref="fileSystemAccess"/>
+ </gshell:action>
+ <gshell:completers>
+ <ref bean="fileObjectNameCompleter"/>
+ <null/>
+ </gshell:completers>
+ </gshell:command>
+
+ <gshell:command name="set">
+ <gshell:action class="org.apache.geronimo.gshell.commands.builtin.SetAction"/>
+ </gshell:command>
+
+ <gshell:command name="unset">
+ <gshell:action class="org.apache.geronimo.gshell.commands.builtin.UnsetAction"/>
+ <gshell:completers>
+ <ref bean="variableNameCompleter"/>
+ <null/>
+ </gshell:completers>
+ </gshell:command>
+
+ <gshell:command name="alias">
+ <gshell:action class="org.apache.geronimo.gshell.commands.builtin.AliasAction">
+ <constructor-arg ref="aliasRegistry"/>
+ </gshell:action>
+ </gshell:command>
+
+ <gshell:command name="unalias">
+ <gshell:action class="org.apache.geronimo.gshell.commands.builtin.UnaliasAction">
+ <constructor-arg ref="aliasRegistry"/>
+ </gshell:action>
+ <gshell:completers>
+ <ref bean="aliasNameCompleter"/>
+ <null/>
+ </gshell:completers>
+ </gshell:command>
+
+ <gshell:command name="history">
+ <gshell:action class="org.apache.geronimo.gshell.commands.builtin.HistoryAction"/>
+ </gshell:command>
+
+ <gshell:command name="info">
+ <gshell:action class="org.apache.servicemix.kernel.gshell.core.commands.InfoAction">
+ <constructor-arg ref="branding" />
+ </gshell:action>
+ </gshell:command>
+ </gshell:command-bundle>
+
+ <gshell:command-bundle>
+ <gshell:command name="vfs/ls">
+ <gshell:action class="org.apache.geronimo.gshell.commands.file.ListDirectoryAction" parent="vfsCommandActionTemplate"/>
+ <gshell:completers>
+ <ref bean="fileObjectNameCompleter"/>
+ <null/>
+ </gshell:completers>
+ </gshell:command>
+ </gshell:command-bundle>
+
+ <gshell:command-bundle>
+ <gshell:command name="optional/cat">
+ <gshell:action class="org.apache.geronimo.gshell.commands.text.CatAction">
+ <property name="fileSystemAccess" ref="fileSystemAccess"/>
+ </gshell:action>
+ <gshell:completers>
+ <ref bean="fileObjectNameCompleter"/>
+ <null/>
+ </gshell:completers>
+ </gshell:command>
+
+ <gshell:command name="optional/find">
+ <gshell:action class="org.apache.geronimo.gshell.commands.shell.FindAction">
+ <property name="fileSystemAccess" ref="fileSystemAccess"/>
+ </gshell:action>
+ <gshell:completers>
+ <ref bean="fileObjectNameCompleter"/>
+ <null/>
+ </gshell:completers>
+ </gshell:command>
+ </gshell:command-bundle>
+
+</beans>
diff --git a/karaf/gshell/gshell-core/src/test/resources/org/apache/servicemix/kernel/gshell/core/gshell-test.xml b/karaf/gshell/gshell-core/src/test/resources/org/apache/servicemix/kernel/gshell/core/gshell-test.xml
new file mode 100644
index 0000000..127543f
--- /dev/null
+++ b/karaf/gshell/gshell-core/src/test/resources/org/apache/servicemix/kernel/gshell/core/gshell-test.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ 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.
+
+-->
+<beans xmlns="http://www.springframework.org/schema/beans"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:util="http://www.springframework.org/schema/util"
+ xmlns:gshell="http://servicemix.apache.org/schema/servicemix-gshell"
+ xsi:schemaLocation="
+ http://www.springframework.org/schema/beans
+ http://www.springframework.org/schema/beans/spring-beans.xsd
+ http://www.springframework.org/schema/util
+ http://www.springframework.org/schema/util/spring-util.xsd
+ http://servicemix.apache.org/schema/servicemix-gshell
+ http://servicemix.apache.org/schema/servicemix-gshell/servicemix-gshell.xsd">
+
+ <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer" />
+
+</beans>
\ No newline at end of file