首页

关于apache的开源ftpserver服务器源码包中通过命令模式command部分主要设计实现及代码解读

标签:命令模式,command,apache-ftp,ftpserver,源码,ftpserver-core     发布时间:2017-12-18   

一、前言

通过apacheftpserver-core包(1.0.6)中关于org.apache.ftpserver.command.Command基于命令模式实现(如下图),其中ftp的cwd、dele、type、list等常用的操作命令基于AbstractCommand定义接口,再注入到DefaultCommandFactory工厂类中。

关于apache的开源ftpserver服务器源码包中通过命令模式command部分主要设计实现及代码解读

二、源码说明

1.Command接口

package org.apache.ftpserver.command;@b@@b@import java.io.IOException;@b@import org.apache.ftpserver.ftplet.FtpException;@b@import org.apache.ftpserver.ftplet.FtpRequest;@b@import org.apache.ftpserver.impl.FtpIoSession;@b@import org.apache.ftpserver.impl.FtpServerContext;@b@@b@public abstract interface Command@b@{@b@  public abstract void execute(FtpIoSession paramFtpIoSession, FtpServerContext paramFtpServerContext, FtpRequest paramFtpRequest)@b@    throws IOException, FtpException;@b@}

2.LIST实现类

package org.apache.ftpserver.command.impl;@b@@b@import java.io.IOException;@b@import java.net.InetAddress;@b@import java.net.SocketException;@b@import org.apache.ftpserver.command.AbstractCommand;@b@import org.apache.ftpserver.command.impl.listing.DirectoryLister;@b@import org.apache.ftpserver.command.impl.listing.LISTFileFormater;@b@import org.apache.ftpserver.command.impl.listing.ListArgument;@b@import org.apache.ftpserver.command.impl.listing.ListArgumentParser;@b@import org.apache.ftpserver.ftplet.DataConnection;@b@import org.apache.ftpserver.ftplet.DataConnectionFactory;@b@import org.apache.ftpserver.ftplet.DefaultFtpReply;@b@import org.apache.ftpserver.ftplet.FileSystemView;@b@import org.apache.ftpserver.ftplet.FtpException;@b@import org.apache.ftpserver.ftplet.FtpFile;@b@import org.apache.ftpserver.ftplet.FtpRequest;@b@import org.apache.ftpserver.impl.FtpIoSession;@b@import org.apache.ftpserver.impl.FtpServerContext;@b@import org.apache.ftpserver.impl.IODataConnectionFactory;@b@import org.apache.ftpserver.impl.LocalizedFtpReply;@b@import org.apache.ftpserver.impl.ServerDataConnectionFactory;@b@import org.slf4j.Logger;@b@import org.slf4j.LoggerFactory;@b@@b@public class LIST extends AbstractCommand@b@{@b@  private final Logger LOG;@b@  private static final LISTFileFormater LIST_FILE_FORMATER = new LISTFileFormater();@b@  private DirectoryLister directoryLister;@b@@b@  public LIST()@b@  {@b@    this.LOG = LoggerFactory.getLogger(LIST.class);@b@@b@    this.directoryLister = new DirectoryLister();@b@  }@b@@b@  public void execute(FtpIoSession session, FtpServerContext context, FtpRequest request)@b@    throws IOException, FtpException@b@  {@b@    try@b@    {@b@      DataConnection dataConnection;@b@      session.resetState();@b@@b@      ListArgument parsedArg = ListArgumentParser.parse(request.getArgument());@b@@b@      FtpFile file = session.getFileSystemView().getFile(parsedArg.getFile());@b@@b@      if (!(file.doesExist())) {@b@        this.LOG.debug("Listing on a non-existing file");@b@        session.write(LocalizedFtpReply.translate(session, request, context, 450, "LIST", null));@b@@b@        return;@b@      }@b@      DataConnectionFactory connFactory = session.getDataConnection();@b@      if (connFactory instanceof IODataConnectionFactory) {@b@        InetAddress address = ((IODataConnectionFactory)connFactory).getInetAddress();@b@@b@        if (address == null) {@b@          session.write(new DefaultFtpReply(503, "PORT or PASV must be issued first"));@b@@b@          return;@b@        }@b@      }@b@      session.write(LocalizedFtpReply.translate(session, request, context, 150, "LIST", null));@b@      try@b@      {@b@        dataConnection = session.getDataConnection().openConnection();@b@      } catch (Exception e) {@b@        this.LOG.debug("Exception getting the output data stream", e);@b@        session.write(LocalizedFtpReply.translate(session, request, context, 425, "LIST", null));@b@@b@        session.getDataConnection().closeDataConnection(); return;@b@      }@b@      boolean failure = false;@b@      try@b@      {@b@        dataConnection.transferToClient(session.getFtpletSession(), this.directoryLister.listFiles(parsedArg, session.getFileSystemView(), LIST_FILE_FORMATER));@b@      }@b@      catch (SocketException ex)@b@      {@b@        this.LOG.debug("Socket exception during list transfer", ex);@b@        failure = true;@b@        session.write(LocalizedFtpReply.translate(session, request, context, 426, "LIST", null));@b@      }@b@      catch (IOException ex)@b@      {@b@        this.LOG.debug("IOException during list transfer", ex);@b@        failure = true;@b@        session.write(LocalizedFtpReply.translate(session, request, context, 551, "LIST", null));@b@      }@b@      catch (IllegalArgumentException e)@b@      {@b@        this.LOG.debug("Illegal list syntax: " + request.getArgument(), e);@b@@b@        session.write(LocalizedFtpReply.translate(session, request, context, 501, "LIST", null));@b@      }@b@@b@      if (!(failure))@b@        session.write(LocalizedFtpReply.translate(session, request, context, 226, "LIST", null));@b@@b@    }@b@    finally@b@    {@b@      session.getDataConnection().closeDataConnection();@b@    }@b@  }@b@}

3.CommandFactory工厂接口类

package org.apache.ftpserver.command;@b@@b@public abstract interface CommandFactory@b@{@b@  public abstract Command getCommand(String paramString);@b@}

4.DefaultCommandFactory默认工厂实现类

package org.apache.ftpserver.command.impl;@b@@b@import java.util.HashMap;@b@import java.util.Map;@b@import org.apache.ftpserver.command.Command;@b@import org.apache.ftpserver.command.CommandFactory;@b@@b@public class DefaultCommandFactory@b@  implements CommandFactory@b@{@b@  private Map<String, Command> commandMap = new HashMap();@b@@b@  public DefaultCommandFactory(Map<String, Command> commandMap)@b@  {@b@    this.commandMap = commandMap;@b@  }@b@@b@  public Command getCommand(String cmdName)@b@  {@b@    if ((cmdName == null) || (cmdName.equals("")))@b@      return null;@b@@b@    String upperCaseCmdName = cmdName.toUpperCase();@b@    return ((Command)this.commandMap.get(upperCaseCmdName));@b@  }@b@}