You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@felix.apache.org by gn...@apache.org on 2009/07/09 10:29:22 UTC
svn commit: r792445 [3/6] - in /felix/trunk/karaf: ./ assembly/
assembly/src/main/descriptors/ assembly/src/main/filtered-resources/
assembly/src/main/filtered-resources/etc/ client/
deployer/features/src/main/resources/OSGI-INF/blueprint/ deployer/fil...
Copied: felix/trunk/karaf/gshell/gshell-console/pom.xml (from r792359, felix/trunk/karaf/gshell/gshell-wrapper/pom.xml)
URL: http://svn.apache.org/viewvc/felix/trunk/karaf/gshell/gshell-console/pom.xml?p2=felix/trunk/karaf/gshell/gshell-console/pom.xml&p1=felix/trunk/karaf/gshell/gshell-wrapper/pom.xml&r1=792359&r2=792445&rev=792445&view=diff
==============================================================================
--- felix/trunk/karaf/gshell/gshell-wrapper/pom.xml (original)
+++ felix/trunk/karaf/gshell/gshell-console/pom.xml Thu Jul 9 08:29:14 2009
@@ -28,42 +28,41 @@
</parent>
<groupId>org.apache.felix.karaf.gshell</groupId>
- <artifactId>org.apache.felix.karaf.gshell.wrapper</artifactId>
+ <artifactId>org.apache.felix.karaf.gshell.console</artifactId>
<packaging>bundle</packaging>
<version>1.2.0-SNAPSHOT</version>
- <name>Apache Felix Karaf :: GShell Service Wrapper</name>
+ <name>Apache Felix Karaf :: GShell Console</name>
<description>
- Provides the Service Wrapper GShell integration
+ Provides the OSGi GShell integration
</description>
- <properties>
- <gshell.osgi.import>
- org.apache.felix.karaf.main.spi.*;resolution:=optional,
- org.apache.geronimo.gshell*,
- </gshell.osgi.import>
- <gshell.osgi.export>
- </gshell.osgi.export>
- <gshell.osgi.private>
- org.apache.felix.karaf.gshell.wrapper.*,
- </gshell.osgi.private>
- </properties>
-
<dependencies>
<dependency>
- <groupId>org.apache.felix.karaf.gshell</groupId>
- <artifactId>org.apache.felix.karaf.gshell.core</artifactId>
+ <groupId>org.apache.servicemix.bundles</groupId>
+ <artifactId>org.apache.servicemix.bundles.jline</artifactId>
</dependency>
-
<dependency>
<groupId>org.apache.felix</groupId>
<artifactId>org.osgi.core</artifactId>
<scope>provided</scope>
</dependency>
-
<dependency>
- <groupId>org.springframework.osgi</groupId>
- <artifactId>spring-osgi-core</artifactId>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>org.osgi.compendium</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.geronimo</groupId>
+ <artifactId>blueprint-bundle</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.felix.gogo</groupId>
+ <artifactId>org.apache.felix.gogo.runtime</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.felix.gogo</groupId>
+ <artifactId>org.apache.felix.gogo.commands</artifactId>
</dependency>
</dependencies>
@@ -97,17 +96,16 @@
<configuration>
<instructions>
<Bundle-SymbolicName>${artifactId}</Bundle-SymbolicName>
- <Export-Package>${pom.artifactId}*;version=${project.version}</Export-Package>
<Import-Package>
- org.apache.geronimo.gshell.command,
- org.apache.geronimo.gshell.wisdom.command,
- org.apache.geronimo.gshell.wisdom.registry,
- org.apache.felix.karaf.gshell.core,
+ !javax.swing,
*
</Import-Package>
- <Private-Package>!*</Private-Package>
+ <Export-Package>
+ org.apache.felix.karaf.gshell.console*;version=${pom.version}
+ </Export-Package>
<_versionpolicy>${bnd.version.policy}</_versionpolicy>
</instructions>
+ <unpackBundle>true</unpackBundle>
</configuration>
</plugin>
</plugins>
Copied: felix/trunk/karaf/gshell/gshell-console/src/main/filtered-resources/org/apache/felix/karaf/gshell/console/branding.properties (from r792359, felix/trunk/karaf/gshell/gshell-core/src/main/resources/org/apache/geronimo/gshell/commands/ssh/SshAction.properties)
URL: http://svn.apache.org/viewvc/felix/trunk/karaf/gshell/gshell-console/src/main/filtered-resources/org/apache/felix/karaf/gshell/console/branding.properties?p2=felix/trunk/karaf/gshell/gshell-console/src/main/filtered-resources/org/apache/felix/karaf/gshell/console/branding.properties&p1=felix/trunk/karaf/gshell/gshell-core/src/main/resources/org/apache/geronimo/gshell/commands/ssh/SshAction.properties&r1=792359&r2=792445&rev=792445&view=diff
==============================================================================
--- felix/trunk/karaf/gshell/gshell-core/src/main/resources/org/apache/geronimo/gshell/commands/ssh/SshAction.properties (original)
+++ felix/trunk/karaf/gshell/gshell-console/src/main/filtered-resources/org/apache/felix/karaf/gshell/console/branding.properties Thu Jul 9 08:29:14 2009
@@ -17,11 +17,16 @@
## under the License.
##
-##
-## $Rev: 703511 $ $Date: 2008-10-10 18:07:36 +0200 (Fri, 10 Oct 2008) $
-##
+welcome = \
+@|cyan __ __ ____ |\n\
+@|cyan / //_/____ __________ _/ __/ |\n\
+@|cyan / ,< / __ `/ ___/ __ `/ /_ |\n\
+@|cyan / /\\| \\|/ /_/ / / / /_/ / __/ |\n\
+@|cyan /_/ \\|_\\|\\__,_/_/ \\__,_/_/ |\n\
+\n\
+ @|bold Apache Felix Karaf| (${pom.version})\n\
+\n\
+Type '@|bold help|' for more information.\n
+
-command.description=SSH client.
-command.manual=\
- TODO: about manual
Copied: felix/trunk/karaf/gshell/gshell-console/src/main/java/org/apache/felix/karaf/gshell/console/BlueprintContainerAware.java (from r792359, felix/trunk/karaf/gshell/gshell-core/src/main/java/org/apache/felix/karaf/gshell/core/sshd/BogusPasswordAuthenticator.java)
URL: http://svn.apache.org/viewvc/felix/trunk/karaf/gshell/gshell-console/src/main/java/org/apache/felix/karaf/gshell/console/BlueprintContainerAware.java?p2=felix/trunk/karaf/gshell/gshell-console/src/main/java/org/apache/felix/karaf/gshell/console/BlueprintContainerAware.java&p1=felix/trunk/karaf/gshell/gshell-core/src/main/java/org/apache/felix/karaf/gshell/core/sshd/BogusPasswordAuthenticator.java&r1=792359&r2=792445&rev=792445&view=diff
==============================================================================
--- felix/trunk/karaf/gshell/gshell-core/src/main/java/org/apache/felix/karaf/gshell/core/sshd/BogusPasswordAuthenticator.java (original)
+++ felix/trunk/karaf/gshell/gshell-console/src/main/java/org/apache/felix/karaf/gshell/console/BlueprintContainerAware.java Thu Jul 9 08:29:14 2009
@@ -16,14 +16,12 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.apache.felix.karaf.gshell.core.sshd;
+package org.apache.felix.karaf.gshell.console;
-import org.apache.sshd.server.PasswordAuthenticator;
+import org.osgi.service.blueprint.container.BlueprintContainer;
-public class BogusPasswordAuthenticator implements PasswordAuthenticator {
+public interface BlueprintContainerAware {
- public Object authenticate(String username, String password) {
- return (username != null && username.equals(password)) ? username : null;
- }
+ void setBlueprintContainer(BlueprintContainer blueprintContainer);
}
Copied: felix/trunk/karaf/gshell/gshell-console/src/main/java/org/apache/felix/karaf/gshell/console/BundleContextAware.java (from r792359, felix/trunk/karaf/gshell/gshell-core/src/main/java/org/apache/felix/karaf/gshell/core/vfs/mvn/MvnFileSystem.java)
URL: http://svn.apache.org/viewvc/felix/trunk/karaf/gshell/gshell-console/src/main/java/org/apache/felix/karaf/gshell/console/BundleContextAware.java?p2=felix/trunk/karaf/gshell/gshell-console/src/main/java/org/apache/felix/karaf/gshell/console/BundleContextAware.java&p1=felix/trunk/karaf/gshell/gshell-core/src/main/java/org/apache/felix/karaf/gshell/core/vfs/mvn/MvnFileSystem.java&r1=792359&r2=792445&rev=792445&view=diff
==============================================================================
--- felix/trunk/karaf/gshell/gshell-core/src/main/java/org/apache/felix/karaf/gshell/core/vfs/mvn/MvnFileSystem.java (original)
+++ felix/trunk/karaf/gshell/gshell-console/src/main/java/org/apache/felix/karaf/gshell/console/BundleContextAware.java Thu Jul 9 08:29:14 2009
@@ -16,20 +16,12 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.apache.felix.karaf.gshell.core.vfs.mvn;
+package org.apache.felix.karaf.gshell.console;
-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;
+import org.osgi.framework.BundleContext;
-public class MvnFileSystem extends UrlFileSystem {
+public interface BundleContextAware {
- protected MvnFileSystem(FileName fileName, FileSystemOptions fileSystemOptions) {
- super(fileName, fileSystemOptions);
- }
+ void setBundleContext(BundleContext bundleContext);
- protected FileObject createFile(FileName fileName) {
- return new MvnFileObject(this, fileName);
- }
}
Added: felix/trunk/karaf/gshell/gshell-console/src/main/java/org/apache/felix/karaf/gshell/console/CompletableFunction.java
URL: http://svn.apache.org/viewvc/felix/trunk/karaf/gshell/gshell-console/src/main/java/org/apache/felix/karaf/gshell/console/CompletableFunction.java?rev=792445&view=auto
==============================================================================
--- felix/trunk/karaf/gshell/gshell-console/src/main/java/org/apache/felix/karaf/gshell/console/CompletableFunction.java (added)
+++ felix/trunk/karaf/gshell/gshell-console/src/main/java/org/apache/felix/karaf/gshell/console/CompletableFunction.java Thu Jul 9 08:29:14 2009
@@ -0,0 +1,11 @@
+package org.apache.felix.karaf.gshell.console;
+
+import java.util.List;
+
+import org.osgi.service.command.Function;
+
+public interface CompletableFunction extends Function {
+
+ List<Completer> getCompleters();
+
+}
Copied: felix/trunk/karaf/gshell/gshell-console/src/main/java/org/apache/felix/karaf/gshell/console/Completer.java (from r792359, felix/trunk/karaf/gshell/gshell-core/src/main/java/org/apache/felix/karaf/gshell/core/sshd/BogusPasswordAuthenticator.java)
URL: http://svn.apache.org/viewvc/felix/trunk/karaf/gshell/gshell-console/src/main/java/org/apache/felix/karaf/gshell/console/Completer.java?p2=felix/trunk/karaf/gshell/gshell-console/src/main/java/org/apache/felix/karaf/gshell/console/Completer.java&p1=felix/trunk/karaf/gshell/gshell-core/src/main/java/org/apache/felix/karaf/gshell/core/sshd/BogusPasswordAuthenticator.java&r1=792359&r2=792445&rev=792445&view=diff
==============================================================================
--- felix/trunk/karaf/gshell/gshell-core/src/main/java/org/apache/felix/karaf/gshell/core/sshd/BogusPasswordAuthenticator.java (original)
+++ felix/trunk/karaf/gshell/gshell-console/src/main/java/org/apache/felix/karaf/gshell/console/Completer.java Thu Jul 9 08:29:14 2009
@@ -7,7 +7,7 @@
* "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
+ * 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
@@ -16,14 +16,12 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.apache.felix.karaf.gshell.core.sshd;
+package org.apache.felix.karaf.gshell.console;
-import org.apache.sshd.server.PasswordAuthenticator;
+import java.util.List;
-public class BogusPasswordAuthenticator implements PasswordAuthenticator {
+public interface Completer {
- public Object authenticate(String username, String password) {
- return (username != null && username.equals(password)) ? username : null;
- }
+ int complete(String buffer, int cursor, List<String> candidates);
}
Copied: felix/trunk/karaf/gshell/gshell-console/src/main/java/org/apache/felix/karaf/gshell/console/OsgiCommandSupport.java (from r792359, felix/trunk/karaf/gshell/gshell-core/src/main/java/org/apache/felix/karaf/gshell/core/OsgiCommandSupport.java)
URL: http://svn.apache.org/viewvc/felix/trunk/karaf/gshell/gshell-console/src/main/java/org/apache/felix/karaf/gshell/console/OsgiCommandSupport.java?p2=felix/trunk/karaf/gshell/gshell-console/src/main/java/org/apache/felix/karaf/gshell/console/OsgiCommandSupport.java&p1=felix/trunk/karaf/gshell/gshell-core/src/main/java/org/apache/felix/karaf/gshell/core/OsgiCommandSupport.java&r1=792359&r2=792445&rev=792445&view=diff
==============================================================================
--- felix/trunk/karaf/gshell/gshell-core/src/main/java/org/apache/felix/karaf/gshell/core/OsgiCommandSupport.java (original)
+++ felix/trunk/karaf/gshell/gshell-console/src/main/java/org/apache/felix/karaf/gshell/console/OsgiCommandSupport.java Thu Jul 9 08:29:14 2009
@@ -16,33 +16,27 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.apache.felix.karaf.gshell.core;
+package org.apache.felix.karaf.gshell.console;
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.apache.felix.gogo.commands.Action;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceReference;
+import org.osgi.service.command.CommandSession;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
-public abstract class OsgiCommandSupport implements CommandAction {
+public abstract class OsgiCommandSupport implements Action, BundleContextAware {
- protected Log log = LogFactory.getLog(getClass());
+ protected final Logger log = LoggerFactory.getLogger(getClass());
protected BundleContext bundleContext;
- protected CommandContext commandContext;
- protected IO io;
- protected Variables variables;
+ protected CommandSession session;
protected List<ServiceReference> usedReferences;
-
- public Object execute(CommandContext commandContext) throws Exception {
- this.commandContext = commandContext;
- this.io = commandContext.getIo();
- this.variables = commandContext.getVariables();
+
+ public Object execute(CommandSession session) throws Exception {
+ this.session = session;
try {
return doExecute();
} finally {
Added: felix/trunk/karaf/gshell/gshell-console/src/main/java/org/apache/felix/karaf/gshell/console/ansi/AnsiCode.java
URL: http://svn.apache.org/viewvc/felix/trunk/karaf/gshell/gshell-console/src/main/java/org/apache/felix/karaf/gshell/console/ansi/AnsiCode.java?rev=792445&view=auto
==============================================================================
--- felix/trunk/karaf/gshell/gshell-console/src/main/java/org/apache/felix/karaf/gshell/console/ansi/AnsiCode.java (added)
+++ felix/trunk/karaf/gshell/gshell-console/src/main/java/org/apache/felix/karaf/gshell/console/ansi/AnsiCode.java Thu Jul 9 08:29:14 2009
@@ -0,0 +1,49 @@
+package org.apache.felix.karaf.gshell.console.ansi;
+
+public enum AnsiCode
+{
+ OFF(0),
+ BOLD(1),
+ UNDERSCORE(4),
+ BLINK(5),
+ REVERSE(7),
+ CONCEALED(8),
+
+ FG_BLACK(30),
+ FG_RED(31),
+ FG_GREEN(32),
+ FG_YELLOW(33),
+ FG_BLUE(34),
+ FG_MAGENTA(35),
+ FG_CYAN(36),
+ FG_WHITE(37),
+
+ BLACK(FG_BLACK),
+ RED(FG_RED),
+ GREEN(FG_GREEN),
+ YELLOW(FG_YELLOW),
+ BLUE(FG_BLUE),
+ MAGENTA(FG_MAGENTA),
+ CYAN(FG_CYAN),
+ WHITE(FG_WHITE),
+
+ BG_BLACK(40),
+ BG_RED(41),
+ BG_GREEN(42),
+ BG_YELLOW(43),
+ BG_BLUE(44),
+ BG_MAGENTA(45),
+ BG_CYAN(46),
+ BG_WHITE(47);
+
+ final int code;
+
+ private AnsiCode(final int code) {
+ this.code = code;
+ }
+
+ private AnsiCode(final AnsiCode code) {
+ this(code.code);
+ }
+
+}
Added: felix/trunk/karaf/gshell/gshell-console/src/main/java/org/apache/felix/karaf/gshell/console/ansi/AnsiOutputStream.java
URL: http://svn.apache.org/viewvc/felix/trunk/karaf/gshell/gshell-console/src/main/java/org/apache/felix/karaf/gshell/console/ansi/AnsiOutputStream.java?rev=792445&view=auto
==============================================================================
--- felix/trunk/karaf/gshell/gshell-console/src/main/java/org/apache/felix/karaf/gshell/console/ansi/AnsiOutputStream.java (added)
+++ felix/trunk/karaf/gshell/gshell-console/src/main/java/org/apache/felix/karaf/gshell/console/ansi/AnsiOutputStream.java Thu Jul 9 08:29:14 2009
@@ -0,0 +1,87 @@
+package org.apache.felix.karaf.gshell.console.ansi;
+
+import java.io.FilterOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.ByteArrayOutputStream;
+
+public class AnsiOutputStream extends FilterOutputStream
+{
+ char[] buf = new char[16];
+ int count = 0;
+ int ansiCodeState;
+
+ public AnsiOutputStream(OutputStream out)
+ {
+ super(out);
+ }
+
+ @Override
+ public void write(int b) throws IOException
+ {
+ if (ansiCodeState == 0) {
+ if (b == '@') {
+ ansiCodeState = 1;
+ } else {
+ super.write(b);
+ }
+ } else if (ansiCodeState == 1) {
+ if (b == '|') {
+ ansiCodeState = 2;
+ count = 0;
+ } else {
+ super.write('@');
+ super.write(b);
+ ansiCodeState = 0;
+ }
+ } else if (ansiCodeState == 2) {
+ if (b == ',') {
+ write(AnsiCode.valueOf(new String(buf, 0, count).toUpperCase()));
+ count = 0;
+ } else if (b == ' ') {
+ write(AnsiCode.valueOf(new String(buf, 0, count).toUpperCase()));
+ ansiCodeState = 3;
+ } else if (count < buf.length) {
+ buf[count++] = (char) b;
+ } else {
+ throw new IOException("Unknown ANSI code (too long): " + new String(buf, 0, count));
+ }
+ } else if (ansiCodeState == 3) {
+ if (b == '|') {
+ write(AnsiCode.OFF);
+ ansiCodeState = 0;
+ } else if (b == '\\') {
+ ansiCodeState = 4;
+ } else {
+ super.write(b);
+ }
+ } else if (ansiCodeState == 4) {
+ if (b != '|') {
+ super.write('\\');
+ }
+ super.write(b);
+ ansiCodeState = 3;
+ } else {
+ throw new IllegalStateException();
+ }
+ }
+
+ protected void write(AnsiCode code) throws IOException {
+ super.write(27); // ESC
+ super.write('[');
+ if (code.code >= 10) {
+ super.write((code.code / 10) + '0');
+ }
+ super.write((code.code % 10) + '0');
+ super.write('m');
+ }
+
+ public static String decode(String str) throws IOException {
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ AnsiOutputStream aos = new AnsiOutputStream(baos);
+ aos.write(str.getBytes());
+ aos.close();
+ return baos.toString();
+ }
+
+}
Added: felix/trunk/karaf/gshell/gshell-console/src/main/java/org/apache/felix/karaf/gshell/console/commands/BlueprintCommand.java
URL: http://svn.apache.org/viewvc/felix/trunk/karaf/gshell/gshell-console/src/main/java/org/apache/felix/karaf/gshell/console/commands/BlueprintCommand.java?rev=792445&view=auto
==============================================================================
--- felix/trunk/karaf/gshell/gshell-console/src/main/java/org/apache/felix/karaf/gshell/console/commands/BlueprintCommand.java (added)
+++ felix/trunk/karaf/gshell/gshell-console/src/main/java/org/apache/felix/karaf/gshell/console/commands/BlueprintCommand.java Thu Jul 9 08:29:14 2009
@@ -0,0 +1,90 @@
+/**
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.felix.karaf.gshell.console.commands;
+
+import java.lang.reflect.Type;
+import java.util.List;
+
+import org.apache.felix.gogo.commands.Action;
+import org.apache.felix.gogo.commands.basic.AbstractCommand;
+import org.apache.felix.gogo.commands.basic.ActionPreparator;
+import org.apache.felix.gogo.commands.basic.DefaultActionPreparator;
+import org.apache.felix.karaf.gshell.console.BlueprintContainerAware;
+import org.apache.felix.karaf.gshell.console.BundleContextAware;
+import org.apache.felix.karaf.gshell.console.CompletableFunction;
+import org.apache.felix.karaf.gshell.console.Completer;
+import org.osgi.framework.BundleContext;
+import org.osgi.service.blueprint.container.BlueprintContainer;
+import org.osgi.service.blueprint.container.Converter;
+import org.osgi.service.command.CommandSession;
+
+public class BlueprintCommand extends AbstractCommand implements CompletableFunction
+{
+
+ protected BlueprintContainer blueprintContainer;
+ protected Converter blueprintConverter;
+ protected String actionId;
+ protected List<Completer> completers;
+
+ public void setBlueprintContainer(BlueprintContainer blueprintContainer) {
+ this.blueprintContainer = blueprintContainer;
+ }
+
+ public void setBlueprintConverter(Converter blueprintConverter) {
+ this.blueprintConverter = blueprintConverter;
+ }
+
+ public void setActionId(String actionId) {
+ this.actionId = actionId;
+ }
+
+ public List<Completer> getCompleters() {
+ return completers;
+ }
+
+ public void setCompleters(List<Completer> completers) {
+ this.completers = completers;
+ }
+
+ @Override
+ protected ActionPreparator getPreparator() throws Exception {
+ return new BlueprintActionPreparator();
+ }
+
+ class BlueprintActionPreparator extends DefaultActionPreparator {
+
+ @Override
+ protected Object convert(Action action, CommandSession commandSession, Object o, Type type) throws Exception {
+ return blueprintConverter.convert(o, new GenericType(type));
+ }
+
+ }
+
+ protected Action createNewAction() throws Exception {
+ Action action = (Action) blueprintContainer.getComponentInstance(actionId);
+ if (action instanceof BlueprintContainerAware) {
+ ((BlueprintContainerAware) action).setBlueprintContainer(blueprintContainer);
+ }
+ if (action instanceof BundleContextAware) {
+ BundleContext context = (BundleContext) blueprintContainer.getComponentInstance("blueprintBundleContext");
+ ((BundleContextAware) action).setBundleContext(context);
+ }
+ return action;
+ }
+
+}
Added: felix/trunk/karaf/gshell/gshell-console/src/main/java/org/apache/felix/karaf/gshell/console/commands/GenericType.java
URL: http://svn.apache.org/viewvc/felix/trunk/karaf/gshell/gshell-console/src/main/java/org/apache/felix/karaf/gshell/console/commands/GenericType.java?rev=792445&view=auto
==============================================================================
--- felix/trunk/karaf/gshell/gshell-console/src/main/java/org/apache/felix/karaf/gshell/console/commands/GenericType.java (added)
+++ felix/trunk/karaf/gshell/gshell-console/src/main/java/org/apache/felix/karaf/gshell/console/commands/GenericType.java Thu Jul 9 08:29:14 2009
@@ -0,0 +1,195 @@
+/**
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.felix.karaf.gshell.console.commands;
+
+import java.lang.reflect.Array;
+import java.lang.reflect.GenericArrayType;
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+import java.lang.reflect.TypeVariable;
+import java.lang.reflect.WildcardType;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.osgi.framework.Bundle;
+import org.osgi.service.blueprint.container.ReifiedType;
+
+public class GenericType extends ReifiedType {
+
+ private static final GenericType[] EMPTY = new GenericType[0];
+
+ private static final Map<String, Class> primitiveClasses = new HashMap<String, Class>();
+
+ static {
+ primitiveClasses.put("int", int.class);
+ primitiveClasses.put("short", short.class);
+ primitiveClasses.put("long", long.class);
+ primitiveClasses.put("byte", byte.class);
+ primitiveClasses.put("char", char.class);
+ primitiveClasses.put("float", float.class);
+ primitiveClasses.put("double", double.class);
+ primitiveClasses.put("boolean", boolean.class);
+ }
+
+ private GenericType[] parameters;
+
+ public GenericType(Type type) {
+ this(getConcreteClass(type), parametersOf(type));
+ }
+
+ public GenericType(Class clazz, GenericType... parameters) {
+ super(clazz);
+ this.parameters = parameters;
+ }
+
+ public static GenericType parse(String type, Object loader) throws ClassNotFoundException, IllegalArgumentException {
+ type = type.trim();
+ // Check if this is an array
+ if (type.endsWith("[]")) {
+ GenericType t = parse(type.substring(0, type.length() - 2), loader);
+ return new GenericType(Array.newInstance(t.getRawClass(), 0).getClass(), t);
+ }
+ // Check if this is a generic
+ int genericIndex = type.indexOf('<');
+ if (genericIndex > 0) {
+ if (!type.endsWith(">")) {
+ throw new IllegalArgumentException("Can not load type: " + type);
+ }
+ GenericType base = parse(type.substring(0, genericIndex), loader);
+ String[] params = type.substring(genericIndex + 1, type.length() - 1).split(",");
+ GenericType[] types = new GenericType[params.length];
+ for (int i = 0; i < params.length; i++) {
+ types[i] = parse(params[i], loader);
+ }
+ return new GenericType(base.getRawClass(), types);
+ }
+ // Primitive
+ if (primitiveClasses.containsKey(type)) {
+ return new GenericType(primitiveClasses.get(type));
+ }
+ // Class
+ if (loader instanceof ClassLoader) {
+ return new GenericType(((ClassLoader) loader).loadClass(type));
+ } else if (loader instanceof Bundle) {
+ return new GenericType(((Bundle) loader).loadClass(type));
+ } else {
+ throw new IllegalArgumentException("Unsupported loader: " + loader);
+ }
+ }
+
+ @Override
+ public ReifiedType getActualTypeArgument(int i) {
+ if (parameters.length == 0) {
+ return super.getActualTypeArgument(i);
+ }
+ return parameters[i];
+ }
+
+ @Override
+ public int size() {
+ return parameters.length;
+ }
+
+ @Override
+ public String toString() {
+ Class cl = getRawClass();
+ if (cl.isArray()) {
+ if (parameters.length > 0) {
+ return parameters[0].toString() + "[]";
+ } else {
+ return cl.getComponentType().getName() + "[]";
+ }
+ }
+ if (parameters.length > 0) {
+ StringBuilder sb = new StringBuilder();
+ sb.append(cl.getName());
+ sb.append("<");
+ for (int i = 0; i < parameters.length; i++) {
+ if (i > 0) {
+ sb.append(",");
+ }
+ sb.append(parameters[i].toString());
+ }
+ sb.append(">");
+ return sb.toString();
+ }
+ return cl.getName();
+ }
+
+ static GenericType[] parametersOf(Type type ) {
+ if ( type instanceof Class ) {
+ Class clazz = (Class) type;
+ if (clazz.isArray()) {
+ GenericType t = new GenericType(clazz.getComponentType());
+ if (t.size() > 0) {
+ return new GenericType[] { t };
+ } else {
+ return EMPTY;
+ }
+ } else {
+ return EMPTY;
+ }
+ }
+ if ( type instanceof ParameterizedType ) {
+ ParameterizedType pt = (ParameterizedType) type;
+ Type [] parameters = pt.getActualTypeArguments();
+ GenericType[] gts = new GenericType[parameters.length];
+ for ( int i =0; i<gts.length; i++) {
+ gts[i] = new GenericType(parameters[i]);
+ }
+ return gts;
+ }
+ if ( type instanceof GenericArrayType ) {
+ return new GenericType[] { new GenericType(((GenericArrayType) type).getGenericComponentType()) };
+ }
+ throw new IllegalStateException();
+ }
+
+ static Class<?> getConcreteClass(Type type) {
+ Type ntype = collapse(type);
+ if ( ntype instanceof Class )
+ return (Class<?>) ntype;
+
+ if ( ntype instanceof ParameterizedType )
+ return getConcreteClass(collapse(((ParameterizedType)ntype).getRawType()));
+
+ throw new RuntimeException("Unknown type " + type );
+ }
+
+ static Type collapse(Type target) {
+ if (target instanceof Class || target instanceof ParameterizedType ) {
+ return target;
+ } else if (target instanceof TypeVariable) {
+ return collapse(((TypeVariable<?>) target).getBounds()[0]);
+ } else if (target instanceof GenericArrayType) {
+ Type t = collapse(((GenericArrayType) target)
+ .getGenericComponentType());
+ while ( t instanceof ParameterizedType )
+ t = collapse(((ParameterizedType)t).getRawType());
+ return Array.newInstance((Class<?>)t, 0).getClass();
+ } else if (target instanceof WildcardType) {
+ WildcardType wct = (WildcardType) target;
+ if (wct.getLowerBounds().length == 0)
+ return collapse(wct.getUpperBounds()[0]);
+ else
+ return collapse(wct.getLowerBounds()[0]);
+ }
+ throw new RuntimeException("Huh? " + target);
+ }
+
+}
Copied: felix/trunk/karaf/gshell/gshell-console/src/main/java/org/apache/felix/karaf/gshell/console/commands/NamespaceHandler.java (from r792359, felix/trunk/karaf/gshell/gshell-core/src/main/java/org/apache/felix/karaf/gshell/core/config/NamespaceHandler.java)
URL: http://svn.apache.org/viewvc/felix/trunk/karaf/gshell/gshell-console/src/main/java/org/apache/felix/karaf/gshell/console/commands/NamespaceHandler.java?p2=felix/trunk/karaf/gshell/gshell-console/src/main/java/org/apache/felix/karaf/gshell/console/commands/NamespaceHandler.java&p1=felix/trunk/karaf/gshell/gshell-core/src/main/java/org/apache/felix/karaf/gshell/core/config/NamespaceHandler.java&r1=792359&r2=792445&rev=792445&view=diff
==============================================================================
--- felix/trunk/karaf/gshell/gshell-core/src/main/java/org/apache/felix/karaf/gshell/core/config/NamespaceHandler.java (original)
+++ felix/trunk/karaf/gshell/gshell-console/src/main/java/org/apache/felix/karaf/gshell/console/commands/NamespaceHandler.java Thu Jul 9 08:29:14 2009
@@ -16,7 +16,8 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.apache.felix.karaf.gshell.core.config;
+package org.apache.felix.karaf.gshell.console.commands;
+
import java.net.URL;
import java.util.List;
@@ -26,23 +27,12 @@
import org.apache.geronimo.blueprint.ParserContext;
import org.apache.geronimo.blueprint.mutable.MutableBeanMetadata;
-import org.apache.geronimo.blueprint.mutable.MutableCollectionMetadata;
import org.apache.geronimo.blueprint.mutable.MutableIdRefMetadata;
import org.apache.geronimo.blueprint.mutable.MutableServiceMetadata;
import org.apache.geronimo.blueprint.mutable.MutableValueMetadata;
import org.apache.geronimo.blueprint.mutable.MutableRefMetadata;
-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.wisdom.command.AliasImpl;
-import org.apache.geronimo.gshell.wisdom.command.CommandMessageSource;
-import org.apache.geronimo.gshell.wisdom.command.LinkImpl;
-import org.apache.geronimo.gshell.wisdom.command.MessageSourceCommandDocumenter;
-import org.apache.geronimo.gshell.wisdom.command.StatefulCommand;
-import org.apache.geronimo.gshell.wisdom.command.StatelessCommand;
-import org.apache.geronimo.gshell.wisdom.command.ConfigurableCommandCompleter;
-import org.apache.geronimo.gshell.wisdom.registry.CommandLocationImpl;
-import org.apache.felix.karaf.gshell.core.BeanContainerWrapper;
+import org.apache.geronimo.blueprint.mutable.MutableCollectionMetadata;
+import org.apache.felix.karaf.gshell.console.CompletableFunction;
import org.osgi.service.blueprint.reflect.BeanArgument;
import org.osgi.service.blueprint.reflect.BeanProperty;
import org.osgi.service.blueprint.reflect.ComponentMetadata;
@@ -53,7 +43,7 @@
import org.osgi.service.blueprint.reflect.NullMetadata;
import org.osgi.service.blueprint.reflect.BeanMetadata;
import org.osgi.service.blueprint.container.ComponentDefinitionException;
-import org.osgi.service.blueprint.container.BlueprintContainer;
+import org.osgi.service.command.Function;
public class NamespaceHandler implements org.apache.geronimo.blueprint.NamespaceHandler {
@@ -69,7 +59,6 @@
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";
@@ -84,14 +73,13 @@
public static final String LINK = "link";
public static final String LINKS = "links";
public static final String TARGET = "target";
-
- public static final String TYPE_STATEFUL = "stateful";
- public static final String TYPE_STATELESS = "stateless";
+ public static final String BLUEPRINT_CONTAINER = "blueprintContainer";
+ public static final String BLUEPRINT_CONVERTER = "blueprintConverter";
private int nameCounter = 0;
public URL getSchemaLocation(String namespace) {
- return getClass().getResource("/org/apache/felix/karaf/gshell/core/karaf-gshell.xsd");
+ return getClass().getResource("karaf-gshell.xsd");
}
public ComponentMetadata decorate(Node node, ComponentMetadata component, ParserContext context) {
@@ -118,62 +106,52 @@
if (nodeNameEquals(element, COMMAND)) {
parseCommand(element, context);
} else if (nodeNameEquals(element, LINK)) {
- parseLink(element, context);
+// parseLink(element, context);
} else if (nodeNameEquals(element, ALIAS)) {
- parseAlias(element, context);
+// parseAlias(element, context);
}
}
private void parseCommand(Element element, ParserContext context) {
MutableBeanMetadata command = context.createMetadata(MutableBeanMetadata.class);
- String type = element.hasAttribute(TYPE) ? element.getAttribute(TYPE) : TYPE_STATEFUL;
- boolean stateful;
- if (TYPE_STATEFUL.equals(type)) {
- command.setRuntimeClass(StatefulCommand.class);
- stateful = true;
- } else if (TYPE_STATELESS.equals(type)) {
- command.setRuntimeClass(StatelessCommand.class);
- stateful = false;
+ command.setRuntimeClass(BlueprintCommand.class);
+ command.addProperty(BLUEPRINT_CONTAINER, createRef(context, BLUEPRINT_CONTAINER));
+ command.addProperty(BLUEPRINT_CONVERTER, createRef(context, BLUEPRINT_CONVERTER));
+// MutableBeanMetadata documenter = context.createMetadata(MutableBeanMetadata.class);
+// documenter.setRuntimeClass(MessageSourceCommandDocumenter.class);
+// command.addProperty(DOCUMENTER, documenter);
+// MutableBeanMetadata messages = context.createMetadata(MutableBeanMetadata.class);
+// messages.setRuntimeClass(CommandMessageSource.class);
+// command.addProperty(MESSAGES, messages);
+// MutableBeanMetadata location = context.createMetadata(MutableBeanMetadata.class);
+// location.setRuntimeClass(CommandLocationImpl.class);
+// location.addArgument(createStringValue(context, element.getAttribute(NAME)), String.class.getName(), 0);
+// command.addProperty(LOCATION, location);
+
+ String location = element.getAttribute(NAME);
+ location = location.replace('/', ':');
+ String scope;
+ String function;
+ if (location.lastIndexOf(':') >= 0) {
+ scope = location.substring(0, location.lastIndexOf(':'));
+ function = location.substring(location.lastIndexOf(':') + 1);
} else {
- throw new ComponentDefinitionException("Bad xml syntax: unknown value '" + type + "' for attribute " + TYPE);
+ scope = "";
+ function = location;
}
- MutableBeanMetadata beanContainer = context.createMetadata(MutableBeanMetadata.class);
- beanContainer.setRuntimeClass(BeanContainerWrapper.class);
- beanContainer.addArgument(createRef(context, "blueprintContainer"), BlueprintContainer.class.getName(), 0);
- command.addProperty("beanContainer", beanContainer);
- MutableBeanMetadata documenter = context.createMetadata(MutableBeanMetadata.class);
- documenter.setRuntimeClass(MessageSourceCommandDocumenter.class);
- command.addProperty(DOCUMENTER, documenter);
- MutableBeanMetadata messages = context.createMetadata(MutableBeanMetadata.class);
- messages.setRuntimeClass(CommandMessageSource.class);
- command.addProperty(MESSAGES, messages);
- MutableBeanMetadata location = context.createMetadata(MutableBeanMetadata.class);
- location.setRuntimeClass(CommandLocationImpl.class);
- location.addArgument(createStringValue(context, element.getAttribute(NAME)), String.class.getName(), 0);
- command.addProperty(LOCATION, location);
- boolean hasAction = false;
NodeList children = element.getChildNodes();
for (int i = 0; i < children.getLength(); i++) {
Node child = children.item(i);
if (child instanceof Element) {
Element childElement = (Element) child;
if (nodeNameEquals(childElement, ACTION)) {
- if (hasAction) {
- throw new ComponentDefinitionException("Only one " + ACTION + " element can be set for a given command");
- }
- hasAction = true;
MutableBeanMetadata action = parseAction(context, command, childElement);
- // TODO: parse other stuff or remove it from schema
- if (stateful) {
- action.setId(getName());
- context.getComponentDefinitionRegistry().registerComponentDefinition(action);
- command.addProperty(ACTION_ID, createIdRef(context, action.getId()));
- } else {
- command.addProperty(ACTION, action);
- }
+ action.setId(getName());
+ context.getComponentDefinitionRegistry().registerComponentDefinition(action);
+ command.addProperty(ACTION_ID, createIdRef(context, action.getId()));
} else if (nodeNameEquals(childElement, COMPLETERS)) {
- command.addProperty(COMPLETER, parseCompleters(context, command, childElement));
+ command.addProperty(COMPLETERS, parseCompleters(context, command, childElement));
} else {
throw new ComponentDefinitionException("Bad xml syntax: unknown element '" + childElement.getNodeName() + "'");
}
@@ -182,8 +160,13 @@
MutableServiceMetadata commandService = context.createMetadata(MutableServiceMetadata.class);
commandService.setId(getName());
- commandService.addInterface(Command.class.getName());
+ commandService.addInterface(Function.class.getName());
+ commandService.addInterface(CompletableFunction.class.getName());
commandService.setServiceComponent(command);
+ commandService.addServiceProperty(createStringValue(context, "osgi.command.scope"),
+ createStringValue(context, scope));
+ commandService.addServiceProperty(createStringValue(context, "osgi.command.function"),
+ createStringValue(context, function));
context.getComponentDefinitionRegistry().registerComponentDefinition(commandService);
}
@@ -208,8 +191,6 @@
}
private Metadata parseCompleters(ParserContext context, ComponentMetadata enclosingComponent, Element element) {
- MutableBeanMetadata completer = context.createMetadata(MutableBeanMetadata.class);
- completer.setRuntimeClass(ConfigurableCommandCompleter.class);
MutableCollectionMetadata collection = context.createMetadata(MutableCollectionMetadata.class);
collection.setCollectionClass(List.class);
NodeList children = element.getChildNodes();
@@ -229,36 +210,35 @@
collection.addValue(metadata);
}
}
- completer.addArgument(collection, List.class.getName(), 0);
- return completer;
- }
-
- private void parseLink(Element element, ParserContext context) {
- MutableBeanMetadata link = context.createMetadata(MutableBeanMetadata.class);
- link.setRuntimeClass(LinkImpl.class);
- link.addArgument(createStringValue(context, element.getAttribute(NAME)), String.class.getName(), 0);
- link.addArgument(createStringValue(context, element.getAttribute(TARGET)), String.class.getName(), 0);
-
- MutableServiceMetadata linkService = context.createMetadata(MutableServiceMetadata.class);
- linkService.setId(getName());
- linkService.addInterface(Link.class.getName());
- linkService.setServiceComponent(link);
- context.getComponentDefinitionRegistry().registerComponentDefinition(linkService);
- }
-
- private void parseAlias(Element element, ParserContext context) {
- MutableBeanMetadata alias = context.createMetadata(MutableBeanMetadata.class);
- alias.setRuntimeClass(AliasImpl.class);
- alias.addArgument(createStringValue(context, element.getAttribute(NAME)), String.class.getName(), 0);
- alias.addArgument(createStringValue(context, element.getAttribute(ALIAS)), String.class.getName(), 0);
-
- MutableServiceMetadata aliasService = context.createMetadata(MutableServiceMetadata.class);
- aliasService.setId(getName());
- aliasService.addInterface(Alias.class.getName());
- aliasService.setServiceComponent(alias);
- context.getComponentDefinitionRegistry().registerComponentDefinition(aliasService);
+ return collection;
}
+// private void parseLink(Element element, ParserContext context) {
+// MutableBeanMetadata link = context.createMetadata(MutableBeanMetadata.class);
+// link.setRuntimeClass(LinkImpl.class);
+// link.addArgument(createStringValue(context, element.getAttribute(NAME)), String.class.getName(), 0);
+// link.addArgument(createStringValue(context, element.getAttribute(TARGET)), String.class.getName(), 0);
+//
+// MutableServiceMetadata linkService = context.createMetadata(MutableServiceMetadata.class);
+// linkService.setId(getName());
+// linkService.addInterface(Link.class.getName());
+// linkService.setServiceComponent(link);
+// context.getComponentDefinitionRegistry().registerComponentDefinition(linkService);
+// }
+//
+// private void parseAlias(Element element, ParserContext context) {
+// MutableBeanMetadata alias = context.createMetadata(MutableBeanMetadata.class);
+// alias.setRuntimeClass(AliasImpl.class);
+// alias.addArgument(createStringValue(context, element.getAttribute(NAME)), String.class.getName(), 0);
+// alias.addArgument(createStringValue(context, element.getAttribute(ALIAS)), String.class.getName(), 0);
+//
+// MutableServiceMetadata aliasService = context.createMetadata(MutableServiceMetadata.class);
+// aliasService.setId(getName());
+// aliasService.addInterface(Alias.class.getName());
+// aliasService.setServiceComponent(alias);
+// context.getComponentDefinitionRegistry().registerComponentDefinition(aliasService);
+// }
+//
private ValueMetadata createStringValue(ParserContext context, String str) {
MutableValueMetadata value = context.createMetadata(MutableValueMetadata.class);
value.setStringValue(str);
Added: felix/trunk/karaf/gshell/gshell-console/src/main/java/org/apache/felix/karaf/gshell/console/completer/AggregateCompleter.java
URL: http://svn.apache.org/viewvc/felix/trunk/karaf/gshell/gshell-console/src/main/java/org/apache/felix/karaf/gshell/console/completer/AggregateCompleter.java?rev=792445&view=auto
==============================================================================
--- felix/trunk/karaf/gshell/gshell-console/src/main/java/org/apache/felix/karaf/gshell/console/completer/AggregateCompleter.java (added)
+++ felix/trunk/karaf/gshell/gshell-console/src/main/java/org/apache/felix/karaf/gshell/console/completer/AggregateCompleter.java Thu Jul 9 08:29:14 2009
@@ -0,0 +1,91 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.felix.karaf.gshell.console.completer;
+
+import java.util.ArrayList;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Collection;
+
+import org.apache.felix.karaf.gshell.console.Completer;
+
+/**
+ * Completer which contains multipule completers and aggregates them together.
+ *
+ * @version $Rev: 699733 $ $Date: 2008-09-27 22:55:23 +0200 (Sat, 27 Sep 2008) $
+ */
+public class AggregateCompleter implements Completer
+{
+ private final Collection<Completer> completers;
+
+ public AggregateCompleter(final Collection<Completer> completers) {
+ assert completers != null;
+ this.completers = completers;
+ }
+
+ public int complete(final String buffer, final int cursor, final List candidates) {
+ // buffer could be null
+ assert candidates != null;
+
+ List<Completion> completions = new ArrayList<Completion>(completers.size());
+
+ // Run each completer, saving its completion results
+ int max = -1;
+ for (Completer completer : completers) {
+ Completion completion = new Completion(candidates);
+ completion.complete(completer, buffer, cursor);
+
+ // Compute the max cursor position
+ max = Math.max(max, completion.cursor);
+
+ completions.add(completion);
+ }
+
+ // Append candiates from completions which have the same cursor position as max
+ for (Completion completion : completions) {
+ if (completion.cursor == max) {
+ // noinspection unchecked
+ candidates.addAll(completion.candidates);
+ }
+ }
+
+ return max;
+ }
+
+ private class Completion
+ {
+ public final List<String> candidates;
+
+ public int cursor;
+
+ public Completion(final List candidates) {
+ assert candidates != null;
+
+ // noinspection unchecked
+ this.candidates = new LinkedList<String>(candidates);
+ }
+
+ public void complete(final Completer completer, final String buffer, final int cursor) {
+ assert completer != null;
+
+ this.cursor = completer.complete(buffer, cursor, candidates);
+ }
+ }
+}
Added: felix/trunk/karaf/gshell/gshell-console/src/main/java/org/apache/felix/karaf/gshell/console/completer/ArgumentCompleter.java
URL: http://svn.apache.org/viewvc/felix/trunk/karaf/gshell/gshell-console/src/main/java/org/apache/felix/karaf/gshell/console/completer/ArgumentCompleter.java?rev=792445&view=auto
==============================================================================
--- felix/trunk/karaf/gshell/gshell-console/src/main/java/org/apache/felix/karaf/gshell/console/completer/ArgumentCompleter.java (added)
+++ felix/trunk/karaf/gshell/gshell-console/src/main/java/org/apache/felix/karaf/gshell/console/completer/ArgumentCompleter.java Thu Jul 9 08:29:14 2009
@@ -0,0 +1,393 @@
+/*
+ * Copyright (c) 2002-2007, Marc Prud'hommeaux. All rights reserved.
+ *
+ * This software is distributable under the BSD license. See the terms of the
+ * BSD license in the documentation provided with this software.
+ */
+package org.apache.felix.karaf.gshell.console.completer;
+
+import java.util.*;
+
+import org.apache.felix.karaf.gshell.console.Completer;
+
+public class ArgumentCompleter implements Completer {
+ final Completer[] completers;
+ final ArgumentDelimiter delim;
+ boolean strict = true;
+
+ /**
+ * Constuctor: create a new completor with the default
+ * argument separator of " ".
+ *
+ * @param completer the embedded completer
+ */
+ public ArgumentCompleter(final Completer completer) {
+ this(new Completer[] {
+ completer
+ });
+ }
+
+ /**
+ * Constuctor: create a new completor with the default
+ * argument separator of " ".
+ *
+ * @param completers the List of completors to use
+ */
+ public ArgumentCompleter(final List<Completer> completers) {
+ this(completers.toArray(new Completer[completers.size()]));
+ }
+
+ /**
+ * Constuctor: create a new completor with the default
+ * argument separator of " ".
+ *
+ * @param completers the embedded argument completers
+ */
+ public ArgumentCompleter(final Completer[] completers) {
+ this(completers, new WhitespaceArgumentDelimiter());
+ }
+
+ /**
+ * Constuctor: create a new completor with the specified
+ * argument delimiter.
+ *
+ * @param completer the embedded completer
+ * @param delim the delimiter for parsing arguments
+ */
+ public ArgumentCompleter(final Completer completer,
+ final ArgumentDelimiter delim) {
+ this(new Completer[] {
+ completer
+ }, delim);
+ }
+
+ /**
+ * Constuctor: create a new completor with the specified
+ * argument delimiter.
+ *
+ * @param completers the embedded completers
+ * @param delim the delimiter for parsing arguments
+ */
+ public ArgumentCompleter(final Completer[] completers,
+ final ArgumentDelimiter delim) {
+ this.completers = completers;
+ this.delim = delim;
+ }
+
+ /**
+ * If true, a completion at argument index N will only succeed
+ * if all the completions from 0-(N-1) also succeed.
+ */
+ public void setStrict(final boolean strict) {
+ this.strict = strict;
+ }
+
+ /**
+ * Returns whether a completion at argument index N will succees
+ * if all the completions from arguments 0-(N-1) also succeed.
+ */
+ public boolean getStrict() {
+ return this.strict;
+ }
+
+ public int complete(final String buffer, final int cursor,
+ final List<String> candidates) {
+ ArgumentList list = delim.delimit(buffer, cursor);
+ int argpos = list.getArgumentPosition();
+ int argIndex = list.getCursorArgumentIndex();
+
+ if (argIndex < 0) {
+ return -1;
+ }
+
+ final Completer comp;
+
+ // if we are beyond the end of the completors, just use the last one
+ if (argIndex >= completers.length) {
+ comp = completers[completers.length - 1];
+ } else {
+ comp = completers[argIndex];
+ }
+
+ // ensure that all the previous completors are successful before
+ // allowing this completor to pass (only if strict is true).
+ for (int i = 0; getStrict() && (i < argIndex); i++) {
+ Completer sub = completers[(i >= completers.length) ? (completers.length - 1) : i];
+ String[] args = list.getArguments();
+ String arg = ((args == null) || (i >= args.length)) ? "" : args[i];
+
+ List<String> subCandidates = new LinkedList<String>();
+
+ if (sub.complete(arg, arg.length(), subCandidates) == -1) {
+ return -1;
+ }
+
+ if (subCandidates.size() == 0) {
+ return -1;
+ }
+ }
+
+ int ret = comp.complete(list.getCursorArgument(), argpos, candidates);
+
+ if (ret == -1) {
+ return -1;
+ }
+
+ int pos = ret + (list.getBufferPosition() - argpos);
+
+ /**
+ * Special case: when completing in the middle of a line, and the
+ * area under the cursor is a delimiter, then trim any delimiters
+ * from the candidates, since we do not need to have an extra
+ * delimiter.
+ *
+ * E.g., if we have a completion for "foo", and we
+ * enter "f bar" into the buffer, and move to after the "f"
+ * and hit TAB, we want "foo bar" instead of "foo bar".
+ */
+ if ((cursor != buffer.length()) && delim.isDelimiter(buffer, cursor)) {
+ for (int i = 0; i < candidates.size(); i++) {
+ String val = candidates.get(i);
+
+ while ((val.length() > 0)
+ && delim.isDelimiter(val, val.length() - 1)) {
+ val = val.substring(0, val.length() - 1);
+ }
+
+ candidates.set(i, val);
+ }
+ }
+
+ return pos;
+ }
+
+ /**
+ * The {@link ArgumentCompleter.ArgumentDelimiter} allows custom
+ * breaking up of a {@link String} into individual arguments in
+ * order to dispatch the arguments to the nested {@link Completer}.
+ *
+ * @author <a href="mailto:mwp1@cornell.edu">Marc Prud'hommeaux</a>
+ */
+ public static interface ArgumentDelimiter {
+ /**
+ * Break the specified buffer into individual tokens
+ * that can be completed on their own.
+ *
+ * @param buffer the buffer to split
+ * @param argumentPosition the current position of the
+ * cursor in the buffer
+ * @return the tokens
+ */
+ ArgumentList delimit(String buffer, int argumentPosition);
+
+ /**
+ * Returns true if the specified character is a whitespace
+ * parameter.
+ *
+ * @param buffer the complete command buffer
+ * @param pos the index of the character in the buffer
+ * @return true if the character should be a delimiter
+ */
+ boolean isDelimiter(String buffer, int pos);
+ }
+
+ /**
+ * Abstract implementation of a delimiter that uses the
+ * {@link #isDelimiter} method to determine if a particular
+ * character should be used as a delimiter.
+ *
+ * @author <a href="mailto:mwp1@cornell.edu">Marc Prud'hommeaux</a>
+ */
+ public abstract static class AbstractArgumentDelimiter
+ implements ArgumentDelimiter {
+ private char[] quoteChars = new char[] { '\'', '"' };
+ private char[] escapeChars = new char[] { '\\' };
+
+ public void setQuoteChars(final char[] quoteChars) {
+ this.quoteChars = quoteChars;
+ }
+
+ public char[] getQuoteChars() {
+ return this.quoteChars;
+ }
+
+ public void setEscapeChars(final char[] escapeChars) {
+ this.escapeChars = escapeChars;
+ }
+
+ public char[] getEscapeChars() {
+ return this.escapeChars;
+ }
+
+ public ArgumentList delimit(final String buffer, final int cursor) {
+ List<String> args = new LinkedList<String>();
+ StringBuffer arg = new StringBuffer();
+ int argpos = -1;
+ int bindex = -1;
+
+ for (int i = 0; (buffer != null) && (i <= buffer.length()); i++) {
+ // once we reach the cursor, set the
+ // position of the selected index
+ if (i == cursor) {
+ bindex = args.size();
+ // the position in the current argument is just the
+ // length of the current argument
+ argpos = arg.length();
+ }
+
+ if ((i == buffer.length()) || isDelimiter(buffer, i)) {
+ if (arg.length() > 0) {
+ args.add(arg.toString());
+ arg.setLength(0); // reset the arg
+ }
+ } else {
+ arg.append(buffer.charAt(i));
+ }
+ }
+
+ return new ArgumentList(args.
+ toArray(new String[args.size()]), bindex, argpos, cursor);
+ }
+
+ /**
+ * Returns true if the specified character is a whitespace
+ * parameter. Check to ensure that the character is not
+ * escaped by any of
+ * {@link #getQuoteChars}, and is not escaped by ant of the
+ * {@link #getEscapeChars}, and returns true from
+ * {@link #isDelimiterChar}.
+ *
+ * @param buffer the complete command buffer
+ * @param pos the index of the character in the buffer
+ * @return true if the character should be a delimiter
+ */
+ public boolean isDelimiter(final String buffer, final int pos) {
+ if (isQuoted(buffer, pos)) {
+ return false;
+ }
+
+ if (isEscaped(buffer, pos)) {
+ return false;
+ }
+
+ return isDelimiterChar(buffer, pos);
+ }
+
+ public boolean isQuoted(final String buffer, final int pos) {
+ return false;
+ }
+
+ public boolean isEscaped(final String buffer, final int pos) {
+ if (pos <= 0) {
+ return false;
+ }
+
+ for (int i = 0; (escapeChars != null) && (i < escapeChars.length);
+ i++) {
+ if (buffer.charAt(pos) == escapeChars[i]) {
+ return !isEscaped(buffer, pos - 1); // escape escape
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Returns true if the character at the specified position
+ * if a delimiter. This method will only be called if the
+ * character is not enclosed in any of the
+ * {@link #getQuoteChars}, and is not escaped by ant of the
+ * {@link #getEscapeChars}. To perform escaping manually,
+ * override {@link #isDelimiter} instead.
+ */
+ public abstract boolean isDelimiterChar(String buffer, int pos);
+ }
+
+ /**
+ * {@link ArgumentCompleter.ArgumentDelimiter}
+ * implementation that counts all
+ * whitespace (as reported by {@link Character#isWhitespace})
+ * as being a delimiter.
+ *
+ * @author <a href="mailto:mwp1@cornell.edu">Marc Prud'hommeaux</a>
+ */
+ public static class WhitespaceArgumentDelimiter
+ extends AbstractArgumentDelimiter {
+ /**
+ * The character is a delimiter if it is whitespace, and the
+ * preceeding character is not an escape character.
+ */
+ public boolean isDelimiterChar(String buffer, int pos) {
+ return Character.isWhitespace(buffer.charAt(pos));
+ }
+ }
+
+ /**
+ * The result of a delimited buffer.
+ *
+ * @author <a href="mailto:mwp1@cornell.edu">Marc Prud'hommeaux</a>
+ */
+ public static class ArgumentList {
+ private String[] arguments;
+ private int cursorArgumentIndex;
+ private int argumentPosition;
+ private int bufferPosition;
+
+ /**
+ * @param arguments the array of tokens
+ * @param cursorArgumentIndex the token index of the cursor
+ * @param argumentPosition the position of the cursor in the
+ * current token
+ * @param bufferPosition the position of the cursor in
+ * the whole buffer
+ */
+ public ArgumentList(String[] arguments, int cursorArgumentIndex,
+ int argumentPosition, int bufferPosition) {
+ this.arguments = arguments;
+ this.cursorArgumentIndex = cursorArgumentIndex;
+ this.argumentPosition = argumentPosition;
+ this.bufferPosition = bufferPosition;
+ }
+
+ public void setCursorArgumentIndex(int cursorArgumentIndex) {
+ this.cursorArgumentIndex = cursorArgumentIndex;
+ }
+
+ public int getCursorArgumentIndex() {
+ return this.cursorArgumentIndex;
+ }
+
+ public String getCursorArgument() {
+ if ((cursorArgumentIndex < 0)
+ || (cursorArgumentIndex >= arguments.length)) {
+ return null;
+ }
+
+ return arguments[cursorArgumentIndex];
+ }
+
+ public void setArgumentPosition(int argumentPosition) {
+ this.argumentPosition = argumentPosition;
+ }
+
+ public int getArgumentPosition() {
+ return this.argumentPosition;
+ }
+
+ public void setArguments(String[] arguments) {
+ this.arguments = arguments;
+ }
+
+ public String[] getArguments() {
+ return this.arguments;
+ }
+
+ public void setBufferPosition(int bufferPosition) {
+ this.bufferPosition = bufferPosition;
+ }
+
+ public int getBufferPosition() {
+ return this.bufferPosition;
+ }
+ }
+}
Added: felix/trunk/karaf/gshell/gshell-console/src/main/java/org/apache/felix/karaf/gshell/console/completer/CommandsCompleter.java
URL: http://svn.apache.org/viewvc/felix/trunk/karaf/gshell/gshell-console/src/main/java/org/apache/felix/karaf/gshell/console/completer/CommandsCompleter.java?rev=792445&view=auto
==============================================================================
--- felix/trunk/karaf/gshell/gshell-console/src/main/java/org/apache/felix/karaf/gshell/console/completer/CommandsCompleter.java (added)
+++ felix/trunk/karaf/gshell/gshell-console/src/main/java/org/apache/felix/karaf/gshell/console/completer/CommandsCompleter.java Thu Jul 9 08:29:14 2009
@@ -0,0 +1,86 @@
+package org.apache.felix.karaf.gshell.console.completer;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.HashSet;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.concurrent.ConcurrentHashMap;
+
+import org.apache.felix.karaf.gshell.console.Completer;
+import org.apache.felix.karaf.gshell.console.CompletableFunction;
+import org.osgi.framework.ServiceReference;
+import org.osgi.framework.BundleContext;
+import org.osgi.service.command.CommandProcessor;
+
+public class CommandsCompleter implements Completer {
+
+ private final Map<ServiceReference, Completer> completers = new ConcurrentHashMap<ServiceReference, Completer>();
+
+ private BundleContext bundleContext;
+
+ public void setBundleContext(BundleContext bundleContext) {
+ this.bundleContext = bundleContext;
+ }
+
+ public void register(ServiceReference reference) {
+ Set<String> functions = getNames(reference);
+ if (functions != null) {
+ List<Completer> cl = new ArrayList<Completer>();
+ cl.add(new StringsCompleter(functions));
+ try {
+ Object function = bundleContext.getService(reference);
+ if (function instanceof CompletableFunction) {
+ List<Completer> fcl = ((CompletableFunction) function).getCompleters();
+ if (fcl != null) {
+ for (Completer c : fcl) {
+ cl.add(c == null ? NullCompleter.INSTANCE : c);
+ }
+ } else {
+ cl.add(NullCompleter.INSTANCE);
+ }
+ } else {
+ cl.add(NullCompleter.INSTANCE);
+ }
+ } finally {
+ bundleContext.ungetService(reference);
+ }
+ ArgumentCompleter c = new ArgumentCompleter(cl);
+ completers.put(reference, c);
+ }
+ }
+
+ public void unregister(ServiceReference reference) {
+ completers.remove(reference);
+ }
+
+ private Set<String> getNames(ServiceReference reference) {
+ Set<String> names = new HashSet<String>();
+ Object scope = reference.getProperty(CommandProcessor.COMMAND_SCOPE);
+ Object function = reference.getProperty(CommandProcessor.COMMAND_FUNCTION);
+ if(scope != null && function != null)
+ {
+ if (function.getClass().isArray())
+ {
+ for (Object f : ((Object[]) function))
+ {
+ names.add(scope + ":" + f.toString());
+ }
+ }
+ else
+ {
+ names.add(scope + ":" + function.toString());
+ }
+ return names;
+ }
+ return null;
+ }
+
+ public int complete(String buffer, int cursor, List<String> candidates) {
+ int res = new AggregateCompleter(completers.values()).complete(buffer, cursor, candidates);
+ Collections.sort(candidates);
+ return res;
+ }
+}
+
Added: felix/trunk/karaf/gshell/gshell-console/src/main/java/org/apache/felix/karaf/gshell/console/completer/NullCompleter.java
URL: http://svn.apache.org/viewvc/felix/trunk/karaf/gshell/gshell-console/src/main/java/org/apache/felix/karaf/gshell/console/completer/NullCompleter.java?rev=792445&view=auto
==============================================================================
--- felix/trunk/karaf/gshell/gshell-console/src/main/java/org/apache/felix/karaf/gshell/console/completer/NullCompleter.java (added)
+++ felix/trunk/karaf/gshell/gshell-console/src/main/java/org/apache/felix/karaf/gshell/console/completer/NullCompleter.java Thu Jul 9 08:29:14 2009
@@ -0,0 +1,14 @@
+package org.apache.felix.karaf.gshell.console.completer;
+
+import java.util.List;
+
+import org.apache.felix.karaf.gshell.console.Completer;
+
+public class NullCompleter implements Completer {
+
+ public static final NullCompleter INSTANCE = new NullCompleter();
+
+ public int complete(String buffer, int cursor, List<String> candidates) {
+ return -1;
+ }
+}
Added: felix/trunk/karaf/gshell/gshell-console/src/main/java/org/apache/felix/karaf/gshell/console/completer/StringsCompleter.java
URL: http://svn.apache.org/viewvc/felix/trunk/karaf/gshell/gshell-console/src/main/java/org/apache/felix/karaf/gshell/console/completer/StringsCompleter.java?rev=792445&view=auto
==============================================================================
--- felix/trunk/karaf/gshell/gshell-console/src/main/java/org/apache/felix/karaf/gshell/console/completer/StringsCompleter.java (added)
+++ felix/trunk/karaf/gshell/gshell-console/src/main/java/org/apache/felix/karaf/gshell/console/completer/StringsCompleter.java Thu Jul 9 08:29:14 2009
@@ -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.felix.karaf.gshell.console.completer;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
+import java.util.SortedSet;
+import java.util.TreeSet;
+
+import org.apache.felix.karaf.gshell.console.Completer;
+
+/**
+ * Completer for a set of strings.
+ *
+ * @version $Rev: 722797 $ $Date: 2008-12-03 08:18:16 +0100 (Wed, 03 Dec 2008) $
+ */
+public class StringsCompleter
+ implements Completer
+{
+ private final SortedSet<String> strings = new TreeSet<String>();
+
+ public StringsCompleter() {}
+
+ public StringsCompleter(final Collection<String> strings) {
+ assert strings != null;
+
+ getStrings().addAll(strings);
+ }
+
+ public StringsCompleter(final String[] strings) {
+ this(Arrays.asList(strings));
+ }
+
+ public Collection<String> getStrings() {
+ return strings;
+ }
+
+ public int complete(String buffer, final int cursor, final List candidates) {
+ // buffer could be null
+ assert candidates != null;
+
+ if (buffer == null) {
+ buffer = "";
+ }
+
+ SortedSet<String> matches = strings.tailSet(buffer);
+
+ for (String match : matches) {
+ if (!match.startsWith(buffer)) {
+ break;
+ }
+
+ // noinspection unchecked
+ candidates.add(match);
+ }
+
+ if (candidates.size() == 1) {
+ // noinspection unchecked
+ candidates.set(0, candidates.get(0) + " ");
+ }
+
+ return candidates.isEmpty() ? -1 : 0;
+ }
+}
\ No newline at end of file
Added: felix/trunk/karaf/gshell/gshell-console/src/main/java/org/apache/felix/karaf/gshell/console/jline/CompleterAsCompletor.java
URL: http://svn.apache.org/viewvc/felix/trunk/karaf/gshell/gshell-console/src/main/java/org/apache/felix/karaf/gshell/console/jline/CompleterAsCompletor.java?rev=792445&view=auto
==============================================================================
--- felix/trunk/karaf/gshell/gshell-console/src/main/java/org/apache/felix/karaf/gshell/console/jline/CompleterAsCompletor.java (added)
+++ felix/trunk/karaf/gshell/gshell-console/src/main/java/org/apache/felix/karaf/gshell/console/jline/CompleterAsCompletor.java Thu Jul 9 08:29:14 2009
@@ -0,0 +1,26 @@
+package org.apache.felix.karaf.gshell.console.jline;
+
+import java.util.List;
+
+import jline.Completor;
+import org.apache.felix.karaf.gshell.console.Completer;
+
+/**
+ * Created by IntelliJ IDEA.
+ * User: gnodet
+ * Date: Jul 6, 2009
+ * Time: 10:26:15 AM
+ * To change this template use File | Settings | File Templates.
+ */
+public class CompleterAsCompletor implements Completor {
+
+ private final Completer completer;
+
+ public CompleterAsCompletor(Completer completer) {
+ this.completer = completer;
+ }
+
+ public int complete(String buffer, int cursor, List candidates) {
+ return completer.complete(buffer, cursor, candidates);
+ }
+}
Added: felix/trunk/karaf/gshell/gshell-console/src/main/java/org/apache/felix/karaf/gshell/console/jline/Console.java
URL: http://svn.apache.org/viewvc/felix/trunk/karaf/gshell/gshell-console/src/main/java/org/apache/felix/karaf/gshell/console/jline/Console.java?rev=792445&view=auto
==============================================================================
--- felix/trunk/karaf/gshell/gshell-console/src/main/java/org/apache/felix/karaf/gshell/console/jline/Console.java (added)
+++ felix/trunk/karaf/gshell/gshell-console/src/main/java/org/apache/felix/karaf/gshell/console/jline/Console.java Thu Jul 9 08:29:14 2009
@@ -0,0 +1,259 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.karaf.gshell.console.jline;
+
+import jline.*;
+import org.osgi.service.command.CommandSession;
+import org.osgi.service.command.Converter;
+import org.apache.felix.karaf.gshell.console.ansi.AnsiOutputStream;
+import org.apache.felix.karaf.gshell.console.Completer;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InterruptedIOException;
+import java.io.PrintWriter;
+import java.lang.reflect.Method;
+import java.util.concurrent.ArrayBlockingQueue;
+import java.util.concurrent.BlockingQueue;
+import java.util.Properties;
+
+public class Console implements Runnable
+{
+
+ public static final String PROMPT = "PROMPT";
+ public static final String DEFAULT_PROMPT = "\"@|bold ${USER}|@${APPLICATION}:@|bold ${SCOPE}|> \"";
+
+ private CommandSession session;
+ private ConsoleReader reader;
+ private BlockingQueue<Integer> queue = new ArrayBlockingQueue<Integer>(1024);
+ private boolean interrupt;
+ private Thread pipe;
+ private boolean running;
+ private Runnable closeCallback;
+ private Terminal terminal;
+
+ public Console(CommandSession session, Terminal term) throws Exception
+ {
+ this(session, term, null);
+ }
+
+ public Console(CommandSession session, Terminal term, Completer completer) throws Exception
+ {
+ this(session, term, completer, null);
+ }
+
+ public Console(CommandSession session, Terminal term, Completer completer, Runnable closeCallback) throws Exception
+ {
+ this.session = session;
+ this.terminal = term == null ? new UnsupportedTerminal() : term;
+ this.closeCallback = closeCallback;
+ reader = new ConsoleReader(new ConsoleInputStream(),
+ new PrintWriter(session.getConsole()),
+ getClass().getResourceAsStream("keybinding.properties"),
+ terminal);
+ if (completer != null) {
+ reader.addCompletor(new CompleterAsCompletor(completer));
+ }
+ pipe = new Thread(new Pipe());
+ pipe.setName("gogo shell pipe thread");
+ pipe.setDaemon(true);
+ }
+
+ public void close() {
+ //System.err.println("Closing");
+ running = false;
+ pipe.interrupt();
+ Thread.interrupted();
+ }
+
+ public void run()
+ {
+ running = true;
+ pipe.start();
+ welcome();
+ while (running) {
+ try {
+ String prompt = AnsiOutputStream.decode(getPrompt());
+ String line = reader.readLine(prompt);
+ if (line == null)
+ {
+ break;
+ }
+ //session.getConsole().println("Executing: " + line);
+ Object result = session.execute(line);
+ if (result != null)
+ {
+ session.getConsole().println(session.format(result, Converter.INSPECT));
+ }
+ }
+ catch (InterruptedIOException e)
+ {
+ //System.err.println("^C");
+ // TODO: interrupt current thread
+ }
+ catch (Throwable t)
+ {
+ t.printStackTrace(session.getConsole());
+ //System.err.println("Exception: " + t.getMessage());
+ }
+ }
+ //System.err.println("Exiting console...");
+ if (closeCallback != null)
+ {
+ closeCallback.run();
+ }
+ }
+
+ protected void welcome() {
+ Properties props = new Properties();
+ loadProps(props, "/org/apache/felix/karaf/gshell/console/branding.properties");
+ loadProps(props, "/org/apache/felix/karaf/branding/branding.properties");
+ String welcome = props.getProperty("welcome");
+ if (welcome != null && welcome.length() > 0) {
+ try {
+ session.getConsole().println(AnsiOutputStream.decode(welcome));
+ } catch (IOException e) {
+ //
+ }
+ }
+ }
+
+ private void loadProps(Properties props, String resource) {
+ InputStream is = null;
+ try {
+ is = getClass().getClassLoader().getResourceAsStream(resource);
+ if (is != null) {
+ props.load(is);
+ }
+ } catch (IOException e) {
+ // ignore
+ } finally {
+ if (is != null) {
+ try {
+ is.close();
+ } catch (IOException e) {
+ // Ignore
+ }
+ }
+ }
+ }
+
+ protected String getPrompt() {
+ try {
+ String prompt;
+ try {
+ Object p = session.get(PROMPT);
+ prompt = p != null ? p.toString() : DEFAULT_PROMPT;
+ } catch (Throwable t) {
+ prompt = DEFAULT_PROMPT;
+ }
+ Object v = session.execute(prompt);
+ if (v != null) {
+ prompt = v.toString();
+ }
+ return prompt;
+ } catch (Throwable t) {
+ return "$ ";
+ }
+ }
+
+ private void checkInterrupt() throws IOException {
+ if (interrupt) {
+ interrupt = false;
+ throw new InterruptedIOException("Keyboard interruption");
+ }
+ }
+
+ private void interrupt() {
+ interrupt = true;
+ //System.err.println("Interrupt ^C");
+ }
+
+ private class ConsoleInputStream extends InputStream
+ {
+ @Override
+ public int read() throws IOException
+ {
+ if (!running)
+ {
+ return -1;
+ }
+ checkInterrupt();
+ int i;
+ try {
+ i = queue.take();
+ }
+ catch (InterruptedException e)
+ {
+ throw new InterruptedIOException();
+ }
+ if (i == 4)
+ {
+ return -1;
+ }
+ checkInterrupt();
+ return i;
+ }
+ }
+
+ private class Pipe implements Runnable
+ {
+ public void run()
+ {
+ try {
+ InputStream in = session.getKeyboard();
+ while (running)
+ {
+ try
+ {
+ int c = in.read();
+ if (c == -1 || c == 4)
+ {
+ //System.err.println("Received " + c + " ... closing");
+ session.getConsole().println("^D");
+ queue.put(c);
+ return;
+ }
+ else if (c == 3)
+ {
+ session.getConsole().println("^C");
+ reader.getCursorBuffer().clearBuffer();
+ interrupt();
+ queue.put(c);
+ }
+ else
+ {
+ queue.put(c);
+ }
+ }
+ catch (Throwable t) {
+ //System.err.println("Exception in pipe: " + t);
+ return;
+ }
+ }
+ }
+ finally
+ {
+ //System.err.println("Exiting pipe thread");
+ close();
+ }
+ }
+ }
+
+}
Added: felix/trunk/karaf/gshell/gshell-console/src/main/java/org/apache/felix/karaf/gshell/console/jline/ConsoleFactory.java
URL: http://svn.apache.org/viewvc/felix/trunk/karaf/gshell/gshell-console/src/main/java/org/apache/felix/karaf/gshell/console/jline/ConsoleFactory.java?rev=792445&view=auto
==============================================================================
--- felix/trunk/karaf/gshell/gshell-console/src/main/java/org/apache/felix/karaf/gshell/console/jline/ConsoleFactory.java (added)
+++ felix/trunk/karaf/gshell/gshell-console/src/main/java/org/apache/felix/karaf/gshell/console/jline/ConsoleFactory.java Thu Jul 9 08:29:14 2009
@@ -0,0 +1,106 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.karaf.gshell.console.jline;
+
+import java.io.InputStream;
+import java.io.PrintStream;
+import java.lang.reflect.Method;
+import java.util.List;
+
+import org.apache.felix.karaf.gshell.console.ansi.AnsiOutputStream;
+import org.apache.felix.karaf.gshell.console.Completer;
+import org.apache.felix.karaf.gshell.console.completer.AggregateCompleter;
+import org.osgi.framework.BundleContext;
+import org.osgi.service.command.CommandProcessor;
+import org.osgi.service.command.CommandSession;
+import jline.Terminal;
+
+public class ConsoleFactory {
+
+ private BundleContext bundleContext;
+ private CommandProcessor commandProcessor;
+ private List<Completer> completers;
+ private Terminal terminal;
+ private Console console;
+ private boolean start;
+
+ public void setBundleContext(BundleContext bundleContext) {
+ this.bundleContext = bundleContext;
+ }
+
+ public synchronized void registerCommandProcessor(CommandProcessor commandProcessor) throws Exception {
+ this.commandProcessor = commandProcessor;
+ start();
+ }
+
+ public synchronized void unregisterCommandProcessor(CommandProcessor commandProcessor) throws Exception {
+ this.commandProcessor = null;
+ stop();
+ }
+
+ public void setCompleters(List<Completer> completers) {
+ this.completers = completers;
+ }
+
+ public void setTerminal(Terminal terminal) {
+ this.terminal = terminal;
+ }
+
+ public void setStart(boolean start) {
+ this.start = start;
+ }
+
+ protected void start() throws Exception {
+ if (start) {
+ InputStream in = unwrap(System.in);
+ PrintStream out = unwrap(System.out);
+ PrintStream err = unwrap(System.err);
+ CommandSession session = this.commandProcessor.createSession(
+ in, new PrintStream(new AnsiOutputStream(out)), new PrintStream(new AnsiOutputStream(err)));
+ session.put("USER", "karaf");
+ session.put("APPLICATION", System.getProperty("karaf.name", "root"));
+ Runnable callback = new Runnable() {
+ public void run() {
+ try {
+ bundleContext.getBundle(0).stop();
+ } catch (Exception e) {
+ // Ignore
+ }
+ }
+ };
+ this.console = new Console(session, terminal, new AggregateCompleter(completers), callback);
+ new Thread(console, "Karaf Shell Console Thread").start();
+ }
+ }
+
+ protected void stop() throws Exception {
+ if (console != null) {
+ console.close();
+ }
+ }
+
+ private static <T> T unwrap(T stream) {
+ try {
+ Method mth = stream.getClass().getMethod("getRoot");
+ return (T) mth.invoke(stream);
+ } catch (Throwable t) {
+ return stream;
+ }
+ }
+}