/** * 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.jboss.as.test.integration.ejb.mdb.dynamic.impl; import org.jboss.as.test.integration.ejb.mdb.dynamic.adapter.TelnetActivationSpec; import org.jboss.as.test.integration.ejb.mdb.dynamic.api.TelnetListener; import org.jboss.logging.Logger; import java.io.Closeable; import java.io.DataInputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.PrintStream; import java.lang.reflect.Method; import java.net.ServerSocket; import java.net.Socket; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Map; import java.util.TreeMap; import java.util.concurrent.atomic.AtomicBoolean; public class TelnetServer implements TtyCodes { private static final Logger logger = Logger.getLogger(TelnetServer.class.getName()); private final TelnetListener listener; private final TelnetActivationSpec spec; private final int port; private final Map<String, Cmd> cmds = new TreeMap<String, Cmd>(); private final AtomicBoolean running = new AtomicBoolean(); private final ServerSocket serverSocket; public TelnetServer(TelnetActivationSpec spec, TelnetListener listener, int port) throws IOException { this.port = port; this.spec = spec; this.listener = listener; // make sure the socket is open right away this.serverSocket = new ServerSocket(port); logger.trace("Listening on " + serverSocket.getLocalPort()); for (Cmd cmd : spec.getCmds()) { this.cmds.put(cmd.getName(), cmd); } try { cmds.put("help", new BuiltInCmd("help", this.getClass().getMethod("help", String.class))); cmds.put("exit", new BuiltInCmd("exit", this.getClass().getMethod("exit"))); } catch (NoSuchMethodException e) { e.printStackTrace(); } } public TelnetListener getListener() { return listener; } public void activate() throws IOException { if (running.compareAndSet(false, true)) { while (running.get()) { final Socket accept = serverSocket.accept(); final Thread thread = new Thread() { @Override public void run() { try { session(accept); } catch (IOException e) { e.printStackTrace(); } } }; thread.start(); } } } public void deactivate() throws IOException { if (running.compareAndSet(true, false)) { try { serverSocket.close(); } catch (IOException e) { } } } public void session(Socket socket) throws IOException { InputStream telnetIn = null; PrintStream telnetOut = null; try { final InputStream in = socket.getInputStream(); final OutputStream out = socket.getOutputStream(); telnetIn = new TelnetInputStream(in, out); telnetOut = new TelnetPrintStream(out); telnetOut.println(""); telnetOut.println("type \'help\' for a list of commands"); final DataInputStream dataInputStream = new DataInputStream(telnetIn); while (running.get()) { prompt(dataInputStream, telnetOut); } } catch (StopException s) { // exit normally } catch (Throwable t) { t.printStackTrace(); } finally { close(telnetIn); close(telnetOut); if (socket != null) socket.close(); } } private static void close(Closeable closeable) { if (closeable == null) return; try { closeable.close(); } catch (IOException e) { e.printStackTrace(); } } protected void prompt(DataInputStream in, PrintStream out) throws StopException { try { out.print(TTY_Reset + TTY_Bright + spec.getPrompt() + " " + TTY_Reset); out.flush(); final String commandline = in.readLine().trim(); if (commandline.length() < 1) return; final List<String> list = new ArrayList<String>(); Collections.addAll(list, commandline.split(" +")); final String command = list.remove(0); final String[] args = list.toArray(new String[list.size()]); final Cmd cmd = cmds.get(command); if (cmd == null) { out.print(command); out.println(": command not found"); } else { try { cmd.exec(listener, args, out); } catch (StopException stop) { throw stop; } catch (Throwable throwable) { throwable.printStackTrace(out); } } } catch (StopException stop) { throw stop; } catch (UnsupportedOperationException e) { throw new StopException(e); } catch (Throwable e) { e.printStackTrace(new PrintStream(out)); throw new StopException(e); } } public class BuiltInCmd extends Cmd { public BuiltInCmd(String name, Method method) { super(name, method); } @Override public void exec(Object impl, String[] args, PrintStream out) throws Throwable { super.exec(TelnetServer.this, args, out); } } public String help(String arg) { final StringBuilder sb = new StringBuilder(); if (arg == null) { for (String s : cmds.keySet()) { sb.append(s).append("\n"); } } else { final Cmd cmd = cmds.get(arg); if (cmd == null) { sb.append("Unknown command: ").append(arg); } else { final Method method = cmd.getMethod(); sb.append(cmd.getName()).append(" "); final Class<?>[] types = method.getParameterTypes(); for (Class<?> type : types) { sb.append("<").append(type.getSimpleName().toLowerCase()).append(">").append(" "); } if (types.length == 0) { sb.append("[no options]"); } } } return sb.toString(); } public void exit() throws StopException { throw new StopException(); } public static class StopException extends Exception { public StopException() { } public StopException(Throwable cause) { super(cause); } } }