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 */ 16package org.mockftpserver.core.command; 17 18import org.mockftpserver.core.session.Session; 19import org.mockftpserver.core.util.Assert; 20import org.mockftpserver.core.util.AssertFailedException; 21 22import java.util.ArrayList; 23import java.util.Iterator; 24import java.util.List; 25import 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 */ 53public 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