100dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair/* 200dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair * Copyright 2008 the original author or authors. 300dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair * 400dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair * Licensed under the Apache License, Version 2.0 (the "License"); 500dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair * you may not use this file except in compliance with the License. 600dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair * You may obtain a copy of the License at 700dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair * 800dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair * http://www.apache.org/licenses/LICENSE-2.0 900dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair * 1000dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair * Unless required by applicable law or agreed to in writing, software 1100dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair * distributed under the License is distributed on an "AS IS" BASIS, 1200dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1300dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair * See the License for the specific language governing permissions and 1400dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair * limitations under the License. 1500dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair */ 1600dc7bdcf1df9e86789d963984dfc6912a8854c6chrismairpackage org.mockftpserver.fake; 1700dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair 1800dc7bdcf1df9e86789d963984dfc6912a8854c6chrismairimport org.mockftpserver.core.command.CommandHandler; 1900dc7bdcf1df9e86789d963984dfc6912a8854c6chrismairimport org.mockftpserver.core.command.CommandNames; 2000dc7bdcf1df9e86789d963984dfc6912a8854c6chrismairimport org.mockftpserver.core.command.ConnectCommandHandler; 2100dc7bdcf1df9e86789d963984dfc6912a8854c6chrismairimport org.mockftpserver.core.command.ReplyTextBundleUtil; 2200dc7bdcf1df9e86789d963984dfc6912a8854c6chrismairimport org.mockftpserver.core.command.UnsupportedCommandHandler; 2300dc7bdcf1df9e86789d963984dfc6912a8854c6chrismairimport org.mockftpserver.core.server.AbstractFtpServer; 2400dc7bdcf1df9e86789d963984dfc6912a8854c6chrismairimport org.mockftpserver.fake.command.*; 2500dc7bdcf1df9e86789d963984dfc6912a8854c6chrismairimport org.mockftpserver.fake.filesystem.FileSystem; 2600dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair 2700dc7bdcf1df9e86789d963984dfc6912a8854c6chrismairimport java.util.HashMap; 2800dc7bdcf1df9e86789d963984dfc6912a8854c6chrismairimport java.util.List; 2900dc7bdcf1df9e86789d963984dfc6912a8854c6chrismairimport java.util.Map; 3000dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair 3100dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair/** 3200dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair * <b>FakeFtpServer</b> is the top-level class for a "fake" implementation of an FTP Server, 3300dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair * suitable for testing FTP client code or standing in for a live FTP server. 3400dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair * <p/> 3500dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair * <b>FakeFtpServer</b> provides a high-level abstraction for an FTP Server and is suitable 3600dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair * for most testing and simulation scenarios. You define a filesystem (internal, in-memory) containing 3700dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair * an arbitrary set of files and directories. These files and directories can (optionally) have 3800dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair * associated access permissions. You also configure a set of one or more user accounts that 3900dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair * control which users can login to the FTP server, and their home (default) directories. The 4000dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair * user account is also used when assigning file and directory ownership for new files. 4100dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair * <p> <b>FakeFtpServer</b> processes FTP client requests and responds with reply codes and 4200dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair * reply messages consistent with its configuration and the contents of its internal filesystem, 4300dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair * including file and directory permissions, if they have been configured. 4400dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair * <p/> 4500dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair * <b>FakeFtpServer</b> can be fully configured programmatically or within the 4600dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair * <a href="http://www.springframework.org/">Spring Framework</a> or other dependency-injection container. 4700dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair * <p/> 4800dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair * In general the steps for setting up and starting the <b>FakeFtpServer</b> are: 4900dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair * <ol> 5000dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair * <li>Create a new <b>FakeFtpServer</b> instance, and optionally set the server control port.</li> 5100dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair * <li>Create and configure a <b>FileSystem</b>, and attach to the <b>FakeFtpServer</b> instance.</li> 5200dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair * <li>Create and configure one or more <b>UserAccount</b> objects and attach to the <b>FakeFtpServer</b> instance.</li> 5300dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair * <li>Start the <b>FakeFtpServer</b> instance.</li> 5400dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair * </ol> 5500dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair * <h4>Example Code</h4> 5600dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair * <pre><code> 5700dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair * FakeFtpServer fakeFtpServer = new FakeFtpServer(); 5800dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair * 5900dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair * FileSystem fileSystem = new WindowsFakeFileSystem(); 6000dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair * fileSystem.add(new DirectoryEntry("c:\\")); 6100dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair * fileSystem.add(new DirectoryEntry("c:\\data")); 6200dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair * fileSystem.add(new FileEntry("c:\\data\\file1.txt", "abcdef 1234567890")); 6300dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair * fileSystem.add(new FileEntry("c:\\data\\run.exe")); 6400dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair * fakeFtpServer.setFileSystem(fileSystem); 6500dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair * 6600dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair * // Create UserAccount with username, password, home-directory 6700dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair * UserAccount userAccount = new UserAccount("joe", "joe123", "c:\\"); 6800dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair * fakeFtpServer.addUserAccounts(userAccount); 6900dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair * 7000dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair * fakeFtpServer.start(); 7100dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair * </code></pre> 7200dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair * 7300dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair * <h4>Example Code with Permissions</h4> 7400dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair * You can optionally set the permissions and owner/group for each file and directory, as in the following example. 7500dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair * <pre><code> 7600dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair * FileSystem fileSystem = new UnixFakeFileSystem(); 7700dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair * DirectoryEntry directoryEntry1 = new DirectoryEntry("/"); 7800dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair * directoryEntry1.setPermissions(new Permissions("rwxrwx---")); 7900dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair * directoryEntry1.setOwner("joe"); 8000dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair * directoryEntry1.setGroup("dev"); 8100dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair * 8200dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair * DirectoryEntry directoryEntry2 = new DirectoryEntry("/data"); 8300dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair * directoryEntry2.setPermissions(Permissions.ALL); 8400dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair * directoryEntry2.setOwner("joe"); 8500dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair * directoryEntry2.setGroup("dev"); 8600dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair * 8700dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair * FileEntry fileEntry1 = new FileEntry("/data/file1.txt", "abcdef 1234567890"); 8800dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair * fileEntry1.setPermissionsFromString("rw-rw-rw-"); 8900dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair * fileEntry1.setOwner("joe"); 9000dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair * fileEntry1.setGroup("dev"); 9100dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair * 9200dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair * FileEntry fileEntry2 = new FileEntry("/data/run.exe"); 9300dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair * fileEntry2.setPermissionsFromString("rwxrwx---"); 9400dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair * fileEntry2.setOwner("mary"); 9500dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair * fileEntry2.setGroup("dev"); 9600dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair * 9700dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair * fileSystem.add(directoryEntry1); 9800dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair * fileSystem.add(directoryEntry2); 9900dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair * fileSystem.add(fileEntry1); 10000dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair * fileSystem.add(fileEntry2); 10100dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair * 10200dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair * FakeFtpServer fakeFtpServer = new FakeFtpServer(); 10300dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair * fakeFtpServer.setFileSystem(fileSystem); 10400dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair * 10500dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair * // Create UserAccount with username, password, home-directory 10600dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair * UserAccount userAccount = new UserAccount("joe", "joe123", "/"); 10700dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair * fakeFtpServer.addUserAccounts(userAccount); 10800dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair * 10900dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair * fakeFtpServer.start(); 11000dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair * </code></pre> 11100dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair * 11200dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair * <h4>FTP Server Control Port</h4> 11300dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair * By default, <b>FakeFtpServer</b> binds to the server control port of 21. You can use a different server control 11400dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair * port by setting the <code>serverControlPort</code> property. If you specify a value of <code>0</code>, 11500dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair * then a free port number will be chosen automatically; call <code>getServerControlPort()</code> AFTER 11600dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair * <code>start()</code> has been called to determine the actual port number being used. Using a non-default 11700dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair * port number is usually necessary when running on Unix or some other system where that port number is 11800dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair * already in use or cannot be bound from a user process. 11900dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair * 12000dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair * <h4>Other Configuration</h4> 12100dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair * The <code>systemName</code> property specifies the value returned by the <code>SYST</code> 12200dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair * command. Note that this is typically used by an FTP client to determine how to parse 12300dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair * system-dependent reply text, such as directory listings. This value defaults to <code>"WINDOWS"</code>. 12400dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair * <p/> 12500dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair * The <code>helpText</code> property specifies a <i>Map</i> of help text replies sent by the 12600dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair * <code>HELP</code> command. The keys in that <i>Map</i> correspond to the command names passed as 12700dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair * parameters to the <code>HELP</code> command. An entry with the key of an empty string ("") indicates the 12800dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair * text used as the default help text when no command name parameter is specified for the <code>HELP</code> command. 12900dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair * 13000dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair * <h4>FTP Command Reply Text ResourceBundle</h4> 13100dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair * The default text asociated with each FTP command reply code is contained within the 13200dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair * "ReplyText.properties" ResourceBundle file. You can customize these messages by providing a 13300dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair * locale-specific ResourceBundle file on the CLASSPATH, according to the normal lookup rules of 13400dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair * the ResourceBundle class (e.g., "ReplyText_de.properties"). Alternatively, you can 13500dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair * completely replace the ResourceBundle file by calling the calling the 13600dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair * {@link #setReplyTextBaseName(String)} method. 13700dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair * 13800dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair * @author Chris Mair 13900dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair * @version $Revision$ - $Date$ 14000dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair */ 14100dc7bdcf1df9e86789d963984dfc6912a8854c6chrismairpublic class FakeFtpServer extends AbstractFtpServer implements ServerConfiguration { 14200dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair 14300dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair private FileSystem fileSystem; 14400dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair private String systemName = "WINDOWS"; 14500dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair private String systemStatus = "Connected"; 14600dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair private Map helpText = new HashMap(); 14700dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair private Map userAccounts = new HashMap(); 14800dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair 14900dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair public FileSystem getFileSystem() { 15000dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair return fileSystem; 15100dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair } 15200dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair 15300dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair public void setFileSystem(FileSystem fileSystem) { 15400dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair this.fileSystem = fileSystem; 15500dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair } 15600dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair 15700dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair public String getSystemName() { 15800dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair return systemName; 15900dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair } 16000dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair 16100dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair public void setSystemName(String systemName) { 16200dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair this.systemName = systemName; 16300dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair } 16400dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair 16500dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair public Map getHelpText() { 16600dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair return helpText; 16700dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair } 16800dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair 16900dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair public void setHelpText(Map helpText) { 17000dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair this.helpText = helpText; 17100dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair } 17200dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair 17300dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair public FakeFtpServer() { 17400dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair setCommandHandler(CommandNames.ACCT, new AcctCommandHandler()); 17500dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair setCommandHandler(CommandNames.ABOR, new AborCommandHandler()); 17600dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair setCommandHandler(CommandNames.ALLO, new AlloCommandHandler()); 17700dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair setCommandHandler(CommandNames.APPE, new AppeCommandHandler()); 17800dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair setCommandHandler(CommandNames.CWD, new CwdCommandHandler()); 17900dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair setCommandHandler(CommandNames.CDUP, new CdupCommandHandler()); 18000dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair setCommandHandler(CommandNames.DELE, new DeleCommandHandler()); 18100dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair setCommandHandler(CommandNames.EPRT, new EprtCommandHandler()); 18200dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair setCommandHandler(CommandNames.EPSV, new EpsvCommandHandler()); 18300dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair setCommandHandler(CommandNames.HELP, new HelpCommandHandler()); 18400dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair setCommandHandler(CommandNames.LIST, new ListCommandHandler()); 18500dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair setCommandHandler(CommandNames.MKD, new MkdCommandHandler()); 18600dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair setCommandHandler(CommandNames.MODE, new ModeCommandHandler()); 18700dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair setCommandHandler(CommandNames.NLST, new NlstCommandHandler()); 18800dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair setCommandHandler(CommandNames.NOOP, new NoopCommandHandler()); 18900dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair setCommandHandler(CommandNames.PASS, new PassCommandHandler()); 19000dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair setCommandHandler(CommandNames.PASV, new PasvCommandHandler()); 19100dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair setCommandHandler(CommandNames.PWD, new PwdCommandHandler()); 19200dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair setCommandHandler(CommandNames.PORT, new PortCommandHandler()); 19300dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair setCommandHandler(CommandNames.QUIT, new QuitCommandHandler()); 19400dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair setCommandHandler(CommandNames.REIN, new ReinCommandHandler()); 19500dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair setCommandHandler(CommandNames.REST, new RestCommandHandler()); 19600dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair setCommandHandler(CommandNames.RETR, new RetrCommandHandler()); 19700dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair setCommandHandler(CommandNames.RMD, new RmdCommandHandler()); 19800dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair setCommandHandler(CommandNames.RNFR, new RnfrCommandHandler()); 19900dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair setCommandHandler(CommandNames.RNTO, new RntoCommandHandler()); 20000dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair setCommandHandler(CommandNames.SITE, new SiteCommandHandler()); 20100dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair setCommandHandler(CommandNames.SMNT, new SmntCommandHandler()); 20200dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair setCommandHandler(CommandNames.STAT, new StatCommandHandler()); 20300dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair setCommandHandler(CommandNames.STOR, new StorCommandHandler()); 20400dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair setCommandHandler(CommandNames.STOU, new StouCommandHandler()); 20500dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair setCommandHandler(CommandNames.STRU, new StruCommandHandler()); 20600dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair setCommandHandler(CommandNames.SYST, new SystCommandHandler()); 20700dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair setCommandHandler(CommandNames.TYPE, new TypeCommandHandler()); 20800dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair setCommandHandler(CommandNames.USER, new UserCommandHandler()); 20900dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair setCommandHandler(CommandNames.XPWD, new PwdCommandHandler()); 21000dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair 21100dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair // "Special" Command Handlers 21200dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair setCommandHandler(CommandNames.CONNECT, new ConnectCommandHandler()); 21300dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair setCommandHandler(CommandNames.UNSUPPORTED, new UnsupportedCommandHandler()); 21400dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair } 21500dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair 21600dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair /** 21700dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair * Initialize a CommandHandler that has been registered to this server. 21800dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair * 21900dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair * If the CommandHandler implements the <code>ServerConfigurationAware</code> interface, then set its 22000dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair * <code>ServerConfiguration</code> property to <code>this</code>. 22100dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair * 22200dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair * If the CommandHandler implements the <code>ReplyTextBundleAware</code> interface, then set its 22300dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair * <code>replyTextBundle</code> property using the reply text bundle for this server. 22400dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair * 22500dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair * @param commandHandler - the CommandHandler to initialize 22600dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair */ 22700dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair protected void initializeCommandHandler(CommandHandler commandHandler) { 22800dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair if (commandHandler instanceof ServerConfigurationAware) { 22900dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair ServerConfigurationAware sca = (ServerConfigurationAware) commandHandler; 23000dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair sca.setServerConfiguration(this); 23100dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair } 23200dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair 23300dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair ReplyTextBundleUtil.setReplyTextBundleIfAppropriate(commandHandler, getReplyTextBundle()); 23400dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair } 23500dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair 23600dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair /** 23700dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair * @return the {@link UserAccount} configured for this server for the specified user name 23800dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair */ 23900dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair public UserAccount getUserAccount(String username) { 24000dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair return (UserAccount) userAccounts.get(username); 24100dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair } 24200dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair 24300dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair /** 24400dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair * Return the help text for a command or the default help text if no command name is specified 24500dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair * 24600dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair * @param name - the command name; may be empty or null to indicate a request for the default help text 24700dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair * @return the help text for the named command or the default help text if no name is supplied 24800dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair */ 24900dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair public String getHelpText(String name) { 25000dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair String key = name == null ? "" : name; 25100dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair return (String) helpText.get(key); 25200dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair } 25300dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair 25400dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair /** 25500dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair * Add a single UserAccount. If an account with the same <code>username</code> already exists, 25600dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair * it will be replaced. 25700dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair * 25800dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair * @param userAccount - the UserAccount to add 25900dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair */ 26000dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair public void addUserAccount(UserAccount userAccount) { 26100dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair userAccounts.put(userAccount.getUsername(), userAccount); 26200dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair } 26300dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair 26400dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair /** 26500dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair * Add the UserAccount objects in the <code>userAccountList</code> to the set of UserAccounts. 26600dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair * 26700dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair * @param userAccountList - the List of UserAccount objects to add 26800dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair */ 26900dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair public void setUserAccounts(List userAccountList) { 27000dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair for (int i = 0; i < userAccountList.size(); i++) { 27100dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair UserAccount userAccount = (UserAccount) userAccountList.get(i); 27200dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair userAccounts.put(userAccount.getUsername(), userAccount); 27300dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair } 27400dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair } 27500dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair 27600dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair /** 27700dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair * Return the system status description 27800dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair * 27900dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair * @return the system status 28000dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair */ 28100dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair public String getSystemStatus() { 28200dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair return systemStatus; 28300dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair } 28400dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair 28500dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair /** 28600dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair * Set the system status description text, used by the STAT command handler. 28700dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair * 28800dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair * @param systemStatus - the system status description text 28900dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair */ 29000dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair public void setSystemStatus(String systemStatus) { 29100dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair this.systemStatus = systemStatus; 29200dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair } 29300dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair 29400dc7bdcf1df9e86789d963984dfc6912a8854c6chrismair}