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