blob: 401bb000ebab9c251e92b62b0a714c62ed3177b3 [file] [log] [blame]
/*
* 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.
*/
// DWB11: add removeCommand: https://www.osgi.org/bugzilla/show_bug.cgi?id=49
// DWB12: there is no API to list commands: https://www.osgi.org/bugzilla/show_bug.cgi?id=49
// DWB13: addCommand() fails to add static methods (if target is Class)
package aQute.shell.runtime;
import java.io.*;
import java.lang.reflect.*;
import java.util.*;
import org.osgi.service.command.*;
import org.osgi.service.threadio.*;
public class CommandShellImpl implements CommandProcessor {
Set<Converter> converters = new HashSet<Converter>();
protected ThreadIO threadIO;
public final static Object NO_SUCH_COMMAND = new Object();
Map<String, Object> commands = new LinkedHashMap<String, Object>();
public CommandShellImpl() {
addCommand("shell", this, "addCommand" );
addCommand("shell", this, "removeCommand" ); // derek
}
public CommandSession createSession(InputStream in, PrintStream out,
PrintStream err) {
return new CommandSessionImpl(this, in, out, err);
}
public void setThreadio(ThreadIO threadIO) {
this.threadIO = threadIO;
}
public void setConverter(Converter c) {
converters.add(c);
}
public void unsetConverter(Converter c) {
converters.remove(c);
}
public Object get(String name) {
name = name.toLowerCase();
int n = name.indexOf(':');
if (n < 0)
return null;
String function = name.substring(n);
Object cmd = null;
if (commands.containsKey(name)) {
cmd = commands.get(name);
} else {
String scope = name.substring(0, n);
if (scope.equals("*")) {
for (Map.Entry<String, Object> entry : commands.entrySet()) {
if (entry.getKey().endsWith(function)) {
cmd = entry.getValue();
break;
}
}
}
// XXX: derek.baum@paremus.com
// there is no API to list commands
// so override otherwise illegal name ":"
if (cmd == null && name.equals(":")) {
return Collections.unmodifiableSet(commands.keySet());
}
}
if (cmd == null)
return null;
if (cmd instanceof Function)
return cmd;
else
return new Command(cmd, function.substring(1));
}
public void addCommand(String scope, Object target) {
// derek - fix target class
Class<?> tc = (target instanceof Class) ? (Class<?>) target : target.getClass();
addCommand(scope, target, tc);
}
public void addCommand(String scope, Object target, Class<?> functions) {
if (target == null)
return;
String[] names = getFunctions(functions);
for (String function : names) {
addCommand(scope, target, function);
}
}
public void addCommand(String scope, Object target, String function) {
commands.put((scope + ":" + function).toLowerCase(), target);
}
// derek.baum@paremus.com: need removeCommand, so stopped bundles can clean up.
public void removeCommand(String scope, String function) {
String func = (scope + ":" + function).toLowerCase();
commands.remove(func);
}
public void removeCommand(Object target) {
for (Iterator<Object> i = commands.values().iterator(); i.hasNext();) {
if (i.next() == target)
i.remove();
}
}
private String[] getFunctions(Class<?> target) {
String[] functions;
Set<String> list = new TreeSet<String>();
Method methods[] = target.getMethods();
for (Method m : methods) {
if (m.getDeclaringClass().equals(Object.class)) // derek
continue;
list.add(m.getName());
if (m.getName().startsWith("get")) {
String s = m.getName().substring(3);
if (s.length() > 0)
list.add(s.substring(0, 1).toLowerCase() + s.substring(1));
}
}
functions = list.toArray(new String[list.size()]);
return functions;
}
protected void put(String name, Object target) {
commands.put(name, target);
}
public Object convert(Class<?> desiredType, Object in) {
for ( Converter c : converters ) {
try {
Object converted = c.convert(desiredType, in);
if ( converted != null)
return converted;
} catch( Exception e ) {
e.printStackTrace();
}
}
return null;
}
}