Home | History | Annotate | Download | only in command
      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.core.command;
     17 
     18 import org.mockftpserver.core.session.Session;
     19 import org.mockftpserver.core.util.Assert;
     20 import org.mockftpserver.core.util.AssertFailedException;
     21 
     22 import java.util.ArrayList;
     23 import java.util.Iterator;
     24 import java.util.List;
     25 import java.util.ResourceBundle;
     26 
     27 /**
     28  * Composite CommandHandler that manages an internal list of CommandHandlers to which it delegates.
     29  * The internal CommandHandlers are maintained in an ordered list. Starting with the first
     30  * CommandHandler in the list, each invocation of this composite handler will invoke (delegate to)
     31  * the current internal CommandHander. Then it moves on the next CommandHandler in the internal list.
     32  * <p>
     33  * The following example replaces the CWD CommandHandler with a <code>SimpleCompositeCommandHandler</code>.
     34  * The first invocation of the CWD command will fail (reply code 500). The seconds will succeed.
     35  * <pre><code>
     36  *
     37  * StubFtpServer stubFtpServer = new StubFtpServer();
     38  *
     39  * CommandHandler commandHandler1 = new StaticReplyCommandHandler(500);
     40  * CommandHandler commandHandler2 = new CwdCommandHandler();
     41  *
     42  * SimpleCompositeCommandHandler simpleCompositeCommandHandler = new SimpleCompositeCommandHandler();
     43  * simpleCompositeCommandHandler.addCommandHandler(commandHandler1);
     44  * simpleCompositeCommandHandler.addCommandHandler(commandHandler2);
     45  *
     46  * stubFtpServer.setCommandHandler("CWD", simpleCompositeCommandHandler);
     47  * </code></pre>
     48  *
     49  * @version $Revision$ - $Date$
     50  *
     51  * @author Chris Mair
     52  */
     53 public final class SimpleCompositeCommandHandler implements CommandHandler, ReplyTextBundleAware {
     54 
     55     private List commandHandlers = new ArrayList();
     56     private int invocationIndex = 0;
     57 
     58     /**
     59      * Add a CommandHandler to the internal list of handlers.
     60      *
     61      * @param commandHandler - the CommandHandler
     62      *
     63      * @throws AssertFailedException - if the commandHandler is null
     64      */
     65     public void addCommandHandler(CommandHandler commandHandler) {
     66         Assert.notNull(commandHandler, "commandHandler");
     67         commandHandlers.add(commandHandler);
     68     }
     69 
     70     /**
     71      * Set the List of CommandHandlers to which to delegate. This replaces any CommandHandlers that
     72      * have been defined previously.
     73      * @param commandHandlers - the complete List of CommandHandlers to which invocations are delegated
     74      */
     75     public void setCommandHandlers(List commandHandlers) {
     76         Assert.notNull(commandHandlers, "commandHandlers");
     77         this.commandHandlers = new ArrayList(commandHandlers);
     78     }
     79 
     80     /**
     81      * Return the CommandHandler corresponding to the specified invocation index. In other words, return
     82      * the CommandHandler instance to which the Nth {@link #handleCommand(Command, Session)} has been or will
     83      * be delegated (where N=index).
     84      * @param index - the index of the desired invocation (zero-based).
     85      * @return the CommandHandler
     86      *
     87      * @throws AssertFailedException - if no CommandHandler is defined for the index or the index is not valid
     88      */
     89     public CommandHandler getCommandHandler(int index) {
     90         Assert.isTrue(index < commandHandlers.size(), "No CommandHandler defined for index " + index);
     91         Assert.isTrue(index >= 0, "The index cannot be less than zero: " + index);
     92         return (CommandHandler) commandHandlers.get(index);
     93     }
     94 
     95     /**
     96      * @see org.mockftpserver.core.command.CommandHandler#handleCommand(org.mockftpserver.core.command.Command, org.mockftpserver.core.session.Session)
     97      */
     98     public void handleCommand(Command command, Session session) throws Exception {
     99         Assert.notNull(command, "command");
    100         Assert.notNull(session, "session");
    101         Assert.isTrue(commandHandlers.size() > invocationIndex, "No CommandHandler defined for invocation #" + invocationIndex);
    102 
    103         CommandHandler commandHandler = (CommandHandler) commandHandlers.get(invocationIndex);
    104         invocationIndex++;
    105         commandHandler.handleCommand(command, session);
    106     }
    107 
    108     /**
    109      * Returns null. This is a composite, and has no reply text bundle.
    110      *
    111      * @see org.mockftpserver.core.command.ReplyTextBundleAware#getReplyTextBundle()
    112      */
    113     public ResourceBundle getReplyTextBundle() {
    114         return null;
    115     }
    116 
    117     /**
    118      * Call <code>setReplyTextBundle()</code> on each of the command handlers within the internal list.
    119      *
    120      * @see org.mockftpserver.core.command.ReplyTextBundleAware#setReplyTextBundle(java.util.ResourceBundle)
    121      */
    122     public void setReplyTextBundle(ResourceBundle replyTextBundle) {
    123         for (Iterator iter = commandHandlers.iterator(); iter.hasNext();) {
    124             CommandHandler commandHandler = (CommandHandler) iter.next();
    125             ReplyTextBundleUtil.setReplyTextBundleIfAppropriate(commandHandler, replyTextBundle);
    126         }
    127     }
    128 
    129 }
    130