You are viewing a plain text version of this content. The canonical link for it is here.
Posted to ftpserver-commits@incubator.apache.org by ng...@apache.org on 2006/11/21 22:41:06 UTC

svn commit: r477942 - in /incubator/ftpserver/trunk/core/src: java/org/apache/ftpserver/DefaultListener.java java/org/apache/ftpserver/FtpServer.java java/org/apache/ftpserver/Listener.java test/org/apache/ftpserver/FtpServerStartupTest.java

Author: ngn
Date: Tue Nov 21 14:41:05 2006
New Revision: 477942

URL: http://svn.apache.org/viewvc?view=rev&rev=477942
Log:
Refactored FtpServer listening thread into specialized listeners. FtpServer can host multiple listener making it possible to have, for example, one port listing on clear text FTP and one on SSL/TLS.

This can also serve as the basics for stuff like virtual hosts and similar.

Right now this change is not exposed in the configuration, but it will be.

Added:
    incubator/ftpserver/trunk/core/src/java/org/apache/ftpserver/DefaultListener.java   (with props)
    incubator/ftpserver/trunk/core/src/java/org/apache/ftpserver/Listener.java   (with props)
Modified:
    incubator/ftpserver/trunk/core/src/java/org/apache/ftpserver/FtpServer.java
    incubator/ftpserver/trunk/core/src/test/org/apache/ftpserver/FtpServerStartupTest.java

Added: incubator/ftpserver/trunk/core/src/java/org/apache/ftpserver/DefaultListener.java
URL: http://svn.apache.org/viewvc/incubator/ftpserver/trunk/core/src/java/org/apache/ftpserver/DefaultListener.java?view=auto&rev=477942
==============================================================================
--- incubator/ftpserver/trunk/core/src/java/org/apache/ftpserver/DefaultListener.java (added)
+++ incubator/ftpserver/trunk/core/src/java/org/apache/ftpserver/DefaultListener.java Tue Nov 21 14:41:05 2006
@@ -0,0 +1,121 @@
+package org.apache.ftpserver;
+
+import java.io.IOException;
+import java.net.ServerSocket;
+import java.net.Socket;
+
+import org.apache.commons.logging.Log;
+import org.apache.ftpserver.interfaces.Connection;
+import org.apache.ftpserver.interfaces.ConnectionManager;
+import org.apache.ftpserver.interfaces.ServerFtpConfig;
+
+public class DefaultListener implements Listener, Runnable {
+
+    private Log log;
+    
+    private ServerFtpConfig ftpConfig;
+
+    private ServerSocket serverSocket;
+
+    private Thread listenerThread;
+
+    private boolean suspended = false;
+
+    public DefaultListener(ServerFtpConfig ftpConfig) {
+        this.ftpConfig = ftpConfig;
+        
+        log = ftpConfig.getLogFactory().getInstance(getClass());
+    }
+
+    public void start() throws Exception {
+        serverSocket = ftpConfig.getSocketFactory().createServerSocket();
+
+        listenerThread = new Thread(this);
+        listenerThread.start();
+
+    }
+
+    public void run() {
+        if(serverSocket == null) {
+            throw new IllegalStateException("start() must be called before run()");
+        }
+        
+        log.info("Listener started on port " + serverSocket.getLocalPort());
+
+        // ftpConfig might be null if stop has been called
+        if (ftpConfig == null) {
+            return;
+        }
+
+        ConnectionManager conManager = ftpConfig.getConnectionManager();
+        
+        while (true) {
+            try {
+
+                // closed - return
+                if (serverSocket == null) {
+                    return;
+                }
+
+                // accept new connection .. if suspended
+                // close immediately.
+                Socket soc = serverSocket.accept();
+
+                if (suspended) {
+                    try {
+                        soc.close();
+                    } catch (Exception ex) {
+                        // ignore
+                    }
+                    continue;
+                }
+
+                Connection connection = new RequestHandler(ftpConfig, soc);
+                conManager.newConnection(connection);
+            } catch (Exception ex) {
+                return;
+            }
+        }
+    }
+
+    public synchronized void stop() {
+        // close server socket
+        if (serverSocket != null) {
+
+            try {
+                serverSocket.close();
+            } catch (IOException ex) {
+            }
+            serverSocket = null;
+        }
+
+        listenerThread.interrupt();
+
+        // wait for the runner thread to terminate
+        if (listenerThread != null && listenerThread.isAlive()) {
+
+            try {
+                listenerThread.join();
+            } catch (InterruptedException ex) {
+            }
+            listenerThread = null;
+        }
+    }
+
+    public boolean isStopped() {
+        return listenerThread == null;
+
+    }
+
+    public boolean isSuspended() {
+        return suspended;
+    }
+
+    public void resume() {
+        suspended = false;
+    }
+
+    public void suspend() {
+        suspended = true;
+    }
+}
\ No newline at end of file

Propchange: incubator/ftpserver/trunk/core/src/java/org/apache/ftpserver/DefaultListener.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: incubator/ftpserver/trunk/core/src/java/org/apache/ftpserver/FtpServer.java
URL: http://svn.apache.org/viewvc/incubator/ftpserver/trunk/core/src/java/org/apache/ftpserver/FtpServer.java?view=diff&rev=477942&r1=477941&r2=477942
==============================================================================
--- incubator/ftpserver/trunk/core/src/java/org/apache/ftpserver/FtpServer.java (original)
+++ incubator/ftpserver/trunk/core/src/java/org/apache/ftpserver/FtpServer.java Tue Nov 21 14:41:05 2006
@@ -15,36 +15,36 @@
  * KIND, either express or implied.  See the License for the
  * specific language governing permissions and limitations
  * under the License.
- */  
+ */
 
 package org.apache.ftpserver;
 
-import java.io.IOException;
-import java.net.ServerSocket;
-import java.net.Socket;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
 
 import org.apache.commons.logging.Log;
-import org.apache.ftpserver.interfaces.Connection;
-import org.apache.ftpserver.interfaces.ConnectionManager;
 import org.apache.ftpserver.interfaces.ServerFtpConfig;
 
-
 /**
  * This is the starting point of all the servers. It invokes a new listener
- * thread. <code>Server</code> implementation is used to create the server 
+ * thread. <code>Server</code> implementation is used to create the server
  * socket and handle client connection.
  * 
  * @author <a href="mailto:rana_b@yahoo.com">Rana Bhattacharyya</a>
  */
-public 
-class FtpServer implements Runnable {
+public class FtpServer {
 
     private Thread runner;
-    private ServerSocket serverSocket;
+
     private ServerFtpConfig ftpConfig;
+
     private Log log;
+
     private boolean suspended;
-    
+
+    private List listeners = new ArrayList();
 
     /**
      * Constructor. Set the server object.
@@ -52,54 +52,38 @@
     public FtpServer(ServerFtpConfig ftpConfig) {
         this.ftpConfig = ftpConfig;
         log = this.ftpConfig.getLogFactory().getInstance(getClass());
+
+        // for now just create one 
+        listeners.add(new DefaultListener(ftpConfig));
     }
 
     /**
      * Start the server. Open a new listener thread.
      */
     public void start() throws Exception {
-        if (runner == null) {
-            serverSocket = ftpConfig.getSocketFactory().createServerSocket();            
-            runner = new Thread(this);
-            runner.start();
-            System.out.println("Server ready :: Apache FTP Server");
-            log.info("------- Apache FTP Server started ------");
+        for (Iterator iter = listeners.iterator(); iter.hasNext();) {
+            Listener listener = (Listener) iter.next();
+            
+            listener.start();
         }
-    }
+        
+        System.out.println("Server ready :: Apache FTP Server");
+        log.info("------- Apache FTP Server started ------");
 
+    }
+    
     /**
      * Stop the server. Stop the listener thread.
      */
     public void stop() {
-        
-        // first interrupt the server engine thread
-        if (runner != null) {
-            runner.interrupt();
-        }
 
-        // close server socket
-        if (serverSocket != null) {
-            try {
-                serverSocket.close();
-            }
-            catch(IOException ex){
-            }
-            serverSocket = null;
-        }  
-
-        
-        // wait for the runner thread to terminate
-        if( (runner != null) && runner.isAlive() ) {
-            try {
-                runner.join();
-            }
-            catch(InterruptedException ex) {
-            }
-            runner = null;
+        // stop all listeners
+        for (Iterator iter = listeners.iterator(); iter.hasNext();) {
+            Listener listener = (Listener) iter.next();
+            
+            listener.stop();
         }
 
-        
-        
         // release server resources
         if (ftpConfig != null) {
             ftpConfig.dispose();
@@ -137,46 +121,7 @@
     }
 
     /**
-     * Listen for client requests.
-     */
-    public void run() {
-        // ftpConfig might be null if stop has been called
-        if(ftpConfig == null) {
-            return;
-        }
-        
-        ConnectionManager conManager = ftpConfig.getConnectionManager();
-        while (runner != null) {
-            try {
-                
-                // closed - return
-                if(serverSocket == null) {
-                    return;
-                }
-                
-                // accept new connection .. if suspended 
-                // close immediately.
-                Socket soc = serverSocket.accept();
-                if(suspended) {
-                    try {
-                        soc.close();
-                    }
-                    catch(Exception ex) {
-                    }
-                    continue;
-                }
-                
-                Connection connection = new RequestHandler(ftpConfig, soc);
-                conManager.newConnection(connection);
-            }
-            catch (Exception ex) {
-                return;
-            }
-        }
-    }
-    
-    /**
-     * Get the root server configuration object. 
+     * Get the root server configuration object.
      */
     public ServerFtpConfig getFtpConfig() {
         return ftpConfig;

Added: incubator/ftpserver/trunk/core/src/java/org/apache/ftpserver/Listener.java
URL: http://svn.apache.org/viewvc/incubator/ftpserver/trunk/core/src/java/org/apache/ftpserver/Listener.java?view=auto&rev=477942
==============================================================================
--- incubator/ftpserver/trunk/core/src/java/org/apache/ftpserver/Listener.java (added)
+++ incubator/ftpserver/trunk/core/src/java/org/apache/ftpserver/Listener.java Tue Nov 21 14:41:05 2006
@@ -0,0 +1,15 @@
+package org.apache.ftpserver;
+
+public interface Listener {
+    void start() throws Exception;
+
+    void stop();
+
+    boolean isStopped();
+
+    void suspend();
+
+    void resume();
+
+    boolean isSuspended();
+}
\ No newline at end of file

Propchange: incubator/ftpserver/trunk/core/src/java/org/apache/ftpserver/Listener.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: incubator/ftpserver/trunk/core/src/test/org/apache/ftpserver/FtpServerStartupTest.java
URL: http://svn.apache.org/viewvc/incubator/ftpserver/trunk/core/src/test/org/apache/ftpserver/FtpServerStartupTest.java?view=diff&rev=477942&r1=477941&r2=477942
==============================================================================
--- incubator/ftpserver/trunk/core/src/test/org/apache/ftpserver/FtpServerStartupTest.java (original)
+++ incubator/ftpserver/trunk/core/src/test/org/apache/ftpserver/FtpServerStartupTest.java Tue Nov 21 14:41:05 2006
@@ -28,8 +28,11 @@
 
     /**
      * Test startup and shutdown of FTPServer
+     * @throws InterruptedException 
      */
-    public void testStartup() {
+    public void testStartup() throws InterruptedException {
+        // allow server to start
+        Thread.sleep(200);
         // NOOP
     }