You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mina.apache.org by ng...@apache.org on 2008/10/18 22:37:55 UTC

svn commit: r705921 - in /mina/ftpserver/trunk/core/src: main/java/org/apache/ftpserver/impl/DefaultFtpServer.java main/java/org/apache/ftpserver/listener/nio/NioListener.java test/java/org/apache/ftpserver/impl/DefaultFtpServerTest.java

Author: ngn
Date: Sat Oct 18 13:37:55 2008
New Revision: 705921

URL: http://svn.apache.org/viewvc?rev=705921&view=rev
Log:
Fix for bug where already started listeners would not be stopped if FtpServer.start() fails later (FTPSERVER-197)

Added:
    mina/ftpserver/trunk/core/src/test/java/org/apache/ftpserver/impl/DefaultFtpServerTest.java
Modified:
    mina/ftpserver/trunk/core/src/main/java/org/apache/ftpserver/impl/DefaultFtpServer.java
    mina/ftpserver/trunk/core/src/main/java/org/apache/ftpserver/listener/nio/NioListener.java

Modified: mina/ftpserver/trunk/core/src/main/java/org/apache/ftpserver/impl/DefaultFtpServer.java
URL: http://svn.apache.org/viewvc/mina/ftpserver/trunk/core/src/main/java/org/apache/ftpserver/impl/DefaultFtpServer.java?rev=705921&r1=705920&r2=705921&view=diff
==============================================================================
--- mina/ftpserver/trunk/core/src/main/java/org/apache/ftpserver/impl/DefaultFtpServer.java (original)
+++ mina/ftpserver/trunk/core/src/main/java/org/apache/ftpserver/impl/DefaultFtpServer.java Sat Oct 18 13:37:55 2008
@@ -19,6 +19,8 @@
 
 package org.apache.ftpserver.impl;
 
+import java.util.ArrayList;
+import java.util.List;
 import java.util.Map;
 
 import org.apache.ftpserver.ConnectionConfig;
@@ -26,6 +28,7 @@
 import org.apache.ftpserver.FtpServerFactory;
 import org.apache.ftpserver.command.CommandFactory;
 import org.apache.ftpserver.ftplet.FileSystemFactory;
+import org.apache.ftpserver.ftplet.FtpException;
 import org.apache.ftpserver.ftplet.Ftplet;
 import org.apache.ftpserver.ftplet.UserManager;
 import org.apache.ftpserver.listener.Listener;
@@ -60,28 +63,45 @@
 
     /**
      * Start the server. Open a new listener thread.
+     * @throws FtpException 
      */
-    public void start() throws Exception {
+    public void start() throws FtpException {
 
-        Map<String, Listener> listeners = serverContext.getListeners();
-        for (Listener listener : listeners.values()) {
-            listener.start(serverContext);
-        }
-
-        // init the Ftplet container
-        serverContext.getFtpletContainer().init(serverContext);
+        List<Listener> startedListeners = new ArrayList<Listener>();
         
-        started = true;
-
-        LOG.info("FTP server started");
+        try {
+            Map<String, Listener> listeners = serverContext.getListeners();
+            for (Listener listener : listeners.values()) {
+                listener.start(serverContext);
+                startedListeners.add(listener);
+            }
+    
+            // init the Ftplet container
+            serverContext.getFtpletContainer().init(serverContext);
+        
+            started = true;
 
+            LOG.info("FTP server started");
+        } catch(Exception e) {
+            // must close listeners that we were able to start
+            for(Listener listener : startedListeners) {
+                listener.stop();
+            }
+            
+            if(e instanceof FtpException) {
+                throw (FtpException)e;
+            } else {
+                throw (RuntimeException)e;
+            }
+            
+        }
     }
 
     /**
      * Stop the server. Stop the listener thread.
      */
     public void stop() {
-        if (!started || serverContext == null) {
+        if (serverContext == null) {
             // we have already been stopped, ignore
             return;
         }

Modified: mina/ftpserver/trunk/core/src/main/java/org/apache/ftpserver/listener/nio/NioListener.java
URL: http://svn.apache.org/viewvc/mina/ftpserver/trunk/core/src/main/java/org/apache/ftpserver/listener/nio/NioListener.java?rev=705921&r1=705920&r2=705921&view=diff
==============================================================================
--- mina/ftpserver/trunk/core/src/main/java/org/apache/ftpserver/listener/nio/NioListener.java (original)
+++ mina/ftpserver/trunk/core/src/main/java/org/apache/ftpserver/listener/nio/NioListener.java Sat Oct 18 13:37:55 2008
@@ -22,6 +22,7 @@
 import java.io.IOException;
 import java.net.InetAddress;
 import java.net.InetSocketAddress;
+import java.security.GeneralSecurityException;
 import java.util.ArrayList;
 import java.util.HashSet;
 import java.util.List;
@@ -31,6 +32,7 @@
 import java.util.concurrent.TimeUnit;
 
 import org.apache.ftpserver.DataConnectionConfiguration;
+import org.apache.ftpserver.FtpServerConfigurationException;
 import org.apache.ftpserver.impl.DefaultFtpHandler;
 import org.apache.ftpserver.impl.FtpHandler;
 import org.apache.ftpserver.impl.FtpIoSession;
@@ -112,65 +114,82 @@
     /**
      * @see Listener#start(FtpServerContext)
      */
-    public synchronized void start(FtpServerContext context) throws Exception {
-        this.context = context;
-
-        acceptor = new NioSocketAcceptor(Runtime.getRuntime()
-                .availableProcessors());
-
-        if (getServerAddress() != null) {
-            address = new InetSocketAddress(getServerAddress(), getPort());
-        } else {
-            address = new InetSocketAddress(getPort());
-        }
-
-        acceptor.setReuseAddress(true);
-        acceptor.getSessionConfig().setReadBufferSize(2048);
-        acceptor.getSessionConfig().setIdleTime(IdleStatus.BOTH_IDLE,
-                getIdleTimeout());
-        // Decrease the default receiver buffer size
-        ((SocketSessionConfig) acceptor.getSessionConfig())
-                .setReceiveBufferSize(512);
-
-        MdcInjectionFilter mdcFilter = new MdcInjectionFilter();
-
-        acceptor.getFilterChain().addLast("mdcFilter", mdcFilter);
-
-        // add and update the blacklist filter
-        acceptor.getFilterChain().addLast("ipFilter", new BlacklistFilter());
-        updateBlacklistFilter();
-
-        acceptor.getFilterChain().addLast("threadPool",
-                new ExecutorFilter(filterExecutor));
-        acceptor.getFilterChain().addLast("codec",
-                new ProtocolCodecFilter(new FtpServerProtocolCodecFactory()));
-        acceptor.getFilterChain().addLast("mdcFilter2", mdcFilter);
-        acceptor.getFilterChain().addLast("logger", new FtpLoggingFilter());
-
-        if (isImplicitSsl()) {
-            SslConfiguration ssl = getSslConfiguration();
-            SslFilter sslFilter = new SslFilter(ssl.getSSLContext());
-
-            if (ssl.getClientAuth() == ClientAuth.NEED) {
-                sslFilter.setNeedClientAuth(true);
-            } else if (ssl.getClientAuth() == ClientAuth.WANT) {
-                sslFilter.setWantClientAuth(true);
+    public synchronized void start(FtpServerContext context) {
+        try {
+            
+            this.context = context;
+    
+            acceptor = new NioSocketAcceptor(Runtime.getRuntime()
+                    .availableProcessors());
+    
+            if (getServerAddress() != null) {
+                address = new InetSocketAddress(getServerAddress(), getPort());
+            } else {
+                address = new InetSocketAddress(getPort());
             }
-
-            if (ssl.getEnabledCipherSuites() != null) {
-                sslFilter.setEnabledCipherSuites(ssl.getEnabledCipherSuites());
+    
+            acceptor.setReuseAddress(true);
+            acceptor.getSessionConfig().setReadBufferSize(2048);
+            acceptor.getSessionConfig().setIdleTime(IdleStatus.BOTH_IDLE,
+                    getIdleTimeout());
+            // Decrease the default receiver buffer size
+            ((SocketSessionConfig) acceptor.getSessionConfig())
+                    .setReceiveBufferSize(512);
+    
+            MdcInjectionFilter mdcFilter = new MdcInjectionFilter();
+    
+            acceptor.getFilterChain().addLast("mdcFilter", mdcFilter);
+    
+            // add and update the blacklist filter
+            acceptor.getFilterChain().addLast("ipFilter", new BlacklistFilter());
+            updateBlacklistFilter();
+    
+            acceptor.getFilterChain().addLast("threadPool",
+                    new ExecutorFilter(filterExecutor));
+            acceptor.getFilterChain().addLast("codec",
+                    new ProtocolCodecFilter(new FtpServerProtocolCodecFactory()));
+            acceptor.getFilterChain().addLast("mdcFilter2", mdcFilter);
+            acceptor.getFilterChain().addLast("logger", new FtpLoggingFilter());
+    
+            if (isImplicitSsl()) {
+                SslConfiguration ssl = getSslConfiguration();
+                SslFilter sslFilter;
+                try {
+                    sslFilter = new SslFilter(ssl.getSSLContext());
+                } catch (GeneralSecurityException e) {
+                    throw new FtpServerConfigurationException("SSL could not be initialized, check configuration");
+                }
+    
+                if (ssl.getClientAuth() == ClientAuth.NEED) {
+                    sslFilter.setNeedClientAuth(true);
+                } else if (ssl.getClientAuth() == ClientAuth.WANT) {
+                    sslFilter.setWantClientAuth(true);
+                }
+    
+                if (ssl.getEnabledCipherSuites() != null) {
+                    sslFilter.setEnabledCipherSuites(ssl.getEnabledCipherSuites());
+                }
+    
+                acceptor.getFilterChain().addFirst("sslFilter", sslFilter);
             }
-
-            acceptor.getFilterChain().addFirst("sslFilter", sslFilter);
+    
+            handler.init(context, this);
+            acceptor.setHandler(new FtpHandlerAdapter(context, handler));
+    
+            try {
+                acceptor.bind(address);
+            } catch (IOException e) {
+                throw new FtpServerConfigurationException("Failed to bind to address " + address + ", check configuration", e);
+            }
+    
+            // update the port to the real port bound by the listener
+            setPort(acceptor.getLocalAddress().getPort());
+        } catch(RuntimeException e) {
+            // clean up if we fail to start
+            stop();
+            
+            throw e;
         }
-
-        handler.init(context, this);
-        acceptor.setHandler(new FtpHandlerAdapter(context, handler));
-
-        acceptor.bind(address);
-
-        // update the port to the real port bound by the listener
-        setPort(acceptor.getLocalAddress().getPort());
     }
 
     /**
@@ -193,6 +212,8 @@
                 // TODO: how to handle?
             }
         }
+        
+        context = null;
     }
 
     /**

Added: mina/ftpserver/trunk/core/src/test/java/org/apache/ftpserver/impl/DefaultFtpServerTest.java
URL: http://svn.apache.org/viewvc/mina/ftpserver/trunk/core/src/test/java/org/apache/ftpserver/impl/DefaultFtpServerTest.java?rev=705921&view=auto
==============================================================================
--- mina/ftpserver/trunk/core/src/test/java/org/apache/ftpserver/impl/DefaultFtpServerTest.java (added)
+++ mina/ftpserver/trunk/core/src/test/java/org/apache/ftpserver/impl/DefaultFtpServerTest.java Sat Oct 18 13:37:55 2008
@@ -0,0 +1,79 @@
+/*
+ * 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.ftpserver.impl;
+
+import java.io.IOException;
+import java.net.BindException;
+
+import org.apache.ftpserver.FtpServer;
+import org.apache.ftpserver.FtpServerConfigurationException;
+import org.apache.ftpserver.FtpServerFactory;
+import org.apache.ftpserver.listener.Listener;
+import org.apache.ftpserver.listener.ListenerFactory;
+import org.apache.ftpserver.test.TestUtil;
+
+import junit.framework.TestCase;
+
+/**
+ *
+ * @author The Apache MINA Project (dev@mina.apache.org)
+ * @version $Rev$, $Date$
+ *
+ */
+public class DefaultFtpServerTest extends TestCase {
+
+    public void testFailStartingSecondListener() throws Exception {
+        // FTPSERVER-197
+        
+        FtpServerFactory serverFactory = new FtpServerFactory();
+        
+        ListenerFactory listenerFactory = new ListenerFactory();
+        listenerFactory.setPort(TestUtil.findFreePort());
+        
+        // let's create two listeners on the same port, second should not start
+     
+        Listener defaultListener = listenerFactory.createListener();
+        Listener secondListener = listenerFactory.createListener();
+        
+        
+        serverFactory.addListener("default", defaultListener);
+        serverFactory.addListener("second", secondListener);
+        
+        FtpServer server = serverFactory.createServer();
+        
+        try {
+            server.start();
+            fail("Must throw FtpServerConfigurationException");
+        } catch(FtpServerConfigurationException e) {
+            if(e.getCause() instanceof BindException) {
+                // OK!
+            } else {
+                throw e;
+            }
+        }
+        
+        assertTrue(defaultListener.isStopped());
+        assertTrue(secondListener.isStopped());
+        assertTrue(server.isStopped());
+        
+        
+    }
+    
+}