1a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair/* 2a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair * Copyright 2008 the original author or authors. 3a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair * 4a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair * Licensed under the Apache License, Version 2.0 (the "License"); 5a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair * you may not use this file except in compliance with the License. 6a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair * You may obtain a copy of the License at 7a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair * 8a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair * http://www.apache.org/licenses/LICENSE-2.0 9a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair * 10a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair * Unless required by applicable law or agreed to in writing, software 11a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair * distributed under the License is distributed on an "AS IS" BASIS, 12a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair * See the License for the specific language governing permissions and 14a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair * limitations under the License. 15a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair */ 16a0ad464efff5f5e2d2523a3522cce6823ce05858chrismairpackage org.mockftpserver.fake; 17a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair 18a0ad464efff5f5e2d2523a3522cce6823ce05858chrismairimport org.mockftpserver.core.command.CommandHandler; 19a0ad464efff5f5e2d2523a3522cce6823ce05858chrismairimport org.mockftpserver.core.command.CommandNames; 20a0ad464efff5f5e2d2523a3522cce6823ce05858chrismairimport org.mockftpserver.core.command.ConnectCommandHandler; 21a0ad464efff5f5e2d2523a3522cce6823ce05858chrismairimport org.mockftpserver.core.command.ReplyTextBundleUtil; 22a0ad464efff5f5e2d2523a3522cce6823ce05858chrismairimport org.mockftpserver.core.command.UnsupportedCommandHandler; 23a0ad464efff5f5e2d2523a3522cce6823ce05858chrismairimport org.mockftpserver.core.server.AbstractFtpServer; 24a0ad464efff5f5e2d2523a3522cce6823ce05858chrismairimport org.mockftpserver.fake.command.*; 25a0ad464efff5f5e2d2523a3522cce6823ce05858chrismairimport org.mockftpserver.fake.filesystem.FileSystem; 26a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair 27a0ad464efff5f5e2d2523a3522cce6823ce05858chrismairimport java.util.HashMap; 28a0ad464efff5f5e2d2523a3522cce6823ce05858chrismairimport java.util.List; 29a0ad464efff5f5e2d2523a3522cce6823ce05858chrismairimport java.util.Map; 30a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair 31a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair/** 32a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair * <b>FakeFtpServer</b> is the top-level class for a "fake" implementation of an FTP Server, 33a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair * suitable for testing FTP client code or standing in for a live FTP server. 34a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair * <p/> 35a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair * <b>FakeFtpServer</b> provides a high-level abstraction for an FTP Server and is suitable 36a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair * for most testing and simulation scenarios. You define a filesystem (internal, in-memory) containing 37a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair * an arbitrary set of files and directories. These files and directories can (optionally) have 38a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair * associated access permissions. You also configure a set of one or more user accounts that 39a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair * control which users can login to the FTP server, and their home (default) directories. The 40a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair * user account is also used when assigning file and directory ownership for new files. 41a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair * <p> <b>FakeFtpServer</b> processes FTP client requests and responds with reply codes and 42a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair * reply messages consistent with its configuration and the contents of its internal filesystem, 43a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair * including file and directory permissions, if they have been configured. 44a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair * <p/> 45a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair * <b>FakeFtpServer</b> can be fully configured programmatically or within the 46a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair * <a href="http://www.springframework.org/">Spring Framework</a> or other dependency-injection container. 47a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair * <p/> 48a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair * In general the steps for setting up and starting the <b>FakeFtpServer</b> are: 49a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair * <ol> 50a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair * <li>Create a new <b>FakeFtpServer</b> instance, and optionally set the server control port.</li> 51a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair * <li>Create and configure a <b>FileSystem</b>, and attach to the <b>FakeFtpServer</b> instance.</li> 52a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair * <li>Create and configure one or more <b>UserAccount</b> objects and attach to the <b>FakeFtpServer</b> instance.</li> 53a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair * <li>Start the <b>FakeFtpServer</b> instance.</li> 54a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair * </ol> 55a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair * <h4>Example Code</h4> 56a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair * <pre><code> 57a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair * FakeFtpServer fakeFtpServer = new FakeFtpServer(); 58a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair * 59a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair * FileSystem fileSystem = new WindowsFakeFileSystem(); 60a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair * fileSystem.add(new DirectoryEntry("c:\\")); 61a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair * fileSystem.add(new DirectoryEntry("c:\\data")); 62a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair * fileSystem.add(new FileEntry("c:\\data\\file1.txt", "abcdef 1234567890")); 63a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair * fileSystem.add(new FileEntry("c:\\data\\run.exe")); 64a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair * fakeFtpServer.setFileSystem(fileSystem); 65a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair * 66a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair * // Create UserAccount with username, password, home-directory 67a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair * UserAccount userAccount = new UserAccount("joe", "joe123", "c:\\"); 68a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair * fakeFtpServer.addUserAccounts(userAccount); 69a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair * 70a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair * fakeFtpServer.start(); 71a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair * </code></pre> 72a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair * 73a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair * <h4>Example Code with Permissions</h4> 74a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair * You can optionally set the permissions and owner/group for each file and directory, as in the following example. 75a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair * <pre><code> 76a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair * FileSystem fileSystem = new UnixFakeFileSystem(); 77a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair * DirectoryEntry directoryEntry1 = new DirectoryEntry("/"); 78a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair * directoryEntry1.setPermissions(new Permissions("rwxrwx---")); 79a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair * directoryEntry1.setOwner("joe"); 80a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair * directoryEntry1.setGroup("dev"); 81a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair * 82a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair * DirectoryEntry directoryEntry2 = new DirectoryEntry("/data"); 83a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair * directoryEntry2.setPermissions(Permissions.ALL); 84a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair * directoryEntry2.setOwner("joe"); 85a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair * directoryEntry2.setGroup("dev"); 86a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair * 87a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair * FileEntry fileEntry1 = new FileEntry("/data/file1.txt", "abcdef 1234567890"); 88a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair * fileEntry1.setPermissionsFromString("rw-rw-rw-"); 89a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair * fileEntry1.setOwner("joe"); 90a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair * fileEntry1.setGroup("dev"); 91a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair * 92a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair * FileEntry fileEntry2 = new FileEntry("/data/run.exe"); 93a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair * fileEntry2.setPermissionsFromString("rwxrwx---"); 94a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair * fileEntry2.setOwner("mary"); 95a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair * fileEntry2.setGroup("dev"); 96a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair * 97a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair * fileSystem.add(directoryEntry1); 98a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair * fileSystem.add(directoryEntry2); 99a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair * fileSystem.add(fileEntry1); 100a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair * fileSystem.add(fileEntry2); 101a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair * 102a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair * FakeFtpServer fakeFtpServer = new FakeFtpServer(); 103a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair * fakeFtpServer.setFileSystem(fileSystem); 104a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair * 105a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair * // Create UserAccount with username, password, home-directory 106a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair * UserAccount userAccount = new UserAccount("joe", "joe123", "/"); 107a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair * fakeFtpServer.addUserAccounts(userAccount); 108a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair * 109a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair * fakeFtpServer.start(); 110a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair * </code></pre> 111a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair * 112a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair * <h4>FTP Server Control Port</h4> 113a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair * By default, <b>MockFtpServer</b> binds to the server control port of 21. You can use a different server 114a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair * control port by setting the the <code>serverControlPort</code> property. This is usually necessary 115a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair * when running on Unix or some other system where that port number is already in use or cannot be bound 116a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair * from a user process. 117a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair * 118a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair * <h4>Other Configuration</h4> 119a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair * The <code>systemName</code> property specifies the value returned by the <code>SYST</code> 120a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair * command. Note that this is typically used by an FTP client to determine how to parse 121a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair * system-dependent reply text, such as directory listings. This value defaults to <code>"WINDOWS"</code>. 122a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair * <p/> 123a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair * The <code>helpText</code> property specifies a <i>Map</i> of help text replies sent by the 124a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair * <code>HELP</code> command. The keys in that <i>Map</i> correspond to the command names passed as 125a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair * parameters to the <code>HELP</code> command. An entry with the key of an empty string ("") indicates the 126a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair * text used as the default help text when no command name parameter is specified for the <code>HELP</code> command. 127a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair * 128a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair * <h4>FTP Command Reply Text ResourceBundle</h4> 129a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair * The default text asociated with each FTP command reply code is contained within the 130a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair * "ReplyText.properties" ResourceBundle file. You can customize these messages by providing a 131a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair * locale-specific ResourceBundle file on the CLASSPATH, according to the normal lookup rules of 132a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair * the ResourceBundle class (e.g., "ReplyText_de.properties"). Alternatively, you can 133a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair * completely replace the ResourceBundle file by calling the calling the 134a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair * {@link #setReplyTextBaseName(String)} method. 135a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair * 136a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair * @author Chris Mair 137a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair * @version $Revision$ - $Date$ 138a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair */ 139a0ad464efff5f5e2d2523a3522cce6823ce05858chrismairpublic class FakeFtpServer extends AbstractFtpServer implements ServerConfiguration { 140a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair 141a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair private FileSystem fileSystem; 142a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair private String systemName = "WINDOWS"; 143a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair private String systemStatus = "Connected"; 144a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair private Map helpText = new HashMap(); 145a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair private Map userAccounts = new HashMap(); 146a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair 147a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair public FileSystem getFileSystem() { 148a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair return fileSystem; 149a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair } 150a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair 151a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair public void setFileSystem(FileSystem fileSystem) { 152a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair this.fileSystem = fileSystem; 153a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair } 154a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair 155a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair public String getSystemName() { 156a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair return systemName; 157a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair } 158a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair 159a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair public void setSystemName(String systemName) { 160a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair this.systemName = systemName; 161a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair } 162a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair 163a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair public Map getHelpText() { 164a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair return helpText; 165a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair } 166a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair 167a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair public void setHelpText(Map helpText) { 168a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair this.helpText = helpText; 169a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair } 170a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair 171a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair public FakeFtpServer() { 172a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair setCommandHandler(CommandNames.ACCT, new AcctCommandHandler()); 173a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair setCommandHandler(CommandNames.ABOR, new AborCommandHandler()); 174a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair setCommandHandler(CommandNames.ALLO, new AlloCommandHandler()); 175a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair setCommandHandler(CommandNames.APPE, new AppeCommandHandler()); 176a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair setCommandHandler(CommandNames.CWD, new CwdCommandHandler()); 177a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair setCommandHandler(CommandNames.CDUP, new CdupCommandHandler()); 178a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair setCommandHandler(CommandNames.DELE, new DeleCommandHandler()); 179a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair setCommandHandler(CommandNames.HELP, new HelpCommandHandler()); 180a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair setCommandHandler(CommandNames.LIST, new ListCommandHandler()); 181a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair setCommandHandler(CommandNames.MKD, new MkdCommandHandler()); 182a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair setCommandHandler(CommandNames.MODE, new ModeCommandHandler()); 183a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair setCommandHandler(CommandNames.NLST, new NlstCommandHandler()); 184a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair setCommandHandler(CommandNames.NOOP, new NoopCommandHandler()); 185a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair setCommandHandler(CommandNames.PASS, new PassCommandHandler()); 186a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair setCommandHandler(CommandNames.PASV, new PasvCommandHandler()); 187a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair setCommandHandler(CommandNames.PWD, new PwdCommandHandler()); 188a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair setCommandHandler(CommandNames.PORT, new PortCommandHandler()); 189a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair setCommandHandler(CommandNames.QUIT, new QuitCommandHandler()); 190a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair setCommandHandler(CommandNames.REIN, new ReinCommandHandler()); 191a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair setCommandHandler(CommandNames.REST, new RestCommandHandler()); 192a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair setCommandHandler(CommandNames.RETR, new RetrCommandHandler()); 193a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair setCommandHandler(CommandNames.RMD, new RmdCommandHandler()); 194a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair setCommandHandler(CommandNames.RNFR, new RnfrCommandHandler()); 195a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair setCommandHandler(CommandNames.RNTO, new RntoCommandHandler()); 196a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair setCommandHandler(CommandNames.SITE, new SiteCommandHandler()); 197a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair setCommandHandler(CommandNames.SMNT, new SmntCommandHandler()); 198a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair setCommandHandler(CommandNames.STAT, new StatCommandHandler()); 199a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair setCommandHandler(CommandNames.STOR, new StorCommandHandler()); 200a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair setCommandHandler(CommandNames.STOU, new StouCommandHandler()); 201a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair setCommandHandler(CommandNames.STRU, new StruCommandHandler()); 202a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair setCommandHandler(CommandNames.SYST, new SystCommandHandler()); 203a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair setCommandHandler(CommandNames.TYPE, new TypeCommandHandler()); 204a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair setCommandHandler(CommandNames.USER, new UserCommandHandler()); 205a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair setCommandHandler(CommandNames.XPWD, new PwdCommandHandler()); 206a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair 207a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair // "Special" Command Handlers 208a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair setCommandHandler(CommandNames.CONNECT, new ConnectCommandHandler()); 209a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair setCommandHandler(CommandNames.UNSUPPORTED, new UnsupportedCommandHandler()); 210a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair } 211a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair 212a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair /** 213a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair * Initialize a CommandHandler that has been registered to this server. 214a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair * 215a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair * If the CommandHandler implements the <code>ServerConfigurationAware</code> interface, then set its 216a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair * <code>ServerConfiguration</code> property to <code>this</code>. 217a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair * 218a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair * If the CommandHandler implements the <code>ReplyTextBundleAware</code> interface, then set its 219a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair * <code>replyTextBundle</code> property using the reply text bundle for this server. 220a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair * 221a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair * @param commandHandler - the CommandHandler to initialize 222a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair */ 223a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair protected void initializeCommandHandler(CommandHandler commandHandler) { 224a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair if (commandHandler instanceof ServerConfigurationAware) { 225a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair ServerConfigurationAware sca = (ServerConfigurationAware) commandHandler; 226a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair sca.setServerConfiguration(this); 227a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair } 228a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair 229a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair ReplyTextBundleUtil.setReplyTextBundleIfAppropriate(commandHandler, getReplyTextBundle()); 230a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair } 231a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair 232a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair /** 233a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair * @return the {@link UserAccount} configured for this server for the specified user name 234a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair */ 235a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair public UserAccount getUserAccount(String username) { 236a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair return (UserAccount) userAccounts.get(username); 237a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair } 238a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair 239a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair /** 240a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair * Return the help text for a command or the default help text if no command name is specified 241a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair * 242a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair * @param name - the command name; may be empty or null to indicate a request for the default help text 243a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair * @return the help text for the named command or the default help text if no name is supplied 244a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair */ 245a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair public String getHelpText(String name) { 246a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair String key = name == null ? "" : name; 247a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair return (String) helpText.get(key); 248a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair } 249a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair 250a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair /** 251a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair * Add a single UserAccount. If an account with the same <code>username</code> already exists, 252a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair * it will be replaced. 253a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair * 254a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair * @param userAccount - the UserAccount to add 255a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair */ 256a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair public void addUserAccount(UserAccount userAccount) { 257a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair userAccounts.put(userAccount.getUsername(), userAccount); 258a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair } 259a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair 260a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair /** 261a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair * Add the UserAccount objects in the <code>userAccountList</code> to the set of UserAccounts. 262a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair * 263a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair * @param userAccountList - the List of UserAccount objects to add 264a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair */ 265a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair public void setUserAccounts(List userAccountList) { 266a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair for (int i = 0; i < userAccountList.size(); i++) { 267a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair UserAccount userAccount = (UserAccount) userAccountList.get(i); 268a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair userAccounts.put(userAccount.getUsername(), userAccount); 269a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair } 270a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair } 271a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair 272a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair /** 273a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair * Return the system status description 274a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair * 275a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair * @return the system status 276a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair */ 277a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair public String getSystemStatus() { 278a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair return systemStatus; 279a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair } 280a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair 281a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair /** 282a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair * Set the system status description text, used by the STAT command handler. 283a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair * 284a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair * @param systemStatus - the system status description text 285a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair */ 286a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair public void setSystemStatus(String systemStatus) { 287a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair this.systemStatus = systemStatus; 288a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair } 289a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair 290a0ad464efff5f5e2d2523a3522cce6823ce05858chrismair}