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