1ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair/* 2ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair * Copyright 2007 the original author or authors. 3ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair * 4ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair * Licensed under the Apache License, Version 2.0 (the "License"); 5ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair * you may not use this file except in compliance with the License. 6ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair * You may obtain a copy of the License at 7ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair * 8ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair * http://www.apache.org/licenses/LICENSE-2.0 9ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair * 10ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair * Unless required by applicable law or agreed to in writing, software 11ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair * distributed under the License is distributed on an "AS IS" BASIS, 12ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair * See the License for the specific language governing permissions and 14ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair * limitations under the License. 15ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair */ 16ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismairpackage org.mockftpserver.stub.command; 17ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair 18ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismairimport org.mockftpserver.core.command.AbstractCommandHandler; 19ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismairimport org.mockftpserver.core.command.Command; 20ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismairimport org.mockftpserver.core.command.CommandHandler; 21ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismairimport org.mockftpserver.core.command.InvocationRecord; 22ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismairimport org.mockftpserver.core.command.ReplyCodes; 23ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismairimport org.mockftpserver.core.session.Session; 24ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismairimport org.mockftpserver.core.util.AssertFailedException; 25ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair 26ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair/** 27ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair * Abstract superclass for CommandHandlers that read from or write to the data connection. 28ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair * <p/> 29ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair * Return two replies on the control connection: by default a reply code of 150 before the 30ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair * data transfer across the data connection and another reply of 226 after the data transfer 31ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair * is complete. 32ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair * <p/> 33ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair * This class implements the <i>Template Method</i> pattern. Subclasses must implement the abstract 34ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair * {@link #processData()} method to perform read or writes across the data connection. 35ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair * <p/> 36ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair * Subclasses can optionally override the {@link #beforeProcessData(Command, Session, InvocationRecord)} 37ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair * method for logic before the data transfer or the {@link #afterProcessData(Command, Session, InvocationRecord)} 38ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair * method for logic after the data transfer. 39ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair * <p/> 40ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair * Subclasses can optionally override the reply code and/or text for the initial reply (before 41ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair * the data transfer across the data connection) by calling {@link #setPreliminaryReplyCode(int)}, 42ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair * {@link #setPreliminaryReplyMessageKey(String)} and/or {@link #setPreliminaryReplyText(String)} 43ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair * methods. 44ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair * <p/> 45ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair * Subclasses can optionally override the reply code and/or text for the final reply (after the 46ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair * the data transfer is complete) by calling {@link #setFinalReplyCode(int)}, 47ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair * {@link #setFinalReplyMessageKey(String)} and/or {@link #setFinalReplyText(String)} methods. 48ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair * 49ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair * @author Chris Mair 50ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair * @version $Revision$ - $Date$ 51ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair */ 52ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismairpublic abstract class AbstractStubDataCommandHandler extends AbstractCommandHandler implements CommandHandler { 53ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair 54ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair // The completion reply code sent before the data transfer 55ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair protected int preliminaryReplyCode = 0; 56ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair 57ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair // The text for the preliminary reply. If null, use the default message associated with the reply code. 58ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair // If not null, this value overrides the preliminaryReplyMessageKey - i.e., this text is used instead of 59ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair // a localized message. 60ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair protected String preliminaryReplyText = null; 61ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair 62ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair // The message key for the preliminary reply text. If null, use the default message associated with 63ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair // the reply code. 64ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair protected String preliminaryReplyMessageKey = null; 65ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair 66ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair // The completion reply code sent after data transfer 67ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair protected int finalReplyCode = 0; 68ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair 69ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair // The text for the completion reply. If null, use the default message associated with the reply code. 70ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair // If not null, this value overrides the finalReplyMessageKey - i.e., this text is used instead of 71ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair // a localized message. 72ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair protected String finalReplyText = null; 73ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair 74ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair // The message key for the completion reply text. If null, use the default message associated with the reply code 75ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair protected String finalReplyMessageKey = null; 76ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair 77ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair /** 78ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair * Constructor. Initialize the preliminary and final reply code. 79ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair */ 80ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair protected AbstractStubDataCommandHandler() { 81ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair setPreliminaryReplyCode(ReplyCodes.TRANSFER_DATA_INITIAL_OK); 82ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair setFinalReplyCode(ReplyCodes.TRANSFER_DATA_FINAL_OK); 83ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair } 84ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair 85ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair /** 86ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair * Handle the command. Perform the following steps: 87ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair * <ol> 88ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair * <li>Invoke the {@link #beforeProcessData()} method</li> 89ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair * <li>Open the data connection</li> 90ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair * <li>Send an preliminary reply, default reply code 150</li> 91ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair * <li>Invoke the {@link #processData()} method</li> 92ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair * <li>Close the data connection</li> 93ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair * <li>Send the final reply, default reply code 226</li> 94ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair * <li>Invoke the {@link #afterProcessData()} method</li> 95ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair * </ol> 96ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair * 97ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair * @see org.mockftpserver.core.command.CommandHandler#handleCommand(Command, Session, InvocationRecord) 98ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair */ 99ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair public final void handleCommand(Command command, Session session, InvocationRecord invocationRecord) throws Exception { 100ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair 101ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair beforeProcessData(command, session, invocationRecord); 102ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair 103ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair sendPreliminaryReply(session); 104ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair session.openDataConnection(); 105ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair processData(command, session, invocationRecord); 106ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair session.closeDataConnection(); 107ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair sendFinalReply(session); 108ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair 109ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair afterProcessData(command, session, invocationRecord); 110ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair } 111ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair 112ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair /** 113ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair * Send the final reply. The default implementation sends a reply code of 226 with the 114ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair * corresponding associated reply text. 115ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair * 116ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair * @param session - the Session 117ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair */ 118ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair protected void sendFinalReply(Session session) { 119ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair sendReply(session, finalReplyCode, finalReplyMessageKey, finalReplyText, null); 120ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair } 121ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair 122ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair /** 123ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair * Perform any necessary logic before transferring data across the data connection. 124ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair * Do nothing by default. Subclasses should override to validate command parameters and 125ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair * store information in the InvocationRecord. 126ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair * 127ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair * @param command - the Command to be handled 128ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair * @param session - the session on which the Command was submitted 129ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair * @param invocationRecord - the InvocationRecord; CommandHandlers are expected to add 130ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair * handler-specific data to the InvocationRecord, as appropriate 131ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair * @throws Exception 132ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair */ 133ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair protected void beforeProcessData(Command command, Session session, InvocationRecord invocationRecord) throws Exception { 134ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair // Do nothing by default 135ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair } 136ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair 137ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair /** 138ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair * Abstract method placeholder for subclass transfer of data across the data connection. 139ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair * Subclasses must override. The data connection is opened before this method and is 140ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair * closed after this method completes. 141ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair * 142ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair * @param command - the Command to be handled 143ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair * @param session - the session on which the Command was submitted 144ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair * @param invocationRecord - the InvocationRecord; CommandHandlers are expected to add 145ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair * handler-specific data to the InvocationRecord, as appropriate 146ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair * @throws Exception 147ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair */ 148ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair protected abstract void processData(Command command, Session session, InvocationRecord invocationRecord) throws Exception; 149ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair 150ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair /** 151ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair * Perform any necessary logic after transferring data across the data connection. 152ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair * Do nothing by default. 153ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair * 154ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair * @param command - the Command to be handled 155ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair * @param session - the session on which the Command was submitted 156ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair * @param invocationRecord - the InvocationRecord; CommandHandlers are expected to add 157ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair * handler-specific data to the InvocationRecord, as appropriate 158ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair * @throws Exception 159ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair */ 160ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair protected void afterProcessData(Command command, Session session, InvocationRecord invocationRecord) throws Exception { 161ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair // Do nothing by default 162ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair } 163ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair 164ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair /** 165ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair * Send the preliminary reply for this command on the control connection. 166ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair * 167ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair * @param session - the Session 168ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair */ 169ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair private void sendPreliminaryReply(Session session) { 170ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair sendReply(session, preliminaryReplyCode, preliminaryReplyMessageKey, preliminaryReplyText, null); 171ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair } 172ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair 173ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair /** 174ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair * Set the completion reply code sent after data transfer 175ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair * 176ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair * @param finalReplyCode - the final reply code 177ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair * @throws AssertFailedException - if the finalReplyCode is invalid 178ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair */ 179ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair public void setFinalReplyCode(int finalReplyCode) { 180ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair assertValidReplyCode(finalReplyCode); 181ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair this.finalReplyCode = finalReplyCode; 182ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair } 183ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair 184ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair /** 185ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair * Set the message key for the completion reply text sent after data transfer 186ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair * 187ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair * @param finalReplyMessageKey - the final reply message key 188ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair */ 189ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair public void setFinalReplyMessageKey(String finalReplyMessageKey) { 190ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair this.finalReplyMessageKey = finalReplyMessageKey; 191ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair } 192ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair 193ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair /** 194ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair * Set the text of the completion reply sent after data transfer 195ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair * 196ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair * @param finalReplyText - the final reply text 197ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair */ 198ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair public void setFinalReplyText(String finalReplyText) { 199ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair this.finalReplyText = finalReplyText; 200ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair } 201ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair 202ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair /** 203ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair * Set the completion reply code sent before data transfer 204ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair * 205ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair * @param preliminaryReplyCode - the preliminary reply code to set 206ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair * @throws AssertFailedException - if the preliminaryReplyCode is invalid 207ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair */ 208ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair public void setPreliminaryReplyCode(int preliminaryReplyCode) { 209ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair assertValidReplyCode(preliminaryReplyCode); 210ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair this.preliminaryReplyCode = preliminaryReplyCode; 211ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair } 212ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair 213ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair /** 214ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair * Set the message key for the completion reply text sent before data transfer 215ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair * 216ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair * @param preliminaryReplyMessageKey - the preliminary reply message key 217ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair */ 218ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair public void setPreliminaryReplyMessageKey(String preliminaryReplyMessageKey) { 219ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair this.preliminaryReplyMessageKey = preliminaryReplyMessageKey; 220ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair } 221ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair 222ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair /** 223ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair * Set the text of the completion reply sent before data transfer 224ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair * 225ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair * @param preliminaryReplyText - the preliminary reply text 226ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair */ 227ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair public void setPreliminaryReplyText(String preliminaryReplyText) { 228ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair this.preliminaryReplyText = preliminaryReplyText; 229ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair } 230ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair 231ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair} 232