Search in sources :

Example 1 with Token

use of org.apache.felix.gogo.runtime.Token in project karaf by apache.

the class DefaultActionPreparator method prepare.

public boolean prepare(Action action, Session session, List<Object> params) throws Exception {
    Command command = action.getClass().getAnnotation(Command.class);
    Map<Option, Field> options = new HashMap<>();
    Map<Argument, Field> arguments = new HashMap<>();
    List<Argument> orderedArguments = new ArrayList<>();
    for (Class<?> type = action.getClass(); type != null; type = type.getSuperclass()) {
        for (Field field : type.getDeclaredFields()) {
            Option option = field.getAnnotation(Option.class);
            if (option != null) {
                options.put(option, field);
            }
            Argument argument = field.getAnnotation(Argument.class);
            if (argument != null) {
                argument = replaceDefaultArgument(field, argument);
                arguments.put(argument, field);
                int index = argument.index();
                while (orderedArguments.size() <= index) {
                    orderedArguments.add(null);
                }
                if (orderedArguments.get(index) != null) {
                    throw new IllegalArgumentException("Duplicate argument index: " + index + " on Action " + action.getClass().getName());
                }
                orderedArguments.set(index, argument);
            }
        }
    }
    assertIndexesAreCorrect(action.getClass(), orderedArguments);
    String commandErrorSt = COLOR_RED + "Error executing command " + command.scope() + ":" + INTENSITY_BOLD + command.name() + INTENSITY_NORMAL + COLOR_DEFAULT + ": ";
    for (Object param : params) {
        if (HelpOption.HELP.name().equals(param)) {
            int termWidth = session.getTerminal() != null ? session.getTerminal().getWidth() : 80;
            boolean globalScope = NameScoping.isGlobalScope(session, command.scope());
            printUsage(action, options, arguments, System.out, globalScope, termWidth);
            return false;
        }
    }
    // Populate
    Map<Option, Object> optionValues = new HashMap<Option, Object>();
    Map<Argument, Object> argumentValues = new HashMap<Argument, Object>();
    boolean processOptions = true;
    int argIndex = 0;
    for (Iterator<Object> it = params.iterator(); it.hasNext(); ) {
        Object param = it.next();
        String paramValue = null;
        if (param instanceof String) {
            paramValue = (String) param;
        }
        if (param instanceof Token) {
            paramValue = param.toString();
        }
        if (processOptions && paramValue != null && paramValue.startsWith("-")) {
            boolean isKeyValuePair = paramValue.indexOf('=') != -1;
            String name;
            Object value = null;
            if (isKeyValuePair) {
                name = paramValue.substring(0, paramValue.indexOf('='));
                value = paramValue.substring(paramValue.indexOf('=') + 1);
            } else {
                name = paramValue;
            }
            Option option = null;
            for (Option opt : options.keySet()) {
                if (name.equals(opt.name()) || Arrays.asList(opt.aliases()).contains(name)) {
                    option = opt;
                    break;
                }
            }
            if (option == null) {
                throw new CommandException(commandErrorSt + "undefined option " + INTENSITY_BOLD + paramValue + INTENSITY_NORMAL + "\n" + "Try <command> --help' for more information.", "Undefined option: " + paramValue);
            }
            Field field = options.get(option);
            if (value == null && (field.getType() == boolean.class || field.getType() == Boolean.class)) {
                value = Boolean.TRUE;
            }
            if (value == null && it.hasNext()) {
                value = it.next();
            }
            if (value == null) {
                throw new CommandException(commandErrorSt + "missing value for option " + INTENSITY_BOLD + paramValue + INTENSITY_NORMAL, "Missing value for option: " + paramValue);
            }
            if (option.multiValued()) {
                @SuppressWarnings("unchecked") List<Object> l = (List<Object>) optionValues.get(option);
                if (l == null) {
                    l = new ArrayList<Object>();
                    optionValues.put(option, l);
                }
                l.add(value);
            } else {
                optionValues.put(option, value);
            }
        } else {
            processOptions = false;
            if (argIndex >= orderedArguments.size()) {
                throw new CommandException(commandErrorSt + "too many arguments specified", "Too many arguments specified");
            }
            Argument argument = orderedArguments.get(argIndex);
            if (!argument.multiValued()) {
                argIndex++;
            }
            if (argument.multiValued()) {
                @SuppressWarnings("unchecked") List<Object> l = (List<Object>) argumentValues.get(argument);
                if (l == null) {
                    l = new ArrayList<Object>();
                    argumentValues.put(argument, l);
                }
                l.add(param);
            } else {
                argumentValues.put(argument, param);
            }
        }
    }
    // Check required arguments / options
    for (Option option : options.keySet()) {
        if (option.required() && optionValues.get(option) == null) {
            throw new CommandException(commandErrorSt + "option " + INTENSITY_BOLD + option.name() + INTENSITY_NORMAL + " is required", "Option " + option.name() + " is required");
        }
    }
    for (Argument argument : orderedArguments) {
        if (argument.required() && argumentValues.get(argument) == null) {
            throw new CommandException(commandErrorSt + "argument " + INTENSITY_BOLD + argument.name() + INTENSITY_NORMAL + " is required", "Argument " + argument.name() + " is required");
        }
    }
    // Convert and inject values
    for (Map.Entry<Option, Object> entry : optionValues.entrySet()) {
        Field field = options.get(entry.getKey());
        Object value;
        try {
            value = convert(action, entry.getValue(), field.getGenericType());
        } catch (Exception e) {
            throw new CommandException(commandErrorSt + "unable to convert option " + INTENSITY_BOLD + entry.getKey().name() + INTENSITY_NORMAL + " with value '" + entry.getValue() + "' to type " + new GenericType(field.getGenericType()).toString(), "Unable to convert option " + entry.getKey().name() + " with value '" + entry.getValue() + "' to type " + new GenericType(field.getGenericType()).toString(), e);
        }
        field.setAccessible(true);
        field.set(action, value);
    }
    for (Map.Entry<Argument, Object> entry : argumentValues.entrySet()) {
        Field field = arguments.get(entry.getKey());
        Object value;
        try {
            value = convert(action, entry.getValue(), field.getGenericType());
        } catch (Exception e) {
            throw new CommandException(commandErrorSt + "unable to convert argument " + INTENSITY_BOLD + entry.getKey().name() + INTENSITY_NORMAL + " with value '" + entry.getValue() + "' to type " + new GenericType(field.getGenericType()).toString(), "Unable to convert argument " + entry.getKey().name() + " with value '" + entry.getValue() + "' to type " + new GenericType(field.getGenericType()).toString(), e);
        }
        field.setAccessible(true);
        field.set(action, value);
    }
    return true;
}
Also used : Argument(org.apache.karaf.shell.api.action.Argument) HashMap(java.util.HashMap) ArrayList(java.util.ArrayList) Token(org.apache.felix.gogo.runtime.Token) Field(java.lang.reflect.Field) ArrayList(java.util.ArrayList) List(java.util.List) GenericType(org.apache.karaf.shell.support.converter.GenericType) CommandException(org.apache.karaf.shell.support.CommandException) IOException(java.io.IOException) CommandException(org.apache.karaf.shell.support.CommandException) Command(org.apache.karaf.shell.api.action.Command) Option(org.apache.karaf.shell.api.action.Option) HashMap(java.util.HashMap) Map(java.util.Map)

Example 2 with Token

use of org.apache.felix.gogo.runtime.Token in project felix by apache.

the class Activator method startShell.

private Runnable startShell(BundleContext context, CommandProcessor processor) throws Exception {
    Dictionary<String, Object> dict = new Hashtable<>();
    dict.put(CommandProcessor.COMMAND_SCOPE, "gogo");
    // register converters
    regs.add(context.registerService(Converter.class.getName(), new Converters(context.getBundle(0).getBundleContext()), null));
    // register commands
    dict.put(CommandProcessor.COMMAND_FUNCTION, Builtin.functions);
    regs.add(context.registerService(Builtin.class.getName(), new Builtin(), dict));
    dict.put(CommandProcessor.COMMAND_FUNCTION, Procedural.functions);
    regs.add(context.registerService(Procedural.class.getName(), new Procedural(), dict));
    dict.put(CommandProcessor.COMMAND_FUNCTION, Posix.functions);
    regs.add(context.registerService(Posix.class.getName(), new Posix(processor), dict));
    Shell shell = new Shell(new ShellContext(), processor);
    dict.put(CommandProcessor.COMMAND_FUNCTION, Shell.functions);
    regs.add(context.registerService(Shell.class.getName(), shell, dict));
    Terminal terminal = TerminalBuilder.builder().name("gogo").system(true).nativeSignals(true).signalHandler(Terminal.SignalHandler.SIG_IGN).build();
    CommandSession session = processor.createSession(terminal.input(), terminal.output(), terminal.output());
    AtomicBoolean closing = new AtomicBoolean();
    Thread thread = new Thread(() -> {
        String errorMessage = "gogo: unable to create console";
        try {
            session.put(Shell.VAR_TERMINAL, terminal);
            try {
                List<String> args = new ArrayList<>();
                args.add("--login");
                String argstr = shell.getContext().getProperty("gosh.args");
                if (argstr != null) {
                    Tokenizer tokenizer = new Tokenizer(argstr);
                    Token token;
                    while ((token = tokenizer.next()) != null) {
                        args.add(token.toString());
                    }
                }
                shell.gosh(session, args.toArray(new String[args.size()]));
            } catch (Throwable e) {
                Object loc = session.get(".location");
                if (null == loc || !loc.toString().contains(":")) {
                    loc = "gogo";
                }
                errorMessage = loc.toString();
                throw e;
            }
        } catch (Throwable e) {
            if (!closing.get()) {
                System.err.println(errorMessage + e.getClass().getSimpleName() + ": " + e.getMessage());
                e.printStackTrace();
            }
        }
    }, "Gogo shell");
    // start shell on a separate thread...
    thread.start();
    return () -> {
        closing.set(true);
        shell.stop();
        try {
            terminal.close();
        } catch (IOException e) {
        // Ignore
        }
        try {
            long t0 = System.currentTimeMillis();
            while (thread.isAlive()) {
                thread.interrupt();
                thread.join(10);
                if (System.currentTimeMillis() - t0 > 5000) {
                    System.err.println("!!! FAILED TO STOP EXECUTOR !!!");
                    break;
                }
            }
        } catch (InterruptedException e) {
            // Restore administration...
            Thread.currentThread().interrupt();
        }
    };
}
Also used : Hashtable(java.util.Hashtable) ArrayList(java.util.ArrayList) Token(org.apache.felix.gogo.runtime.Token) IOException(java.io.IOException) Terminal(org.jline.terminal.Terminal) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) CommandSession(org.apache.felix.service.command.CommandSession) Tokenizer(org.apache.felix.gogo.runtime.Tokenizer)

Example 3 with Token

use of org.apache.felix.gogo.runtime.Token in project felix by apache.

the class Highlighter method highlight.

public AttributedString highlight(LineReader reader, String buffer) {
    try {
        Program program = null;
        List<Token> tokens = null;
        List<Statement> statements = null;
        String repaired = buffer;
        while (program == null) {
            try {
                org.apache.felix.gogo.runtime.Parser parser = new org.apache.felix.gogo.runtime.Parser(repaired);
                program = parser.program();
                tokens = parser.tokens();
                statements = parser.statements();
            } catch (EOFError e) {
                repaired = repaired + " " + e.repair();
                // Make sure we don't loop forever
                if (repaired.length() > buffer.length() + 1024) {
                    return new AttributedStringBuilder().append(buffer).toAttributedString();
                }
            }
        }
        Map<String, String> colors = Posix.getColorMap(session, "HIGHLIGHTER", DEFAULT_HIGHLIGHTER_COLORS);
        int underlineStart = -1;
        int underlineEnd = -1;
        int negativeStart = -1;
        int negativeEnd = -1;
        String search = reader.getSearchTerm();
        if (search != null && search.length() > 0) {
            underlineStart = buffer.indexOf(search);
            if (underlineStart >= 0) {
                underlineEnd = underlineStart + search.length() - 1;
            }
        }
        if (reader.getRegionActive() != RegionType.NONE) {
            negativeStart = reader.getRegionMark();
            negativeEnd = reader.getBuffer().cursor();
            if (negativeStart > negativeEnd) {
                int x = negativeEnd;
                negativeEnd = negativeStart;
                negativeStart = x;
            }
            if (reader.getRegionActive() == RegionType.LINE) {
                while (negativeStart > 0 && reader.getBuffer().atChar(negativeStart - 1) != '\n') {
                    negativeStart--;
                }
                while (negativeEnd < reader.getBuffer().length() - 1 && reader.getBuffer().atChar(negativeEnd + 1) != '\n') {
                    negativeEnd++;
                }
            }
        }
        Type[] types = new Type[repaired.length()];
        Arrays.fill(types, Type.Unknown);
        int cur = 0;
        for (Token token : tokens) {
            // We're on the repair side, so exit now
            if (token.start() >= buffer.length()) {
                break;
            }
            if (token.start() > cur) {
                cur = token.start();
            }
            // Find corresponding statement
            Statement statement = null;
            for (int i = statements.size() - 1; i >= 0; i--) {
                Statement s = statements.get(i);
                if (s.start() <= cur && cur < s.start() + s.length()) {
                    statement = s;
                    break;
                }
            }
            // Reserved tokens
            Type type = Type.Unknown;
            if (Token.eq(token, "{") || Token.eq(token, "}") || Token.eq(token, "(") || Token.eq(token, ")") || Token.eq(token, "[") || Token.eq(token, "]") || Token.eq(token, "|") || Token.eq(token, ";") || Token.eq(token, "=")) {
                type = Type.Reserved;
            } else if (token.charAt(0) == '\'' || token.charAt(0) == '"') {
                type = Type.String;
            } else if (token.toString().matches("^[-+]?[0-9]*\\.?[0-9]+([eE][-+]?[0-9]+)?$")) {
                type = Type.Number;
            } else if (token.charAt(0) == '$') {
                type = Type.Variable;
            } else if (((Set) session.get(CommandSessionImpl.CONSTANTS)).contains(token.toString()) || Token.eq(token, "null") || Token.eq(token, "false") || Token.eq(token, "true")) {
                type = Type.Constant;
            } else {
                boolean isFirst = statement != null && statement.tokens().size() > 0 && token == statement.tokens().get(0);
                boolean isThirdWithNext = statement != null && statement.tokens().size() > 3 && token == statement.tokens().get(2);
                boolean isAssign = statement != null && statement.tokens().size() > 1 && Token.eq(statement.tokens().get(1), "=");
                if (isFirst && isAssign) {
                    type = Type.VariableName;
                }
                if (isFirst && !isAssign || isAssign && isThirdWithNext) {
                    Object v = session.get(Shell.resolve(session, token.toString()));
                    type = (v instanceof Function) ? Type.Function : Type.BadFunction;
                }
            }
            Arrays.fill(types, token.start(), Math.min(token.start() + token.length(), types.length), type);
            cur = Math.min(token.start() + token.length(), buffer.length());
        }
        if (buffer.length() < repaired.length()) {
            Arrays.fill(types, buffer.length(), repaired.length(), Type.Repair);
        }
        AttributedStringBuilder sb = new AttributedStringBuilder();
        for (int i = 0; i < repaired.length(); i++) {
            sb.style(AttributedStyle.DEFAULT);
            applyStyle(sb, colors, types[i]);
            if (i >= underlineStart && i <= underlineEnd) {
                sb.style(sb.style().underline());
            }
            if (i >= negativeStart && i <= negativeEnd) {
                sb.style(sb.style().inverse());
            }
            char c = repaired.charAt(i);
            if (c == '\t' || c == '\n') {
                sb.append(c);
            } else if (c < 32) {
                sb.style(sb.style().inverseNeg()).append('^').append((char) (c + '@')).style(sb.style().inverseNeg());
            } else {
                int w = WCWidth.wcwidth(c);
                if (w > 0) {
                    sb.append(c);
                }
            }
        }
        return sb.toAttributedString();
    } catch (SyntaxError e) {
        return super.highlight(reader, buffer);
    }
}
Also used : Program(org.apache.felix.gogo.runtime.Parser.Program) Statement(org.apache.felix.gogo.runtime.Parser.Statement) Token(org.apache.felix.gogo.runtime.Token) AttributedStringBuilder(org.jline.utils.AttributedStringBuilder) AttributedString(org.jline.utils.AttributedString) Function(org.apache.felix.service.command.Function) RegionType(org.jline.reader.LineReader.RegionType) SyntaxError(org.apache.felix.gogo.runtime.SyntaxError) EOFError(org.apache.felix.gogo.runtime.EOFError)

Example 4 with Token

use of org.apache.felix.gogo.runtime.Token in project karaf by apache.

the class KarafParser method doParse.

private ParsedLine doParse(String line, int cursor, ParseContext parseContext) throws SyntaxError {
    Program program = null;
    List<Statement> statements = null;
    String repaired = line;
    while (program == null) {
        try {
            org.apache.felix.gogo.runtime.Parser parser = new org.apache.felix.gogo.runtime.Parser(repaired);
            program = parser.program();
            statements = parser.statements();
        } catch (EOFError e) {
            // Make sure we don't loop forever
            if (parseContext == ParseContext.COMPLETE && repaired.length() < line.length() + 1024) {
                repaired = repaired + " " + e.repair();
            } else {
                throw e;
            }
        }
    }
    // Find corresponding statement
    Statement statement = null;
    for (int i = statements.size() - 1; i >= 0; i--) {
        Statement s = statements.get(i);
        if (s.start() <= cursor) {
            boolean isOk = true;
            // check if there are only spaces after the previous statement
            if (s.start() + s.length() < cursor) {
                for (int j = s.start() + s.length(); isOk && j < cursor; j++) {
                    isOk = Character.isWhitespace(line.charAt(j));
                }
            }
            statement = s;
            break;
        }
    }
    if (statement != null && statement.tokens() != null && !statement.tokens().isEmpty()) {
        String cmdName = session.resolveCommand(statement.tokens().get(0).toString());
        String[] parts = cmdName.split(":");
        Command cmd = parts.length == 2 ? session.getRegistry().getCommand(parts[0], parts[1]) : null;
        Parser cmdParser = cmd != null ? cmd.getParser() : null;
        if (cmdParser != null) {
            final CommandLine cmdLine = cmdParser.parse(session, statement.toString(), cursor - statement.start());
            return new ParsedLine() {

                @Override
                public String word() {
                    return cmdLine.getCursorArgument();
                }

                @Override
                public int wordCursor() {
                    return cmdLine.getArgumentPosition();
                }

                @Override
                public int wordIndex() {
                    return cmdLine.getCursorArgumentIndex();
                }

                @Override
                public List<String> words() {
                    return Arrays.asList(cmdLine.getArguments());
                }

                @Override
                public String line() {
                    return cmdLine.getBuffer();
                }

                @Override
                public int cursor() {
                    return cmdLine.getBufferPosition();
                }
            };
        }
        if (repaired != line) {
            Token stmt = statement.subSequence(0, line.length() - statement.start());
            List<Token> tokens = new ArrayList<>(statement.tokens());
            Token last = tokens.get(tokens.size() - 1);
            tokens.set(tokens.size() - 1, last.subSequence(0, line.length() - last.start()));
            return new ParsedLineImpl(program, stmt, cursor, tokens);
        }
        return new ParsedLineImpl(program, statement, cursor, statement.tokens());
    } else {
        // TODO:
        return new ParsedLineImpl(program, program, cursor, Collections.singletonList(program));
    }
}
Also used : Program(org.apache.felix.gogo.runtime.Parser.Program) Statement(org.apache.felix.gogo.runtime.Parser.Statement) ArrayList(java.util.ArrayList) Token(org.apache.felix.gogo.runtime.Token) Parser(org.apache.karaf.shell.api.console.Parser) CommandLine(org.apache.karaf.shell.api.console.CommandLine) Command(org.apache.karaf.shell.api.console.Command) ParsedLineImpl(org.apache.felix.gogo.jline.ParsedLineImpl) ParsedLine(org.jline.reader.ParsedLine) EOFError(org.apache.felix.gogo.runtime.EOFError)

Example 5 with Token

use of org.apache.felix.gogo.runtime.Token in project karaf by apache.

the class SecuredCommand method execute.

@Override
public Object execute(final CommandSession commandSession, List<Object> arguments) throws Exception {
    // TODO: remove the hack for .session
    Session session = (Session) commandSession.get(".session");
    // When need to translate closures to a compatible type for the command
    for (int i = 0; i < arguments.size(); i++) {
        Object v = arguments.get(i);
        if (v instanceof Closure) {
            final Closure closure = (Closure) v;
            arguments.set(i, new VersatileFunction(closure));
        }
        if (v instanceof Token) {
            arguments.set(i, v.toString());
        }
    }
    return execute(session, arguments);
}
Also used : Closure(org.apache.felix.gogo.runtime.Closure) Token(org.apache.felix.gogo.runtime.Token) Session(org.apache.karaf.shell.api.console.Session) CommandSession(org.apache.felix.service.command.CommandSession)

Aggregations

Token (org.apache.felix.gogo.runtime.Token)5 ArrayList (java.util.ArrayList)3 IOException (java.io.IOException)2 EOFError (org.apache.felix.gogo.runtime.EOFError)2 Program (org.apache.felix.gogo.runtime.Parser.Program)2 Statement (org.apache.felix.gogo.runtime.Parser.Statement)2 CommandSession (org.apache.felix.service.command.CommandSession)2 Field (java.lang.reflect.Field)1 HashMap (java.util.HashMap)1 Hashtable (java.util.Hashtable)1 List (java.util.List)1 Map (java.util.Map)1 AtomicBoolean (java.util.concurrent.atomic.AtomicBoolean)1 ParsedLineImpl (org.apache.felix.gogo.jline.ParsedLineImpl)1 Closure (org.apache.felix.gogo.runtime.Closure)1 SyntaxError (org.apache.felix.gogo.runtime.SyntaxError)1 Tokenizer (org.apache.felix.gogo.runtime.Tokenizer)1 Function (org.apache.felix.service.command.Function)1 Argument (org.apache.karaf.shell.api.action.Argument)1 Command (org.apache.karaf.shell.api.action.Command)1