一、前言
关于mina-core包(2.0.4)包中通过定义org.apache.ftpserver.FtpServerFactory工厂类依赖DefaultFtpServerContext实现org.apache.ftpserver.FtpServer定义文件传输协议服务接口,主要包括FtpServer、DefaultFtpServer、FtpServerFactory、FtpServerContext及DefaultFtpServerContext等,具体代码如下所示
二、源码说明
1.org.apache.ftpserver.FtpServer
package org.apache.ftpserver;@b@@b@import org.apache.ftpserver.ftplet.FtpException;@b@@b@public abstract interface FtpServer@b@{@b@ public abstract void start()@b@ throws FtpException;@b@@b@ public abstract void stop();@b@@b@ public abstract boolean isStopped();@b@@b@ public abstract void suspend();@b@@b@ public abstract void resume();@b@@b@ public abstract boolean isSuspended();@b@}
2.默认org.apache.ftpserver.impl.DefaultFtpServer实现类
package org.apache.ftpserver.impl;@b@@b@import java.util.ArrayList;@b@import java.util.Collection;@b@import java.util.Iterator;@b@import java.util.List;@b@import java.util.Map;@b@import org.apache.ftpserver.ConnectionConfig;@b@import org.apache.ftpserver.FtpServer;@b@import org.apache.ftpserver.command.CommandFactory;@b@import org.apache.ftpserver.ftplet.FileSystemFactory;@b@import org.apache.ftpserver.ftplet.FtpException;@b@import org.apache.ftpserver.ftplet.Ftplet;@b@import org.apache.ftpserver.ftplet.UserManager;@b@import org.apache.ftpserver.ftpletcontainer.FtpletContainer;@b@import org.apache.ftpserver.listener.Listener;@b@import org.apache.ftpserver.message.MessageResource;@b@import org.slf4j.Logger;@b@import org.slf4j.LoggerFactory;@b@@b@public class DefaultFtpServer@b@ implements FtpServer@b@{@b@ private final Logger LOG = LoggerFactory.getLogger(DefaultFtpServer.class);@b@ private FtpServerContext serverContext;@b@ private boolean suspended = false;@b@ private boolean started = false;@b@@b@ public DefaultFtpServer(FtpServerContext serverContext)@b@ {@b@ this.serverContext = serverContext;@b@ }@b@@b@ public void start()@b@ throws FtpException@b@ {@b@ Iterator i$;@b@ Listener listener;@b@ if (this.serverContext == null)@b@ {@b@ throw new IllegalStateException("FtpServer has been stopped. Restart is not supported");@b@ }@b@@b@ List startedListeners = new ArrayList();@b@ try@b@ {@b@ Map listeners = this.serverContext.getListeners();@b@ for (i$ = listeners.values().iterator(); i$.hasNext(); ) { listener = (Listener)i$.next();@b@ listener.start(this.serverContext);@b@ startedListeners.add(listener);@b@ }@b@@b@ this.serverContext.getFtpletContainer().init(this.serverContext);@b@@b@ this.started = true;@b@@b@ this.LOG.info("FTP server started");@b@ }@b@ catch (Exception e) {@b@ for (i$ = startedListeners.iterator(); i$.hasNext(); ) { listener = (Listener)i$.next();@b@ listener.stop();@b@ }@b@@b@ if (e instanceof FtpException)@b@ throw ((FtpException)e);@b@@b@ throw ((RuntimeException)e);@b@ }@b@ }@b@@b@ public void stop()@b@ {@b@ if (this.serverContext == null)@b@ {@b@ return;@b@ }@b@@b@ Map listeners = this.serverContext.getListeners();@b@ for (Listener listener : listeners.values()) {@b@ listener.stop();@b@ }@b@@b@ this.serverContext.getFtpletContainer().destroy();@b@@b@ if (this.serverContext != null) {@b@ this.serverContext.dispose();@b@ this.serverContext = null;@b@ }@b@@b@ this.started = false;@b@ }@b@@b@ public boolean isStopped()@b@ {@b@ return (!(this.started));@b@ }@b@@b@ public void suspend()@b@ {@b@ if (!(this.started)) {@b@ return;@b@ }@b@@b@ this.LOG.debug("Suspending server");@b@@b@ Map listeners = this.serverContext.getListeners();@b@ for (Listener listener : listeners.values()) {@b@ listener.suspend();@b@ }@b@@b@ this.suspended = true;@b@ this.LOG.debug("Server suspended");@b@ }@b@@b@ public void resume()@b@ {@b@ if (!(this.suspended)) {@b@ return;@b@ }@b@@b@ this.LOG.debug("Resuming server");@b@ Map listeners = this.serverContext.getListeners();@b@ for (Listener listener : listeners.values()) {@b@ listener.resume();@b@ }@b@@b@ this.suspended = false;@b@ this.LOG.debug("Server resumed");@b@ }@b@@b@ public boolean isSuspended()@b@ {@b@ return this.suspended;@b@ }@b@@b@ public FtpServerContext getServerContext()@b@ {@b@ return this.serverContext;@b@ }@b@@b@ public Map<String, Listener> getListeners()@b@ {@b@ return getServerContext().getListeners();@b@ }@b@@b@ public Listener getListener(String name)@b@ {@b@ return getServerContext().getListener(name);@b@ }@b@@b@ public Map<String, Ftplet> getFtplets()@b@ {@b@ return getServerContext().getFtpletContainer().getFtplets();@b@ }@b@@b@ public UserManager getUserManager()@b@ {@b@ return getServerContext().getUserManager();@b@ }@b@@b@ public FileSystemFactory getFileSystem()@b@ {@b@ return getServerContext().getFileSystemManager();@b@ }@b@@b@ public CommandFactory getCommandFactory()@b@ {@b@ return getServerContext().getCommandFactory();@b@ }@b@@b@ public MessageResource getMessageResource()@b@ {@b@ return getServerContext().getMessageResource();@b@ }@b@@b@ public ConnectionConfig getConnectionConfig()@b@ {@b@ return getServerContext().getConnectionConfig();@b@ }@b@}
3.org.apache.ftpserver.FtpServerFactory实现工厂类
package org.apache.ftpserver;@b@@b@import java.util.Map;@b@import org.apache.ftpserver.command.CommandFactory;@b@import org.apache.ftpserver.ftplet.FileSystemFactory;@b@import org.apache.ftpserver.ftplet.Ftplet;@b@import org.apache.ftpserver.ftplet.UserManager;@b@import org.apache.ftpserver.ftpletcontainer.FtpletContainer;@b@import org.apache.ftpserver.ftpletcontainer.impl.DefaultFtpletContainer;@b@import org.apache.ftpserver.impl.DefaultFtpServer;@b@import org.apache.ftpserver.impl.DefaultFtpServerContext;@b@import org.apache.ftpserver.listener.Listener;@b@import org.apache.ftpserver.message.MessageResource;@b@@b@public class FtpServerFactory@b@{@b@ private DefaultFtpServerContext serverContext;@b@@b@ public FtpServerFactory()@b@ {@b@ this.serverContext = new DefaultFtpServerContext();@b@ }@b@@b@ public FtpServer createServer()@b@ {@b@ return new DefaultFtpServer(this.serverContext);@b@ }@b@@b@ public Map<String, Listener> getListeners()@b@ {@b@ return this.serverContext.getListeners();@b@ }@b@@b@ public Listener getListener(String name)@b@ {@b@ return this.serverContext.getListener(name);@b@ }@b@@b@ public void addListener(String name, Listener listener)@b@ {@b@ this.serverContext.addListener(name, listener);@b@ }@b@@b@ public void setListeners(Map<String, Listener> listeners)@b@ {@b@ this.serverContext.setListeners(listeners);@b@ }@b@@b@ public Map<String, Ftplet> getFtplets()@b@ {@b@ return this.serverContext.getFtpletContainer().getFtplets();@b@ }@b@@b@ public void setFtplets(Map<String, Ftplet> ftplets)@b@ {@b@ this.serverContext.setFtpletContainer(new DefaultFtpletContainer(ftplets));@b@ }@b@@b@ public UserManager getUserManager()@b@ {@b@ return this.serverContext.getUserManager();@b@ }@b@@b@ public void setUserManager(UserManager userManager)@b@ {@b@ this.serverContext.setUserManager(userManager);@b@ }@b@@b@ public FileSystemFactory getFileSystem()@b@ {@b@ return this.serverContext.getFileSystemManager();@b@ }@b@@b@ public void setFileSystem(FileSystemFactory fileSystem)@b@ {@b@ this.serverContext.setFileSystemManager(fileSystem);@b@ }@b@@b@ public CommandFactory getCommandFactory()@b@ {@b@ return this.serverContext.getCommandFactory();@b@ }@b@@b@ public void setCommandFactory(CommandFactory commandFactory)@b@ {@b@ this.serverContext.setCommandFactory(commandFactory);@b@ }@b@@b@ public MessageResource getMessageResource()@b@ {@b@ return this.serverContext.getMessageResource();@b@ }@b@@b@ public void setMessageResource(MessageResource messageResource)@b@ {@b@ this.serverContext.setMessageResource(messageResource);@b@ }@b@@b@ public ConnectionConfig getConnectionConfig()@b@ {@b@ return this.serverContext.getConnectionConfig();@b@ }@b@@b@ public void setConnectionConfig(ConnectionConfig connectionConfig)@b@ {@b@ this.serverContext.setConnectionConfig(connectionConfig);@b@ }@b@}
4.org.apache.ftpserver.impl.FtpServerContext及实现类DefaultFtpServerContext
package org.apache.ftpserver.impl;@b@@b@import java.util.Map;@b@import java.util.concurrent.ThreadPoolExecutor;@b@import org.apache.ftpserver.ConnectionConfig;@b@import org.apache.ftpserver.command.CommandFactory;@b@import org.apache.ftpserver.ftplet.FtpletContext;@b@import org.apache.ftpserver.ftpletcontainer.FtpletContainer;@b@import org.apache.ftpserver.listener.Listener;@b@import org.apache.ftpserver.message.MessageResource;@b@@b@public abstract interface FtpServerContext extends FtpletContext@b@{@b@ public abstract ConnectionConfig getConnectionConfig();@b@@b@ public abstract MessageResource getMessageResource();@b@@b@ public abstract FtpletContainer getFtpletContainer();@b@@b@ public abstract Listener getListener(String paramString);@b@@b@ public abstract Map<String, Listener> getListeners();@b@@b@ public abstract CommandFactory getCommandFactory();@b@@b@ public abstract void dispose();@b@@b@ public abstract ThreadPoolExecutor getThreadPoolExecutor();@b@}
package org.apache.ftpserver.impl;@b@@b@import java.util.ArrayList;@b@import java.util.HashMap;@b@import java.util.List;@b@import java.util.Map;@b@import java.util.concurrent.ThreadPoolExecutor;@b@import java.util.concurrent.TimeUnit;@b@import org.apache.ftpserver.ConnectionConfig;@b@import org.apache.ftpserver.ConnectionConfigFactory;@b@import org.apache.ftpserver.command.CommandFactory;@b@import org.apache.ftpserver.command.CommandFactoryFactory;@b@import org.apache.ftpserver.filesystem.nativefs.NativeFileSystemFactory;@b@import org.apache.ftpserver.ftplet.Authority;@b@import org.apache.ftpserver.ftplet.FileSystemFactory;@b@import org.apache.ftpserver.ftplet.FtpStatistics;@b@import org.apache.ftpserver.ftplet.Ftplet;@b@import org.apache.ftpserver.ftplet.UserManager;@b@import org.apache.ftpserver.ftpletcontainer.FtpletContainer;@b@import org.apache.ftpserver.ftpletcontainer.impl.DefaultFtpletContainer;@b@import org.apache.ftpserver.listener.Listener;@b@import org.apache.ftpserver.listener.ListenerFactory;@b@import org.apache.ftpserver.message.MessageResource;@b@import org.apache.ftpserver.message.MessageResourceFactory;@b@import org.apache.ftpserver.usermanager.PropertiesUserManagerFactory;@b@import org.apache.ftpserver.usermanager.impl.BaseUser;@b@import org.apache.ftpserver.usermanager.impl.ConcurrentLoginPermission;@b@import org.apache.ftpserver.usermanager.impl.TransferRatePermission;@b@import org.apache.ftpserver.usermanager.impl.WritePermission;@b@import org.apache.mina.filter.executor.OrderedThreadPoolExecutor;@b@import org.slf4j.Logger;@b@import org.slf4j.LoggerFactory;@b@@b@public class DefaultFtpServerContext@b@ implements FtpServerContext@b@{@b@ private final Logger LOG = LoggerFactory.getLogger(DefaultFtpServerContext.class);@b@ private MessageResource messageResource = new MessageResourceFactory().createMessageResource();@b@ private UserManager userManager = new PropertiesUserManagerFactory().createUserManager();@b@ private FileSystemFactory fileSystemManager = new NativeFileSystemFactory();@b@ private FtpletContainer ftpletContainer = new DefaultFtpletContainer();@b@ private FtpStatistics statistics = new DefaultFtpStatistics();@b@ private CommandFactory commandFactory = new CommandFactoryFactory().createCommandFactory();@b@ private ConnectionConfig connectionConfig = new ConnectionConfigFactory().createConnectionConfig();@b@ private Map<String, Listener> listeners = new HashMap();@b@ private static final List<Authority> ADMIN_AUTHORITIES = new ArrayList();@b@ private static final List<Authority> ANON_AUTHORITIES = new ArrayList();@b@ private ThreadPoolExecutor threadPoolExecutor = null;@b@@b@ public DefaultFtpServerContext()@b@ {@b@ this.listeners.put("default", new ListenerFactory().createListener());@b@ }@b@@b@ public void createDefaultUsers()@b@ throws Exception@b@ {@b@ UserManager userManager = getUserManager();@b@@b@ String adminName = userManager.getAdminName();@b@ if (!(userManager.doesExist(adminName))) {@b@ this.LOG.info("Creating user : " + adminName);@b@ BaseUser adminUser = new BaseUser();@b@ adminUser.setName(adminName);@b@ adminUser.setPassword(adminName);@b@ adminUser.setEnabled(true);@b@@b@ adminUser.setAuthorities(ADMIN_AUTHORITIES);@b@@b@ adminUser.setHomeDirectory("./res/home");@b@ adminUser.setMaxIdleTime(0);@b@ userManager.save(adminUser);@b@ }@b@@b@ if (!(userManager.doesExist("anonymous"))) {@b@ this.LOG.info("Creating user : anonymous");@b@ BaseUser anonUser = new BaseUser();@b@ anonUser.setName("anonymous");@b@ anonUser.setPassword("");@b@@b@ anonUser.setAuthorities(ANON_AUTHORITIES);@b@@b@ anonUser.setEnabled(true);@b@@b@ anonUser.setHomeDirectory("./res/home");@b@ anonUser.setMaxIdleTime(300);@b@ userManager.save(anonUser);@b@ }@b@ }@b@@b@ public UserManager getUserManager()@b@ {@b@ return this.userManager;@b@ }@b@@b@ public FileSystemFactory getFileSystemManager()@b@ {@b@ return this.fileSystemManager;@b@ }@b@@b@ public MessageResource getMessageResource()@b@ {@b@ return this.messageResource;@b@ }@b@@b@ public FtpStatistics getFtpStatistics()@b@ {@b@ return this.statistics;@b@ }@b@@b@ public void setFtpStatistics(FtpStatistics statistics) {@b@ this.statistics = statistics;@b@ }@b@@b@ public FtpletContainer getFtpletContainer()@b@ {@b@ return this.ftpletContainer;@b@ }@b@@b@ public CommandFactory getCommandFactory()@b@ {@b@ return this.commandFactory;@b@ }@b@@b@ public Ftplet getFtplet(String name)@b@ {@b@ return this.ftpletContainer.getFtplet(name);@b@ }@b@@b@ public void dispose()@b@ {@b@ this.listeners.clear();@b@ this.ftpletContainer.getFtplets().clear();@b@ if (this.threadPoolExecutor != null) {@b@ this.LOG.debug("Shutting down the thread pool executor");@b@ this.threadPoolExecutor.shutdown();@b@ try {@b@ this.threadPoolExecutor.awaitTermination(5000L, TimeUnit.MILLISECONDS);@b@ }@b@ catch (InterruptedException e)@b@ {@b@ }@b@ }@b@ }@b@@b@ public Listener getListener(String name) {@b@ return ((Listener)this.listeners.get(name));@b@ }@b@@b@ public void setListener(String name, Listener listener) {@b@ this.listeners.put(name, listener);@b@ }@b@@b@ public Map<String, Listener> getListeners() {@b@ return this.listeners;@b@ }@b@@b@ public void setListeners(Map<String, Listener> listeners) {@b@ this.listeners = listeners;@b@ }@b@@b@ public void addListener(String name, Listener listener) {@b@ this.listeners.put(name, listener);@b@ }@b@@b@ public Listener removeListener(String name) {@b@ return ((Listener)this.listeners.remove(name));@b@ }@b@@b@ public void setCommandFactory(CommandFactory commandFactory) {@b@ this.commandFactory = commandFactory;@b@ }@b@@b@ public void setFileSystemManager(FileSystemFactory fileSystemManager) {@b@ this.fileSystemManager = fileSystemManager;@b@ }@b@@b@ public void setFtpletContainer(FtpletContainer ftpletContainer) {@b@ this.ftpletContainer = ftpletContainer;@b@ }@b@@b@ public void setMessageResource(MessageResource messageResource) {@b@ this.messageResource = messageResource;@b@ }@b@@b@ public void setUserManager(UserManager userManager) {@b@ this.userManager = userManager;@b@ }@b@@b@ public ConnectionConfig getConnectionConfig() {@b@ return this.connectionConfig;@b@ }@b@@b@ public void setConnectionConfig(ConnectionConfig connectionConfig) {@b@ this.connectionConfig = connectionConfig;@b@ }@b@@b@ public synchronized ThreadPoolExecutor getThreadPoolExecutor() {@b@ if (this.threadPoolExecutor == null) {@b@ int maxThreads = this.connectionConfig.getMaxThreads();@b@ if (maxThreads < 1) {@b@ int maxLogins = this.connectionConfig.getMaxLogins();@b@ if (maxLogins > 0) {@b@ maxThreads = maxLogins;@b@ }@b@ else@b@ maxThreads = 16;@b@ }@b@@b@ this.LOG.debug("Intializing shared thread pool executor with max threads of {}", Integer.valueOf(maxThreads));@b@ this.threadPoolExecutor = new OrderedThreadPoolExecutor(maxThreads);@b@ }@b@ return this.threadPoolExecutor;@b@ }@b@@b@ static@b@ {@b@ ADMIN_AUTHORITIES.add(new WritePermission());@b@@b@ ANON_AUTHORITIES.add(new ConcurrentLoginPermission(20, 2));@b@ ANON_AUTHORITIES.add(new TransferRatePermission(4800, 4800));@b@ }@b@}