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