Added: 
felix/trunk/gogo/jline/src/main/java/org/apache/felix/gogo/jline/ssh/ShellFactoryImpl.java
URL: 
http://svn.apache.org/viewvc/felix/trunk/gogo/jline/src/main/java/org/apache/felix/gogo/jline/ssh/ShellFactoryImpl.java?rev=1735995&view=auto
==============================================================================
--- 
felix/trunk/gogo/jline/src/main/java/org/apache/felix/gogo/jline/ssh/ShellFactoryImpl.java
 (added)
+++ 
felix/trunk/gogo/jline/src/main/java/org/apache/felix/gogo/jline/ssh/ShellFactoryImpl.java
 Mon Mar 21 16:53:06 2016
@@ -0,0 +1,277 @@
+/*
+ * 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.gogo.jline.ssh;
+
+import java.io.Closeable;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.PrintStream;
+import java.util.Map;
+
+import org.apache.felix.gogo.jline.Shell;
+import org.apache.felix.gogo.jline.Shell.Context;
+import org.apache.felix.service.command.CommandProcessor;
+import org.apache.felix.service.command.CommandSession;
+import org.apache.sshd.common.Factory;
+import org.apache.sshd.common.channel.PtyMode;
+import org.apache.sshd.server.Command;
+import org.apache.sshd.server.Environment;
+import org.apache.sshd.server.ExitCallback;
+import org.apache.sshd.server.SessionAware;
+import org.apache.sshd.server.Signal;
+import org.apache.sshd.server.SignalListener;
+import org.apache.sshd.server.session.ServerSession;
+import org.jline.terminal.Attributes;
+import org.jline.terminal.Attributes.ControlChar;
+import org.jline.terminal.Attributes.InputFlag;
+import org.jline.terminal.Attributes.LocalFlag;
+import org.jline.terminal.Attributes.OutputFlag;
+import org.jline.terminal.Size;
+import org.jline.terminal.Terminal;
+import org.jline.terminal.TerminalBuilder;
+
+/**
+ * SSHD {@link org.apache.sshd.server.Command} factory which provides access to
+ * Shell.
+ */
+public class ShellFactoryImpl implements Factory<Command> {
+    private final CommandProcessor processor;
+
+    public ShellFactoryImpl(CommandProcessor processor) {
+        this.processor = processor;
+    }
+
+    private static void flush(OutputStream... streams) {
+        for (OutputStream s : streams) {
+            try {
+                s.flush();
+            } catch (IOException e) {
+                // Ignore
+            }
+        }
+    }
+
+    static void close(Closeable... closeables) {
+        for (Closeable c : closeables) {
+            try {
+                c.close();
+            } catch (IOException e) {
+                // Ignore
+            }
+        }
+    }
+
+    public Command create() {
+        return new ShellImpl();
+    }
+
+    public class ShellImpl implements Command, SessionAware {
+        private InputStream in;
+
+        private OutputStream out;
+
+        private OutputStream err;
+
+        private ExitCallback callback;
+
+        private ServerSession session;
+
+        private boolean closed;
+
+        public void setInputStream(final InputStream in) {
+            this.in = in;
+        }
+
+        public void setOutputStream(final OutputStream out) {
+            this.out = out;
+        }
+
+        public void setErrorStream(final OutputStream err) {
+            this.err = err;
+        }
+
+        public void setExitCallback(ExitCallback callback) {
+            this.callback = callback;
+        }
+
+        public void setSession(ServerSession session) {
+            this.session = session;
+        }
+
+        public void start(final Environment env) throws IOException {
+            try {
+                new Thread() {
+                    public void run() {
+                        try {
+                            ShellImpl.this.run(env);
+                        } catch (Throwable t) {
+                            t.printStackTrace();
+                        }
+                    }
+                }.start();
+            } catch (Exception e) {
+                throw (IOException) new IOException("Unable to start 
shell").initCause(e);
+            }
+        }
+
+        public void run(Environment env) throws Exception {
+            try {
+                Terminal terminal = TerminalBuilder.builder()
+                        .name("gogo")
+                        .type(env.getEnv().get("TERM"))
+                        .system(false)
+                        .streams(in, out)
+                        .build();
+                terminal.setSize(new 
Size(Integer.parseInt(env.getEnv().get("COLUMNS")),
+                        Integer.parseInt(env.getEnv().get("LINES"))));
+                Attributes attr = terminal.getAttributes();
+                for (Map.Entry<PtyMode, Integer> e : 
env.getPtyModes().entrySet()) {
+                    switch (e.getKey()) {
+                        case VINTR:
+                            attr.setControlChar(ControlChar.VINTR, 
e.getValue());
+                            break;
+                        case VQUIT:
+                            attr.setControlChar(ControlChar.VQUIT, 
e.getValue());
+                            break;
+                        case VERASE:
+                            attr.setControlChar(ControlChar.VERASE, 
e.getValue());
+                            break;
+                        case VKILL:
+                            attr.setControlChar(ControlChar.VKILL, 
e.getValue());
+                            break;
+                        case VEOF:
+                            attr.setControlChar(ControlChar.VEOF, 
e.getValue());
+                            break;
+                        case VEOL:
+                            attr.setControlChar(ControlChar.VEOL, 
e.getValue());
+                            break;
+                        case VEOL2:
+                            attr.setControlChar(ControlChar.VEOL2, 
e.getValue());
+                            break;
+                        case VSTART:
+                            attr.setControlChar(ControlChar.VSTART, 
e.getValue());
+                            break;
+                        case VSTOP:
+                            attr.setControlChar(ControlChar.VSTOP, 
e.getValue());
+                            break;
+                        case VSUSP:
+                            attr.setControlChar(ControlChar.VSUSP, 
e.getValue());
+                            break;
+                        case VDSUSP:
+                            attr.setControlChar(ControlChar.VDSUSP, 
e.getValue());
+                            break;
+                        case VREPRINT:
+                            attr.setControlChar(ControlChar.VREPRINT, 
e.getValue());
+                            break;
+                        case VWERASE:
+                            attr.setControlChar(ControlChar.VWERASE, 
e.getValue());
+                            break;
+                        case VLNEXT:
+                            attr.setControlChar(ControlChar.VLNEXT, 
e.getValue());
+                            break;
+                        /*
+                        case VFLUSH:
+                            attr.setControlChar(ControlChar.VMIN, 
e.getValue());
+                            break;
+                        case VSWTCH:
+                            attr.setControlChar(ControlChar.VTIME, 
e.getValue());
+                            break;
+                        */
+                        case VSTATUS:
+                            attr.setControlChar(ControlChar.VSTATUS, 
e.getValue());
+                            break;
+                        case VDISCARD:
+                            attr.setControlChar(ControlChar.VDISCARD, 
e.getValue());
+                            break;
+                        case ECHO:
+                            attr.setLocalFlag(LocalFlag.ECHO, e.getValue() != 
0);
+                            break;
+                        case ICANON:
+                            attr.setLocalFlag(LocalFlag.ICANON, e.getValue() 
!= 0);
+                            break;
+                        case ISIG:
+                            attr.setLocalFlag(LocalFlag.ISIG, e.getValue() != 
0);
+                            break;
+                        case ICRNL:
+                            attr.setInputFlag(InputFlag.ICRNL, e.getValue() != 
0);
+                            break;
+                        case INLCR:
+                            attr.setInputFlag(InputFlag.INLCR, e.getValue() != 
0);
+                            break;
+                        case IGNCR:
+                            attr.setInputFlag(InputFlag.IGNCR, e.getValue() != 
0);
+                            break;
+                        case OCRNL:
+                            attr.setOutputFlag(OutputFlag.OCRNL, e.getValue() 
!= 0);
+                            break;
+                        case ONLCR:
+                            attr.setOutputFlag(OutputFlag.ONLCR, e.getValue() 
!= 0);
+                            break;
+                        case ONLRET:
+                            attr.setOutputFlag(OutputFlag.ONLRET, e.getValue() 
!= 0);
+                            break;
+                        case OPOST:
+                            attr.setOutputFlag(OutputFlag.OPOST, e.getValue() 
!= 0);
+                            break;
+                    }
+                }
+                terminal.setAttributes(attr);
+                PrintStream pout = new PrintStream(terminal.output());
+                final CommandSession session = 
processor.createSession(terminal.input(), pout, pout);
+                for (Map.Entry<String, String> e : env.getEnv().entrySet()) {
+                    session.put(e.getKey(), e.getValue());
+                }
+                env.addSignalListener(new SignalListener() {
+                    @Override
+                    public void signal(Signal signal) {
+                        terminal.setSize(new 
Size(Integer.parseInt(env.getEnv().get("COLUMNS")),
+                                Integer.parseInt(env.getEnv().get("LINES"))));
+                        terminal.raise(Terminal.Signal.WINCH);
+                    }
+                }, Signal.WINCH);
+                Context context = new Context() {
+                    @Override
+                    public String getProperty(String name) {
+                        return System.getProperty(name);
+                    }
+
+                    @Override
+                    public void exit() throws Exception {
+                        destroy();
+                    }
+                };
+                new Shell(context, processor, terminal).gosh(session, new 
String[]{"--login"});
+            } catch (Throwable t) {
+                t.printStackTrace();
+            }
+        }
+
+        public void destroy() {
+            if (!closed) {
+                closed = true;
+                ShellFactoryImpl.flush(out, err);
+                ShellFactoryImpl.close(in, out, err);
+                callback.onExit(0);
+            }
+        }
+
+    }
+
+}

Added: 
felix/trunk/gogo/jline/src/main/java/org/apache/felix/gogo/jline/ssh/Ssh.java
URL: 
http://svn.apache.org/viewvc/felix/trunk/gogo/jline/src/main/java/org/apache/felix/gogo/jline/ssh/Ssh.java?rev=1735995&view=auto
==============================================================================
--- 
felix/trunk/gogo/jline/src/main/java/org/apache/felix/gogo/jline/ssh/Ssh.java 
(added)
+++ 
felix/trunk/gogo/jline/src/main/java/org/apache/felix/gogo/jline/ssh/Ssh.java 
Mon Mar 21 16:53:06 2016
@@ -0,0 +1,115 @@
+/*
+ * 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.gogo.jline.ssh;
+
+import java.io.IOException;
+import java.util.Collections;
+import java.util.List;
+
+import org.apache.felix.service.command.CommandProcessor;
+import org.apache.felix.service.command.CommandSession;
+import org.apache.sshd.common.NamedFactory;
+import org.apache.sshd.server.Command;
+import org.apache.sshd.server.ServerBuilder;
+import org.apache.sshd.server.SshServer;
+import org.apache.sshd.server.command.ScpCommandFactory;
+import org.apache.sshd.server.keyprovider.SimpleGeneratorHostKeyProvider;
+import org.apache.sshd.server.subsystem.sftp.SftpSubsystemFactory;
+import org.jline.builtins.Options;
+
+public class Ssh {
+
+    public static final String[] functions = {"sshd"};
+
+    private static final int defaultPort = 2022;
+
+    private final CommandProcessor processor;
+    private SshServer server;
+    private Object context;
+    private int port;
+    private String ip;
+
+    public Ssh(CommandProcessor processor) {
+        this.processor = processor;
+    }
+
+    public void sshd(CommandSession session, String[] argv) throws IOException 
{
+        final String[] usage = {"sshd - start an ssh server",
+                "Usage: sshd [-i ip] [-p port] start | stop | status",
+                "  -i --ip=INTERFACE        listen interface 
(default=127.0.0.1)",
+                "  -p --port=PORT           listen port (default=" + 
defaultPort + ")",
+                "  -? --help                show help"};
+
+        Options opt = Options.compile(usage).parse(argv);
+        List<String> args = opt.args();
+
+        if (opt.isSet("help") || args.isEmpty()) {
+            opt.usage(System.err);
+            return;
+        }
+
+        String command = args.get(0);
+
+        if ("start".equals(command)) {
+            if (server != null) {
+                throw new IllegalStateException("sshd is already running on 
port " + port);
+            }
+            ip = opt.get("ip");
+            port = opt.getNumber("port");
+            context = 
session.get(org.apache.felix.gogo.runtime.activator.Activator.CONTEXT);
+            start();
+            status();
+        } else if ("stop".equals(command)) {
+            if (server == null) {
+                throw new IllegalStateException("sshd is not running.");
+            }
+            stop();
+        } else if ("status".equals(command)) {
+            status();
+        } else {
+            throw opt.usageError("bad command: " + command);
+        }
+
+    }
+
+    private void status() {
+        if (server != null) {
+            System.out.println("sshd is running on " + ip + ":" + port);
+        } else {
+            System.out.println("sshd is not running.");
+        }
+    }
+
+    private void start() throws IOException {
+        server = ServerBuilder.builder().build();
+        server.setPort(port);
+        server.setHost(ip);
+        server.setShellFactory(new ShellFactoryImpl(processor));
+        server.setCommandFactory(new 
ScpCommandFactory.Builder().withDelegate(new 
ShellCommandFactory(processor)).build());
+        
server.setSubsystemFactories(Collections.<NamedFactory<Command>>singletonList(
+                new SftpSubsystemFactory.Builder().build()
+        ));
+        server.setKeyPairProvider(new SimpleGeneratorHostKeyProvider());
+        server.start();
+    }
+
+    private void stop() throws IOException {
+        server.stop();
+    }
+}

Added: 
felix/trunk/gogo/jline/src/main/java/org/apache/felix/gogo/jline/telnet/BootException.java
URL: 
http://svn.apache.org/viewvc/felix/trunk/gogo/jline/src/main/java/org/apache/felix/gogo/jline/telnet/BootException.java?rev=1735995&view=auto
==============================================================================
--- 
felix/trunk/gogo/jline/src/main/java/org/apache/felix/gogo/jline/telnet/BootException.java
 (added)
+++ 
felix/trunk/gogo/jline/src/main/java/org/apache/felix/gogo/jline/telnet/BootException.java
 Mon Mar 21 16:53:06 2016
@@ -0,0 +1,73 @@
+/*
+ * 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.
+ */
+
+/***
+ * Java TelnetD library (embeddable telnet daemon)
+ * Copyright (c) 2000-2005 Dieter Wimberger
+ * All rights reserved.
+ * <p/>
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * <p/>
+ * Neither the name of the author nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ * <p/>
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS ``AS
+ * IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ ***/
+
+package org.apache.felix.gogo.jline.telnet;
+
+/**
+ * Class that implements a BootException.<br>
+ * This exception will flag a broken boot process,
+ * which expresses startup failure and unavailabilty
+ * of telnet service for the container application.
+ *
+ * @author Dieter Wimberger
+ * @version 2.0 (16/07/2006)
+ */
+public class BootException extends Exception {
+
+    /**
+     * Constructor method for a BootException.<br>
+     *
+     * @param msg String that contains an understandable failure message.
+     */
+    public BootException(String msg) {
+        super(msg);
+    }//constructor
+
+}//class BootException
\ No newline at end of file

Added: 
felix/trunk/gogo/jline/src/main/java/org/apache/felix/gogo/jline/telnet/Connection.java
URL: 
http://svn.apache.org/viewvc/felix/trunk/gogo/jline/src/main/java/org/apache/felix/gogo/jline/telnet/Connection.java?rev=1735995&view=auto
==============================================================================
--- 
felix/trunk/gogo/jline/src/main/java/org/apache/felix/gogo/jline/telnet/Connection.java
 (added)
+++ 
felix/trunk/gogo/jline/src/main/java/org/apache/felix/gogo/jline/telnet/Connection.java
 Mon Mar 21 16:53:06 2016
@@ -0,0 +1,257 @@
+/*
+ * 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.
+ */
+
+/***
+ * Java TelnetD library (embeddable telnet daemon)
+ * Copyright (c) 2000-2005 Dieter Wimberger
+ * All rights reserved.
+ * <p/>
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * <p/>
+ * Neither the name of the author nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ * <p/>
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS ``AS
+ * IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ ***/
+
+package org.apache.felix.gogo.jline.telnet;
+
+import java.util.List;
+import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * Class that implements a connection with this telnet daemon.<br>
+ * It is derived from java.lang.Thread, which reflects the architecture
+ * constraint of one thread per connection. This might seem a waste of
+ * resources, but as a matter of fact sharing threads would require a
+ * far more complex imlementation, due to the fact that telnet is not a
+ * stateless protocol (i.e. alive throughout a session of multiple requests
+ * and responses).<br>
+ * Each Connection instance is created by the listeners ConnectionManager
+ * instance, making it part of a threadgroup and passing in an associated
+ * ConnectionData instance, that holds vital information about the connection.
+ * Be sure to take a look at their documention.<br>
+ * <p/>
+ * Once the thread has started and is running, it will get a login
+ * shell instance from the ShellManager and run passing its own reference.
+ *
+ * @author Dieter Wimberger
+ * @version 2.0 (16/07/2006)
+ * @see ConnectionManager
+ * @see ConnectionData
+ */
+public abstract class Connection
+        extends Thread {
+
+    private static final Logger LOG = 
Logger.getLogger(Connection.class.getName());
+    private static int number;            //unique number for a thread in the 
thread group
+    private boolean dead;
+    private List<ConnectionListener> listeners;
+
+    //Associations
+    private ConnectionData connectionData;    //associated information
+
+    /**
+     * Constructs a TelnetConnection by invoking its parent constructor
+     * and setting of various members.<br>
+     * Subsequently instantiates the whole i/o subsystem, negotiating
+     * telnet protocol level options etc.<br>
+     *
+     * @param tcg ThreadGroup that this instance is running in.
+     * @param cd  ConnectionData instance containing all vital information
+     *            of this connection.
+     * @see ConnectionData
+     */
+    public Connection(ThreadGroup tcg, ConnectionData cd) {
+        super(tcg, ("Connection" + (++number)));
+
+        connectionData = cd;
+        //init the connection listeners for events
+        //(there should actually be only one or two)
+        listeners = new CopyOnWriteArrayList<ConnectionListener>();
+        dead = false;
+    }//constructor
+
+    /**
+     * Method overloaded to implement following behaviour:
+     * <ol>
+     * <li> On first entry, retrieve an instance of the configured
+     * login shell from the ShellManager and run it.
+     * <li> Handle a shell switch or close down disgracefully when
+     * problems (i.e. unhandled unchecked exceptions) occur in the
+     * running shell.
+     * </ol>
+     */
+    public void run() {
+        try {
+            doRun();
+
+        } catch (Exception ex) {
+            LOG.log(Level.SEVERE, "run()", ex); //Handle properly
+        } finally {
+            //call close if not dead already
+            if (!dead) {
+                close();
+            }
+        }
+        LOG.log(Level.FINE, "run():: Returning from " + this.toString());
+    }//run
+
+    protected abstract void doRun() throws Exception;
+
+    protected abstract void doClose() throws Exception;
+
+    /**
+     * Method to access the associated connection data.
+     *
+     * @return ConnectionData associated with the Connection instance.
+     * @see ConnectionData
+     */
+    public ConnectionData getConnectionData() {
+        return connectionData;
+    }//getConnectionData
+
+    /**
+     * Closes the connection and its underlying i/o and network
+     * resources.<br>
+     */
+    public synchronized void close() {
+        if (dead) {
+            return;
+        } else {
+            try {
+                //connection dead
+                dead = true;
+                //close i/o
+                doClose();
+            } catch (Exception ex) {
+                LOG.log(Level.SEVERE, "close()", ex);
+                //handle
+            }
+            try {
+                //close socket
+                connectionData.getSocket().close();
+            } catch (Exception ex) {
+                LOG.log(Level.SEVERE, "close()", ex);
+                //handle
+            }
+            try {
+                //register closed connection in ConnectionManager
+                connectionData.getManager().registerClosedConnection(this);
+            } catch (Exception ex) {
+                LOG.log(Level.SEVERE, "close()", ex);
+                //handle
+            }
+            try {
+                //try to interrupt it
+                interrupt();
+            } catch (Exception ex) {
+                LOG.log(Level.SEVERE, "close()", ex);
+                //handle
+            }
+
+
+            LOG.log(Level.FINE, "Closed " + this.toString() + " and 
inactive.");
+        }
+    }//close
+
+    /**
+     * Returns if a connection has been closed.<br>
+     *
+     * @return the state of the connection.
+     */
+    public boolean isActive() {
+        return !dead;
+    }//isClosed
+
+    /****** Event handling ****************/
+
+    /**
+     * Method that registers a ConnectionListener with the
+     * Connection instance.
+     *
+     * @param cl ConnectionListener to be registered.
+     * @see ConnectionListener
+     */
+    public void addConnectionListener(ConnectionListener cl) {
+        listeners.add(cl);
+    }//addConnectionListener
+
+    /**
+     * Method that removes a ConnectionListener from the
+     * Connection instance.
+     *
+     * @param cl ConnectionListener to be removed.
+     * @see ConnectionListener
+     */
+    public void removeConnectionListener(ConnectionListener cl) {
+        listeners.remove(cl);
+    }//removeConnectionListener
+
+
+    /**
+     * Method called by the io subsystem to pass on a
+     * "low-level" event. It will be properly delegated to
+     * all registered listeners.
+     *
+     * @param ce ConnectionEvent to be processed.
+     * @see ConnectionEvent
+     */
+    public void processConnectionEvent(ConnectionEvent ce) {
+        for (ConnectionListener cl : listeners) {
+            switch (ce.getType()) {
+                case CONNECTION_IDLE:
+                    cl.connectionIdle(ce);
+                    break;
+                case CONNECTION_TIMEDOUT:
+                    cl.connectionTimedOut(ce);
+                    break;
+                case CONNECTION_LOGOUTREQUEST:
+                    cl.connectionLogoutRequest(ce);
+                    break;
+                case CONNECTION_BREAK:
+                    cl.connectionSentBreak(ce);
+                    break;
+                case CONNECTION_TERMINAL_GEOMETRY_CHANGED:
+                    cl.connectionTerminalGeometryChanged(ce);
+            }
+        }
+    }//processConnectionEvent
+
+}//class Connection

Added: 
felix/trunk/gogo/jline/src/main/java/org/apache/felix/gogo/jline/telnet/ConnectionData.java
URL: 
http://svn.apache.org/viewvc/felix/trunk/gogo/jline/src/main/java/org/apache/felix/gogo/jline/telnet/ConnectionData.java?rev=1735995&view=auto
==============================================================================
--- 
felix/trunk/gogo/jline/src/main/java/org/apache/felix/gogo/jline/telnet/ConnectionData.java
 (added)
+++ 
felix/trunk/gogo/jline/src/main/java/org/apache/felix/gogo/jline/telnet/ConnectionData.java
 Mon Mar 21 16:53:06 2016
@@ -0,0 +1,449 @@
+/*
+ * 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.
+ */
+
+/***
+ * Java TelnetD library (embeddable telnet daemon)
+ * Copyright (c) 2000-2005 Dieter Wimberger
+ * All rights reserved.
+ * <p/>
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * <p/>
+ * Neither the name of the author nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ * <p/>
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS ``AS
+ * IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ ***/
+
+package org.apache.felix.gogo.jline.telnet;
+
+import java.net.InetAddress;
+import java.net.Socket;
+import java.util.HashMap;
+import java.util.Locale;
+import java.util.Map;
+
+/**
+ * An utility class that is used to store and allow retrieval
+ * of all data associated with a connection.
+ *
+ * @author Dieter Wimberger
+ * @version 2.0 (16/07/2006)
+ * @see Connection
+ */
+public class ConnectionData {
+
+    //Associations
+    private ConnectionManager connectionManager;    //the connection's 
ConnectionManager
+    private Socket socket;                            //the connection's socket
+    private InetAddress address;                    //the connection's IP 
Address Object
+    private Map<String, String> environment;        //the environment
+
+    //Members
+    private String hostName;                        //cache for the hostname
+    private String hostAddress;                        //cache for the host ip
+    private int port;                                //port of the connection
+    private Locale locale;                            //locale of the 
connection
+    private long lastActivity;                        //timestamp for the last 
activity
+    private boolean warned;                            //warned flag
+    private String negotiatedTerminalType;            //negotiated 
TerminalType as String
+    private int[] terminalGeometry;                    //negotiated terminal 
geometry
+    private boolean terminalGeometryChanged = true;    //flag for changes in 
the terminal geometry
+    private String loginShell;                      //the login shell
+    private boolean lineMode = false;
+
+    /**
+     * Constructs a ConnectionData instance storing vital
+     * information about a connection.
+     *
+     * @param sock Socket of the inbound connection.
+     */
+    public ConnectionData(Socket sock, ConnectionManager cm) {
+        socket = sock;
+        connectionManager = cm;
+        address = sock.getInetAddress();
+        setHostName();
+        setHostAddress();
+        setLocale();
+        port = sock.getPort();
+        //this will set a default geometry and terminal type for the terminal
+        terminalGeometry = new int[2];
+        terminalGeometry[0] = 80;    //width
+        terminalGeometry[1] = 25;    //height
+        negotiatedTerminalType = "default";
+        environment = new HashMap<String, String>(20);
+        //this will stamp the first activity for validity :)
+        activity();
+    }//ConnectionData
+
+
+    /**
+     * Returns a reference to the ConnectionManager the
+     * connection is associated with.
+     *
+     * @return Reference to the associated ConnectionManager.
+     * @see ConnectionManager
+     */
+    public ConnectionManager getManager() {
+        return connectionManager;
+    }//getManager
+
+    /**
+     * Returns a reference to the socket the Connection
+     * is associated with.
+     *
+     * @return Reference to the associated Socket.
+     * @see java.net.Socket
+     */
+    public Socket getSocket() {
+        return socket;
+    }//getSocket
+
+    /**
+     * Returns the remote port to which the socket is connected.
+     *
+     * @return String that contains the remote port number to which the socket 
is connected.
+     */
+    public int getPort() {
+        return port;
+    }//getPort
+
+    /**
+     * Returns the fully qualified host name for the connection's IP 
address.<br>
+     * The name is cached on creation for performance reasons. Subsequent calls
+     * will not result in resolve queries.
+     *
+     * @return String that contains the fully qualified host name for this 
address.
+     */
+    public String getHostName() {
+        return hostName;
+    }//getHostName
+
+    /**
+     * Returns the IP address of the connection.
+     *
+     * @return String that contains the connection's IP address.<br>
+     *         The format "%d.%d.%d.%d" is well known, where %d goes from zero 
to 255.
+     */
+    public String getHostAddress() {
+        return hostAddress;
+    }//getHostAddress
+
+    /**
+     * Returns the InetAddress object associated with the connection.
+     *
+     * @return InetAddress associated with the connection.
+     */
+    public InetAddress getInetAddress() {
+        return address;
+    }//getInetAddress
+
+    /**
+     * Returns the Locale object associated with the connection
+     * by carrying out a simple domain match. <br>
+     * This can either be effective, if your users are really
+     * home in the country they are connecting from,
+     * or ineffective if they are on the move getting connected
+     * from anywhere in the world.<br>
+     * <br>
+     * Yet this gives the chance of capturing a default locale
+     * and starting from some point. On application context
+     * this can be by far better handled, so be aware that
+     * it makes sense to spend some thoughts on that thing when you
+     * build your application.
+     *
+     * @return the Locale object "guessed" for the connection based
+     *         on its host name.
+     */
+    public Locale getLocale() {
+        return locale;
+    }//getLocale
+
+
+    /**
+     * Returns a timestamp of the last activity that happened on
+     * the associated connection.
+     *
+     * @return the timestamp as a long representing the difference,
+     *         measured in milliseconds, between the current time and
+     *         midnight, January 1, 1970 UTC.
+     */
+    public long getLastActivity() {
+        return lastActivity;
+    }//getLastActivity
+
+
+    /**
+     * Sets a new timestamp to the actual time in millis
+     * retrieved from the System. This will remove an idle warning
+     * flag if it has been set. Note that you can use this behaviour
+     * to implement your own complex idle timespan policies within
+     * the context of your application.<br>
+     * The check frequency of the ConnectionManager should just be set
+     * according to the lowest time to warning and time to disconnect
+     * requirements.
+     */
+    public void activity() {
+        warned = false;
+        lastActivity = System.currentTimeMillis();
+    }//setLastActivity
+
+    /**
+     * Returns the state of the idle warning flag, which
+     * will be true if a warning has been issued, and false
+     * if not.
+     *
+     * @return the state of the idle warning flag.
+     */
+    public boolean isWarned() {
+        return warned;
+    }//isWarned
+
+    /**
+     * Sets the state of the idle warning flag.<br>
+     * Note that this method will also update the
+     * the timestamp if the idle warning flag is removed,
+     * which means its kind of a second way to achieve the
+     * same thing as with the activity method.
+     *
+     * @param bool true if a warning is to be issued,
+     *             false if to be removed.
+     * @see #activity()
+     */
+    public void setWarned(boolean bool) {
+        warned = bool;
+        if (!bool) {
+            lastActivity = System.currentTimeMillis();
+        }
+    }//setWarned
+
+    /**
+     * Sets the terminal geometry data.<br>
+     * <em>This method should not be called explicitly
+     * by the application (i.e. the its here for the io subsystem).</em><br>
+     * A call will set the terminal geometry changed flag.
+     *
+     * @param width  of the terminal in columns.
+     * @param height of the terminal in rows.
+     */
+    public void setTerminalGeometry(int width, int height) {
+        terminalGeometry[0] = width;
+        terminalGeometry[1] = height;
+        terminalGeometryChanged = true;
+    }//setTerminalGeometry
+
+    /**
+     * Returns the terminal geometry in an array of two integers.
+     * <ul>
+     * <li>index 0: Width in columns.
+     * <li>index 1: Height in rows.
+     * </ul>
+     * A call will reset the terminal geometry changed flag.
+     *
+     * @return integer array containing width and height.
+     */
+    public int[] getTerminalGeometry() {
+        //we toggle the flag because the change should now be known
+        if (terminalGeometryChanged) terminalGeometryChanged = false;
+        return terminalGeometry;
+    }//getTerminalGeometry
+
+    /**
+     * Returns the width of the terminal in columns for convenience.
+     *
+     * @return the number of columns.
+     */
+    public int getTerminalColumns() {
+        return terminalGeometry[0];
+    }//getTerminalColumns
+
+    /**
+     * Returns the height of the terminal in rows for convenience.
+     *
+     * @return the number of rows.
+     */
+    public int getTerminalRows() {
+        return terminalGeometry[1];
+    }//getTerminalRows
+
+    /**
+     * Returns the state of the terminal geometry changed flag,
+     * which will be true if it has been set, and false
+     * if not.
+     *
+     * @return the state of the terminal geometry changed flag.
+     */
+    public boolean isTerminalGeometryChanged() {
+        return terminalGeometryChanged;
+    }//isTerminalGeometryChanged
+
+    /**
+     * Returns the terminal type that has been negotiated
+     * between the telnet client and the telnet server, in
+     * of a String.<br>
+     *
+     * @return the negotiated terminal type as String.
+     */
+    public String getNegotiatedTerminalType() {
+        return negotiatedTerminalType;
+    }//getNegotiatedTerminalType
+
+    /**
+     * Sets the terminal type that has been negotiated
+     * between telnet client and telnet server, in form of
+     * a String.<br>
+     * <p/>
+     * <em>This method should not be called explicitly
+     * by the application (i.e. the its here for the io subsystem).</em><br>
+     *
+     * @param termtype the negotiated terminal type as String.
+     */
+    public void setNegotiatedTerminalType(String termtype) {
+        negotiatedTerminalType = termtype;
+    }//setNegotiatedTerminalType
+
+    /**
+     * Returns the hashmap for storing and
+     * retrieving environment variables to be passed
+     * between shells.
+     *
+     * @return a <tt>HashMap</tt> instance.
+     */
+    public Map<String, String> getEnvironment() {
+        return environment;
+    }//getEnvironment
+
+    /**
+     * Returns the login shell name.
+     *
+     * @return the shell name as string.
+     */
+    public String getLoginShell() {
+        return loginShell;
+    }//getLoginShell
+
+    /**
+     * Sets the login shell name.
+     *
+     * @param s the shell name as string.
+     */
+    public void setLoginShell(String s) {
+        loginShell = s;
+    }//setLoginShell
+
+    /**
+     * Tests if in line mode.
+     *
+     * @return true if in line mode, false otherwise
+     */
+    public boolean isLineMode() {
+        return lineMode;
+    }//isLineMode
+
+    /**
+     * Sets the line mode flag for the connection.
+     * Note that the setting will only be used at
+     * startup at the moment.
+     *
+     * @param b true if to be initialized in linemode,
+     *          false otherwise.
+     */
+    public void setLineMode(boolean b) {
+        lineMode = b;
+    }//setLineMode
+
+    /**
+     * Mutator for HostName cache
+     */
+    private void setHostName() {
+        hostName = address.getHostName();
+    }//setHostName
+
+    /**
+     * Mutator for HostAddress cache
+     */
+    private void setHostAddress() {
+        hostAddress = address.getHostAddress();
+    }//setHostAddress
+
+    /**
+     * Mutator for Locale
+     * Sets a Locale derived from the hostname,
+     * or the default which is Locale.ENGLISH if something
+     * goes wrong.
+     * The localhost represents a problem for example :)
+     */
+    private void setLocale() {
+        String country = getHostName();
+        try {
+            country = country.substring(country.lastIndexOf(".") + 1);
+            if (country.equals("at")) {
+                locale = new Locale("de", "AT");
+            } else if (country.equals("de")) {
+                locale = new Locale("de", "DE");
+            } else if (country.equals("mx")) {
+                locale = new Locale("es", "MX");
+            } else if (country.equals("es")) {
+                locale = new Locale("es", "ES");
+            } else if (country.equals("it")) {
+                locale = Locale.ITALY;
+            } else if (country.equals("fr")) {
+                locale = Locale.FRANCE;
+            } else if (country.equals("uk")) {
+                locale = new Locale("en", "GB");
+            } else if (country.equals("arpa")) {
+                locale = Locale.US;
+            } else if (country.equals("com")) {
+                locale = Locale.US;
+            } else if (country.equals("edu")) {
+                locale = Locale.US;
+            } else if (country.equals("gov")) {
+                locale = Locale.US;
+            } else if (country.equals("org")) {
+                locale = Locale.US;
+            } else if (country.equals("mil")) {
+                locale = Locale.US;
+            } else {
+                //default to english
+                locale = Locale.ENGLISH;
+            }
+        } catch (Exception ex) {
+            //default to english
+            locale = Locale.ENGLISH;
+        }
+    }//setLocale
+
+}//class ConnectionData

Added: 
felix/trunk/gogo/jline/src/main/java/org/apache/felix/gogo/jline/telnet/ConnectionEvent.java
URL: 
http://svn.apache.org/viewvc/felix/trunk/gogo/jline/src/main/java/org/apache/felix/gogo/jline/telnet/ConnectionEvent.java?rev=1735995&view=auto
==============================================================================
--- 
felix/trunk/gogo/jline/src/main/java/org/apache/felix/gogo/jline/telnet/ConnectionEvent.java
 (added)
+++ 
felix/trunk/gogo/jline/src/main/java/org/apache/felix/gogo/jline/telnet/ConnectionEvent.java
 Mon Mar 21 16:53:06 2016
@@ -0,0 +1,137 @@
+/*
+ * 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.
+ */
+
+/***
+ * Java TelnetD library (embeddable telnet daemon)
+ * Copyright (c) 2000-2005 Dieter Wimberger
+ * All rights reserved.
+ * <p/>
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * <p/>
+ * Neither the name of the author nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ * <p/>
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS ``AS
+ * IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ ***/
+
+package org.apache.felix.gogo.jline.telnet;
+
+/**
+ * Class implmenting a ConnectionEvent.<br>
+ * These events are used to communicate things that are
+ * supposed to be handled within the application context.
+ * These events are processed by the Connection instance
+ * calling upon its registered listeners.
+ *
+ * @author Dieter Wimberger
+ * @version 2.0 (16/07/2006)
+ * @see Connection
+ * @see ConnectionListener
+ */
+public class ConnectionEvent {
+
+    private final Connection source;
+    private final Type type;
+    /**
+     * Constructs a new instance of a ConnectionEvent
+     * with a given source (Connection) and a given type.
+     *
+     * @param source Connection that represents the source of this event.
+     * @param type int that contains one of the defined event types.
+     */
+    public ConnectionEvent(Connection source, Type type) {
+        this.type = type;
+        this.source = source;
+    }//constructor
+
+    /**
+     * Accessor method returning the source of the
+     * ConnectionEvent instance.
+     *
+     * @return Connection representing the source.
+     */
+    public Connection getSource() {
+        return source;
+    }//getSource
+
+    /**
+     * Method that helps identifying the type.
+     *
+     * @return Event type.
+     */
+    public Type getType() {
+        return type;
+    }//getType
+
+    public enum Type {
+        /**
+         * Defines the connection idle event type.<br>
+         * It occurs if a connection has been idle exceeding
+         * the configured time to warning.
+         */
+        CONNECTION_IDLE,
+
+        /**
+         * Defines the connection timed out event type.<br>
+         * It occurs if a connection has been idle exceeding
+         * the configured time to warning and the configured time
+         * to timedout.
+         */
+        CONNECTION_TIMEDOUT,
+
+        /**
+         * Defines the connection requested logout event type.<br>
+         * It occurs if a connection requested disgraceful logout by
+         * sending a <Ctrl>-<D> key combination.
+         */
+        CONNECTION_LOGOUTREQUEST,
+
+        /**
+         * Defines the connection sent break event type.<br>
+         * It occurs when the connection sent a NVT BREAK.
+         */
+        CONNECTION_BREAK,
+
+        /**
+         * Defines the connection geometry event type.
+         * It occurs when the connection sent a NAWS.
+         */
+        CONNECTION_TERMINAL_GEOMETRY_CHANGED;
+    }
+
+
+}//class ConnectionEvent
\ No newline at end of file

Added: 
felix/trunk/gogo/jline/src/main/java/org/apache/felix/gogo/jline/telnet/ConnectionFilter.java
URL: 
http://svn.apache.org/viewvc/felix/trunk/gogo/jline/src/main/java/org/apache/felix/gogo/jline/telnet/ConnectionFilter.java?rev=1735995&view=auto
==============================================================================
--- 
felix/trunk/gogo/jline/src/main/java/org/apache/felix/gogo/jline/telnet/ConnectionFilter.java
 (added)
+++ 
felix/trunk/gogo/jline/src/main/java/org/apache/felix/gogo/jline/telnet/ConnectionFilter.java
 Mon Mar 21 16:53:06 2016
@@ -0,0 +1,82 @@
+/*
+ * 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.
+ */
+
+/***
+ * Java TelnetD library (embeddable telnet daemon)
+ * Copyright (c) 2000-2005 Dieter Wimberger
+ * All rights reserved.
+ * <p/>
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * <p/>
+ * Neither the name of the author nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ * <p/>
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS ``AS
+ * IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ ***/
+
+package org.apache.felix.gogo.jline.telnet;
+
+import java.net.InetAddress;
+
+/**
+ * Interface defining a generic IP level connection
+ * filter.<br>
+ * Due to the fact that this task depends heavily on
+ * application context, I chose a very generic way
+ * of applying IP level connection filtering.
+ * <br><br>
+ * Implementations should consider following issues:
+ * <ul>
+ * <li>performance
+ * <li>administration (maybe via an admin shell)
+ * <li>logging denials
+ * </ul>
+ *
+ * @author Dieter Wimberger
+ * @version 2.0 (16/07/2006)
+ */
+public interface ConnectionFilter {
+
+    /**
+     * Tests if a given ip address is allowed to connect.
+     *
+     * @param ip the address to be tested.
+     * @return true if allowed to connect, false otherwise.
+     */
+    boolean isAllowed(InetAddress ip);
+
+}//interface ConnectionFilter
\ No newline at end of file

Added: 
felix/trunk/gogo/jline/src/main/java/org/apache/felix/gogo/jline/telnet/ConnectionListener.java
URL: 
http://svn.apache.org/viewvc/felix/trunk/gogo/jline/src/main/java/org/apache/felix/gogo/jline/telnet/ConnectionListener.java?rev=1735995&view=auto
==============================================================================
--- 
felix/trunk/gogo/jline/src/main/java/org/apache/felix/gogo/jline/telnet/ConnectionListener.java
 (added)
+++ 
felix/trunk/gogo/jline/src/main/java/org/apache/felix/gogo/jline/telnet/ConnectionListener.java
 Mon Mar 21 16:53:06 2016
@@ -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.
+ */
+
+/***
+ * Java TelnetD library (embeddable telnet daemon)
+ * Copyright (c) 2000-2005 Dieter Wimberger
+ * All rights reserved.
+ * <p/>
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * <p/>
+ * Neither the name of the author nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ * <p/>
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS ``AS
+ * IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ ***/
+
+package org.apache.felix.gogo.jline.telnet;
+
+
+/**
+ * Interface to be implemented if a class wants to
+ * qualify as a ConnectionListener.<br>
+ * Note that a Shell is per contract also forced to
+ * implement this interface.
+ *
+ * @author Dieter Wimberger
+ * @version 2.0 (16/07/2006)
+ * @see ConnectionEvent
+ */
+public interface ConnectionListener {
+
+    /**
+     * Called when a CONNECTION_IDLE event occured.
+     *
+     * @param ce ConnectionEvent instance.
+     * @see ConnectionEvent.Type#CONNECTION_IDLE
+     */
+    void connectionIdle(ConnectionEvent ce);
+
+    /**
+     * Called when a CONNECTION_TIMEDOUT event occured.
+     *
+     * @param ce ConnectionEvent instance.
+     * @see ConnectionEvent.Type#CONNECTION_TIMEDOUT
+     */
+    void connectionTimedOut(ConnectionEvent ce);
+
+    /**
+     * Called when a CONNECTION_LOGOUTREQUEST occured.
+     *
+     * @param ce ConnectionEvent instance.
+     * @see ConnectionEvent.Type#CONNECTION_LOGOUTREQUEST
+     */
+    void connectionLogoutRequest(ConnectionEvent ce);
+
+    /**
+     * Called when a CONNECTION_BREAK event occured.
+     *
+     * @param ce ConnectionEvent instance.
+     * @see ConnectionEvent.Type#CONNECTION_BREAK
+     */
+    void connectionSentBreak(ConnectionEvent ce);
+
+    /**
+     * Called when a CONNECTION_TERMINAL_GEOMETRY_CHANGED event occured.
+     *
+     * @param ce ConnectionEvent instance.
+     * @see ConnectionEvent.Type#CONNECTION_TERMINAL_GEOMETRY_CHANGED
+     */
+    void connectionTerminalGeometryChanged(ConnectionEvent ce);
+
+}//interface ConnectionListener
\ No newline at end of file

Added: 
felix/trunk/gogo/jline/src/main/java/org/apache/felix/gogo/jline/telnet/ConnectionManager.java
URL: 
http://svn.apache.org/viewvc/felix/trunk/gogo/jline/src/main/java/org/apache/felix/gogo/jline/telnet/ConnectionManager.java?rev=1735995&view=auto
==============================================================================
--- 
felix/trunk/gogo/jline/src/main/java/org/apache/felix/gogo/jline/telnet/ConnectionManager.java
 (added)
+++ 
felix/trunk/gogo/jline/src/main/java/org/apache/felix/gogo/jline/telnet/ConnectionManager.java
 Mon Mar 21 16:53:06 2016
@@ -0,0 +1,393 @@
+/*
+ * 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.
+ */
+
+/***
+ * Java TelnetD library (embeddable telnet daemon)
+ * Copyright (c) 2000-2005 Dieter Wimberger
+ * All rights reserved.
+ * <p/>
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * <p/>
+ * Neither the name of the author nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ * <p/>
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS ``AS
+ * IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ ***/
+
+package org.apache.felix.gogo.jline.telnet;
+
+import java.io.IOException;
+import java.net.InetAddress;
+import java.net.Socket;
+import java.text.MessageFormat;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Stack;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * Class that takes care for active and queued connection.
+ * Housekeeping is done also for connections that were just broken
+ * off, or exceeded their timeout. 
+ *
+ * @author Dieter Wimberger
+ * @version 2.0 (16/07/2006)
+ */
+public abstract class ConnectionManager implements Runnable {
+
+    private static Logger LOG = 
Logger.getLogger(ConnectionManager.class.getName());
+    private final List<Connection> openConnections;
+    private Thread thread;
+    private ThreadGroup threadGroup; //ThreadGroup all connections run in
+    private Stack<Connection> closedConnections;
+    private ConnectionFilter connectionFilter; //reference to the connection 
filter
+    private int maxConnections; //maximum allowed connections stored from the 
properties
+    private int warningTimeout; //time to idle warning
+    private int disconnectTimeout; //time to idle diconnection
+    private int housekeepingInterval; //interval for managing cleanups
+    private String loginShell;
+    private boolean lineMode = false;
+    private boolean stopping = false;
+
+    public ConnectionManager() {
+        threadGroup = new ThreadGroup(toString() + "Connections");
+        closedConnections = new Stack<Connection>();
+        openConnections = Collections.synchronizedList(new 
ArrayList<Connection>(100));
+    }
+
+    public ConnectionManager(int con, int timew, int timedis, int hoke, 
ConnectionFilter filter, String lsh, boolean lm) {
+        this();
+        connectionFilter = filter;
+        loginShell = lsh;
+        lineMode = lm;
+        maxConnections = con;
+        warningTimeout = timew;
+        disconnectTimeout = timedis;
+        housekeepingInterval = hoke;
+    }//constructor
+
+    /**
+     * Gets the active ConnectionFilter instance or
+     * returns null if no filter is set.
+     *
+     * @return the managers ConnectionFilter.
+     */
+    public ConnectionFilter getConnectionFilter() {
+        return connectionFilter;
+    }//getConnectionFilter
+
+    /**
+     * Set a connection filter for this
+     * ConnectionManager instance. The filter is used to handle
+     * IP level allow/deny of incoming connections.
+     *
+     * @param filter ConnectionFilter instance.
+     */
+    public void setConnectionFilter(ConnectionFilter filter) {
+        connectionFilter = filter;
+    }//setConnectionFilter
+
+    /**
+     * Returns the number of open connections.
+     * @return the number of open connections as <tt>int</tt>.
+     */
+    public int openConnectionCount() {
+        return openConnections.size();
+    }//openConnectionCount
+
+    /**
+     * Returns the {@link Connection} at the given index.
+     * @param idx
+     * @return
+     */
+    public Connection getConnection(int idx) {
+        synchronized (openConnections) {
+            return openConnections.get(idx);
+        }
+    }//getConnection
+
+    /**
+     * Get all {@link Connection} instances with the given
+     * <tt>InetAddress</tt>.
+     *
+     * @return all {@link Connection} instances with the given
+     *         <tt>InetAddress</tt>.
+     */
+    public Connection[] getConnectionsByAdddress(InetAddress addr) {
+        ArrayList<Connection> l = new ArrayList<Connection>();
+        synchronized (openConnections) {
+            for (Connection connection : openConnections) {
+                if 
(connection.getConnectionData().getInetAddress().equals(addr)) {
+                    l.add(connection);
+                }
+            }
+        }
+        Connection[] conns = new Connection[l.size()];
+        return l.toArray(conns);
+    }//getConnectionsByAddress
+
+    /**
+     * Starts this <tt>ConnectionManager</tt>.
+     */
+    public void start() {
+        thread = new Thread(this);
+        thread.start();
+    }//start
+
+    /**
+     * Stops this <tt>ConnectionManager</tt>.
+     */
+    public void stop() {
+        LOG.log(Level.FINE, "stop()::" + this.toString());
+        stopping = true;
+        //wait for thread to die
+        try {
+            if (thread != null) {
+                thread.join();
+            }
+        } catch (InterruptedException iex) {
+            LOG.log(Level.SEVERE, "stop()", iex);
+        }
+        synchronized (openConnections) {
+            for (Connection tc : openConnections) {
+                try {
+                    //maybe write a disgrace to the socket?
+                    tc.close();
+                } catch (Exception exc) {
+                    LOG.log(Level.SEVERE, "stop()", exc);
+                }
+            }
+            openConnections.clear();
+        }
+        LOG.log(Level.FINE, "stop():: Stopped " + this.toString());
+    }//stop
+
+    /**
+     * Method that that tries to connect an incoming request.
+     * Properly  queueing.
+     *
+     * @param insock Socket thats representing the incoming connection.
+     */
+    public void makeConnection(Socket insock) {
+        LOG.log(Level.FINE, "makeConnection()::" + insock.toString());
+        if (connectionFilter == null || 
connectionFilter.isAllowed(insock.getInetAddress())) {
+            //we create the connection data object at this point to
+            //store certain information there.
+            ConnectionData newCD = new ConnectionData(insock, this);
+            newCD.setLoginShell(loginShell);
+            newCD.setLineMode(lineMode);
+            if (openConnections.size() < maxConnections) {
+                //create a new Connection instance
+                Connection con = createConnection(threadGroup, newCD);
+                //log the newly created connection
+                Object[] args = {openConnections.size() + 1};
+                LOG.info(MessageFormat.format("connection #{0,number,integer} 
made.", args));
+                //register it for being managed
+                synchronized (openConnections) {
+                    openConnections.add(con);
+                }
+                //start it
+                con.start();
+            }
+        } else {
+            LOG.info("makeConnection():: Active Filter blocked incoming 
connection.");
+            try {
+                insock.close();
+            } catch (IOException ex) {
+                //do nothing or log.
+            }
+        }
+    }//makeConnection
+
+    protected abstract Connection createConnection(ThreadGroup threadGroup, 
ConnectionData newCD);
+
+    /**
+     * Periodically does following work:
+     * <ul>
+     * <li> cleaning up died connections.
+     * <li> checking managed connections if they are working properly.
+     * <li> checking the open connections.
+     * </ul>
+     */
+    public void run() {
+        //housekeep connections
+        try {
+            do {
+                //clean up and close all broken connections
+                //cleanupBroken();
+                //clean up closed connections
+                cleanupClosed();
+                //check all active connections
+                checkOpenConnections();
+                //sleep interval
+                Thread.sleep(housekeepingInterval);
+            } while (!stopping);
+
+        } catch (Exception e) {
+            LOG.log(Level.SEVERE, "run()", e);
+        }
+        LOG.log(Level.FINE, "run():: Ran out " + this.toString());
+    }//run
+
+    /*
+    private void cleanupBroken() {
+      //cleanup loop
+      while (!m_BrokenConnections.isEmpty()) {
+        Connection nextOne = (Connection) m_BrokenConnections.pop();
+        log.info("cleanupBroken():: Closing broken connection " + 
nextOne.toString());
+        //fire logoff event for shell site cleanup , beware could hog the 
daemon thread
+        nextOne.processConnectionEvent(new ConnectionEvent(nextOne, 
ConnectionEvent.CONNECTION_BROKEN));
+        //close the connection, will be automatically registered as closed
+        nextOne.close();
+      }
+    }//cleanupBroken
+    */
+    private void cleanupClosed() {
+        if (stopping) {
+            return;
+        }
+        //cleanup loop
+        while (!closedConnections.isEmpty()) {
+            Connection nextOne = closedConnections.pop();
+            LOG.info("cleanupClosed():: Removing closed connection " + 
nextOne.toString());
+            synchronized (openConnections) {
+                openConnections.remove(nextOne);
+            }
+        }
+    }//cleanupBroken
+
+    private void checkOpenConnections() {
+        if (stopping) {
+            return;
+        }
+        //do routine checks on active connections
+        synchronized (openConnections) {
+            for (Connection conn : openConnections) {
+                ConnectionData cd = conn.getConnectionData();
+                //check if it is dead and remove it.
+                if (!conn.isActive()) {
+                    registerClosedConnection(conn);
+                    continue;
+                }
+                /* Timeouts check */
+                //first we caculate the inactivity time
+                long inactivity = System.currentTimeMillis() - 
cd.getLastActivity();
+                //now we check for warning and disconnection
+                if (inactivity > warningTimeout) {
+                    //..and for disconnect
+                    if (inactivity > (disconnectTimeout + warningTimeout)) {
+                        //this connection needs to be disconnected :)
+                        LOG.log(Level.FINE, "checkOpenConnections():" + 
conn.toString() + " exceeded total timeout.");
+                        //fire logoff event for shell site cleanup , beware 
could hog the daemon thread
+                        conn.processConnectionEvent(new ConnectionEvent(conn, 
ConnectionEvent.Type.CONNECTION_TIMEDOUT));
+                        //conn.close();
+                    } else {
+                        //this connection needs to be warned :)
+                        if (!cd.isWarned()) {
+                            LOG.log(Level.FINE, "checkOpenConnections():" + 
conn.toString() + " exceeded warning timeout.");
+                            cd.setWarned(true);
+                            //warning event is fired but beware this could hog 
the daemon thread!!
+                            conn.processConnectionEvent(new 
ConnectionEvent(conn, ConnectionEvent.Type.CONNECTION_IDLE));
+                        }
+                    }
+                }
+            }
+            /* end Timeouts check */
+        }
+    }//checkConnections
+
+    public void registerClosedConnection(Connection con) {
+        if (stopping) {
+            return;
+        }
+        if (!closedConnections.contains(con)) {
+            LOG.log(Level.FINE, "registerClosedConnection()::" + 
con.toString());
+            closedConnections.push(con);
+        }
+    }//unregister
+
+    public int getDisconnectTimeout() {
+        return disconnectTimeout;
+    }
+
+    public void setDisconnectTimeout(int disconnectTimeout) {
+        this.disconnectTimeout = disconnectTimeout;
+    }
+
+    public int getHousekeepingInterval() {
+        return housekeepingInterval;
+    }
+
+    public void setHousekeepingInterval(int housekeepingInterval) {
+        this.housekeepingInterval = housekeepingInterval;
+    }
+
+    public boolean isLineMode() {
+        return lineMode;
+    }
+
+    public void setLineMode(boolean lineMode) {
+        this.lineMode = lineMode;
+    }
+
+    public String getLoginShell() {
+        return loginShell;
+    }
+
+    public void setLoginShell(String loginShell) {
+        this.loginShell = loginShell;
+    }
+
+    public int getMaxConnections() {
+        return maxConnections;
+    }
+
+    public void setMaxConnections(int maxConnections) {
+        this.maxConnections = maxConnections;
+    }
+
+    public int getWarningTimeout() {
+        return warningTimeout;
+    }
+
+    public void setWarningTimeout(int warningTimeout) {
+        this.warningTimeout = warningTimeout;
+    }
+
+}//class ConnectionManager

Added: 
felix/trunk/gogo/jline/src/main/java/org/apache/felix/gogo/jline/telnet/PortListener.java
URL: 
http://svn.apache.org/viewvc/felix/trunk/gogo/jline/src/main/java/org/apache/felix/gogo/jline/telnet/PortListener.java?rev=1735995&view=auto
==============================================================================
--- 
felix/trunk/gogo/jline/src/main/java/org/apache/felix/gogo/jline/telnet/PortListener.java
 (added)
+++ 
felix/trunk/gogo/jline/src/main/java/org/apache/felix/gogo/jline/telnet/PortListener.java
 Mon Mar 21 16:53:06 2016
@@ -0,0 +1,222 @@
+/*
+ * 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.
+ */
+
+/***
+ * Java TelnetD library (embeddable telnet daemon)
+ * Copyright (c) 2000-2005 Dieter Wimberger
+ * All rights reserved.
+ * <p/>
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * <p/>
+ * Neither the name of the author nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ * <p/>
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS ``AS
+ * IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ ***/
+
+package org.apache.felix.gogo.jline.telnet;
+
+import java.io.IOException;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.net.SocketException;
+import java.text.MessageFormat;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * Class that implements a <tt>PortListener</tt>.<br>
+ * If available, it accepts incoming connections and passes them
+ * to an associated <tt>ConnectionManager</tt>.
+ *
+ * @author Dieter Wimberger
+ * @version 2.0 (16/07/2006)
+ * @see ConnectionManager
+ */
+public class PortListener
+        implements Runnable {
+
+    private static final Logger LOG = 
Logger.getLogger(PortListener.class.getName());
+    private static final String logmsg =
+            "Listening to Port {0,number,integer} with a connectivity queue 
size of {1,number,integer}.";
+    private String name;
+    private int port;                                        //port number 
running on
+    private int floodProtection;                        //flooding protection
+    private ServerSocket serverSocket = null; //server socket
+    private Thread thread;
+    private ConnectionManager connectionManager;    //connection management 
thread
+    private boolean stopping = false;
+    private boolean available;                    //Flag for availability
+
+    /**
+     * Constructs a PortListener instance.<br>
+     *
+     * @param port      int that specifies the port number of the server 
socket.
+     * @param floodprot that specifies the server socket queue size.
+     */
+    public PortListener(String name, int port, int floodprot) {
+        this.name = name;
+        available = false;
+        this.port = port;
+        floodProtection = floodprot;
+    }//constructor
+
+    /**
+     * Returns the name of this <tt>PortListener</tt>.
+     *
+     * @return the name as <tt>String</tt>.
+     */
+    public String getName() {
+        return name;
+    }//getName
+
+    /**
+     * Tests if this <tt>PortListener</tt> is available.
+     *
+     * @return true if available, false otherwise.
+     */
+    public boolean isAvailable() {
+        return available;
+    }//isAvailable
+
+    /**
+     * Sets the availability flag of this <tt>PortListener</tt>.
+     *
+     * @param b true if to be available, false otherwise.
+     */
+    public void setAvailable(boolean b) {
+        available = b;
+    }//setAvailable
+
+    /**
+     * Starts this <tt>PortListener</tt>.
+     */
+    public void start() {
+        LOG.log(Level.FINE, "start()");
+        thread = new Thread(this);
+        thread.start();
+        available = true;
+    }//start
+
+    /**
+     * Stops this <tt>PortListener</tt>, and returns
+     * when everything was stopped successfully.
+     */
+    public void stop() {
+        LOG.log(Level.FINE, "stop()::" + this.toString());
+        //flag stop
+        stopping = true;
+        available = false;
+        //take down all connections
+        connectionManager.stop();
+
+        //close server socket
+        try {
+            serverSocket.close();
+        } catch (IOException ex) {
+            LOG.log(Level.SEVERE, "stop()", ex);
+        }
+
+        //wait for thread to die
+        try {
+            thread.join();
+        } catch (InterruptedException iex) {
+            LOG.log(Level.SEVERE, "stop()", iex);
+        }
+
+        LOG.info("stop()::Stopped " + this.toString());
+    }//stop
+
+    /**
+     * Listen constantly to a server socket and handles incoming connections
+     * through the associated {a:link ConnectionManager}.
+     *
+     * @see ConnectionManager
+     */
+    public void run() {
+        try {
+            /*
+                A server socket is opened with a connectivity queue of a size 
specified
+                in int floodProtection.  Concurrent login handling under 
normal circumstances
+                should be handled properly, but denial of service attacks via 
massive parallel
+                program logins should be prevented with this.
+            */
+            serverSocket = new ServerSocket(port, floodProtection);
+
+            //log entry
+            LOG.info(MessageFormat.format(logmsg, port, floodProtection));
+
+            do {
+                try {
+                    Socket s = serverSocket.accept();
+                    if (available) {
+                        connectionManager.makeConnection(s);
+                    } else {
+                        //just shut down the socket
+                        s.close();
+                    }
+                } catch (SocketException ex) {
+                    if (stopping) {
+                        //server socket was closed blocked in accept
+                        LOG.log(Level.FINE, "run(): ServerSocket closed by 
stop()");
+                    } else {
+                        LOG.log(Level.SEVERE, "run()", ex);
+                    }
+                }
+            } while (!stopping);
+
+        } catch (IOException e) {
+            LOG.log(Level.SEVERE, "run()", e);
+        }
+        LOG.log(Level.FINE, "run(): returning.");
+    }//run
+
+    /**
+     * Returns reference to ConnectionManager instance associated
+     * with the PortListener.
+     *
+     * @return the associated ConnectionManager.
+     */
+    public ConnectionManager getConnectionManager() {
+        return connectionManager;
+    }//getConnectionManager
+
+    public void setConnectionManager(ConnectionManager connectionManager) {
+        this.connectionManager = connectionManager;
+    }
+
+}//class PortListener


Reply via email to