153295844df24dff0a1f59e1104795e640b54c2efchrismair/* 253295844df24dff0a1f59e1104795e640b54c2efchrismair * Copyright 2007 the original author or authors. 353295844df24dff0a1f59e1104795e640b54c2efchrismair * 453295844df24dff0a1f59e1104795e640b54c2efchrismair * Licensed under the Apache License, Version 2.0 (the "License"); 553295844df24dff0a1f59e1104795e640b54c2efchrismair * you may not use this file except in compliance with the License. 653295844df24dff0a1f59e1104795e640b54c2efchrismair * You may obtain a copy of the License at 753295844df24dff0a1f59e1104795e640b54c2efchrismair * 853295844df24dff0a1f59e1104795e640b54c2efchrismair * http://www.apache.org/licenses/LICENSE-2.0 953295844df24dff0a1f59e1104795e640b54c2efchrismair * 1053295844df24dff0a1f59e1104795e640b54c2efchrismair * Unless required by applicable law or agreed to in writing, software 1153295844df24dff0a1f59e1104795e640b54c2efchrismair * distributed under the License is distributed on an "AS IS" BASIS, 1253295844df24dff0a1f59e1104795e640b54c2efchrismair * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1353295844df24dff0a1f59e1104795e640b54c2efchrismair * See the License for the specific language governing permissions and 1453295844df24dff0a1f59e1104795e640b54c2efchrismair * limitations under the License. 1553295844df24dff0a1f59e1104795e640b54c2efchrismair */ 1653295844df24dff0a1f59e1104795e640b54c2efchrismairpackage org.mockftpserver.stub.command; 1753295844df24dff0a1f59e1104795e640b54c2efchrismair 1853295844df24dff0a1f59e1104795e640b54c2efchrismairimport java.io.IOException; 1953295844df24dff0a1f59e1104795e640b54c2efchrismairimport java.io.InputStream; 2053295844df24dff0a1f59e1104795e640b54c2efchrismair 2153295844df24dff0a1f59e1104795e640b54c2efchrismair 2253295844df24dff0a1f59e1104795e640b54c2efchrismairimport org.apache.log4j.Logger; 2353295844df24dff0a1f59e1104795e640b54c2efchrismairimport org.mockftpserver.core.MockFtpServerException; 2453295844df24dff0a1f59e1104795e640b54c2efchrismairimport org.mockftpserver.core.command.Command; 2553295844df24dff0a1f59e1104795e640b54c2efchrismairimport org.mockftpserver.core.command.CommandHandler; 2653295844df24dff0a1f59e1104795e640b54c2efchrismairimport org.mockftpserver.core.command.InvocationRecord; 2753295844df24dff0a1f59e1104795e640b54c2efchrismairimport org.mockftpserver.core.session.Session; 2853295844df24dff0a1f59e1104795e640b54c2efchrismairimport org.mockftpserver.core.util.Assert; 2953295844df24dff0a1f59e1104795e640b54c2efchrismairimport org.mockftpserver.core.util.AssertFailedException; 3053295844df24dff0a1f59e1104795e640b54c2efchrismair 3153295844df24dff0a1f59e1104795e640b54c2efchrismair/** 3253295844df24dff0a1f59e1104795e640b54c2efchrismair * CommandHandler for the RETR command. Returns the contents of the specified file on the 3353295844df24dff0a1f59e1104795e640b54c2efchrismair * data connection, along with two replies on the control connection: a reply code of 150 and 3453295844df24dff0a1f59e1104795e640b54c2efchrismair * another of 226. 3553295844df24dff0a1f59e1104795e640b54c2efchrismair * <p> 3653295844df24dff0a1f59e1104795e640b54c2efchrismair * The <code>file</code> property specifies the pathname for the file whose contents should 3753295844df24dff0a1f59e1104795e640b54c2efchrismair * be returned from this command. The file path is relative to the CLASSPATH (using the 3853295844df24dff0a1f59e1104795e640b54c2efchrismair * ClassLoader for this class). 3953295844df24dff0a1f59e1104795e640b54c2efchrismair * <p> 4053295844df24dff0a1f59e1104795e640b54c2efchrismair * An exception is thrown if the <code>file</code> property has not been set or if the specified 4153295844df24dff0a1f59e1104795e640b54c2efchrismair * file does not exist or cannot be read. 4253295844df24dff0a1f59e1104795e640b54c2efchrismair * <p> 4353295844df24dff0a1f59e1104795e640b54c2efchrismair * Each invocation record stored by this CommandHandler includes the following data element key/values: 4453295844df24dff0a1f59e1104795e640b54c2efchrismair * <ul> 4553295844df24dff0a1f59e1104795e640b54c2efchrismair * <li>{@link #PATHNAME_KEY} ("pathname") - the pathname of the file submitted on the invocation (the first command parameter) 4653295844df24dff0a1f59e1104795e640b54c2efchrismair * </ul> 4753295844df24dff0a1f59e1104795e640b54c2efchrismair * 4853295844df24dff0a1f59e1104795e640b54c2efchrismair * @version $Revision$ - $Date$ 4953295844df24dff0a1f59e1104795e640b54c2efchrismair * 5053295844df24dff0a1f59e1104795e640b54c2efchrismair * @author Chris Mair 5153295844df24dff0a1f59e1104795e640b54c2efchrismair */ 5253295844df24dff0a1f59e1104795e640b54c2efchrismairpublic final class FileRetrCommandHandler extends AbstractStubDataCommandHandler implements CommandHandler { 5353295844df24dff0a1f59e1104795e640b54c2efchrismair 5453295844df24dff0a1f59e1104795e640b54c2efchrismair public static final String PATHNAME_KEY = "pathname"; 5553295844df24dff0a1f59e1104795e640b54c2efchrismair static final int BUFFER_SIZE = 512; // package-private for testing 5653295844df24dff0a1f59e1104795e640b54c2efchrismair private static final Logger LOG = Logger.getLogger(FileRetrCommandHandler.class); 5753295844df24dff0a1f59e1104795e640b54c2efchrismair 5853295844df24dff0a1f59e1104795e640b54c2efchrismair private String file; 5953295844df24dff0a1f59e1104795e640b54c2efchrismair 6053295844df24dff0a1f59e1104795e640b54c2efchrismair /** 6153295844df24dff0a1f59e1104795e640b54c2efchrismair * Create new uninitialized instance 6253295844df24dff0a1f59e1104795e640b54c2efchrismair */ 6353295844df24dff0a1f59e1104795e640b54c2efchrismair public FileRetrCommandHandler() { 6453295844df24dff0a1f59e1104795e640b54c2efchrismair } 6553295844df24dff0a1f59e1104795e640b54c2efchrismair 6653295844df24dff0a1f59e1104795e640b54c2efchrismair /** 6753295844df24dff0a1f59e1104795e640b54c2efchrismair * Create new instance using the specified file pathname 6853295844df24dff0a1f59e1104795e640b54c2efchrismair * @param file - the path to the file 6953295844df24dff0a1f59e1104795e640b54c2efchrismair * @throws AssertFailedException - if the file is null 7053295844df24dff0a1f59e1104795e640b54c2efchrismair */ 7153295844df24dff0a1f59e1104795e640b54c2efchrismair public FileRetrCommandHandler(String file) { 7253295844df24dff0a1f59e1104795e640b54c2efchrismair setFile(file); 7353295844df24dff0a1f59e1104795e640b54c2efchrismair } 7453295844df24dff0a1f59e1104795e640b54c2efchrismair 7553295844df24dff0a1f59e1104795e640b54c2efchrismair /** 7653295844df24dff0a1f59e1104795e640b54c2efchrismair * @see org.mockftpserver.stub.command.AbstractStubDataCommandHandler#beforeProcessData(org.mockftpserver.core.command.Command, org.mockftpserver.core.session.Session, org.mockftpserver.core.command.InvocationRecord) 7753295844df24dff0a1f59e1104795e640b54c2efchrismair */ 7853295844df24dff0a1f59e1104795e640b54c2efchrismair protected void beforeProcessData(Command command, Session session, InvocationRecord invocationRecord) throws Exception { 7953295844df24dff0a1f59e1104795e640b54c2efchrismair Assert.notNull(file, "file"); 8053295844df24dff0a1f59e1104795e640b54c2efchrismair invocationRecord.set(PATHNAME_KEY, command.getRequiredString(0)); 8153295844df24dff0a1f59e1104795e640b54c2efchrismair } 8253295844df24dff0a1f59e1104795e640b54c2efchrismair 8353295844df24dff0a1f59e1104795e640b54c2efchrismair /** 8453295844df24dff0a1f59e1104795e640b54c2efchrismair * @see org.mockftpserver.stub.command.AbstractStubDataCommandHandler#processData(org.mockftpserver.core.command.Command, org.mockftpserver.core.session.Session, org.mockftpserver.core.command.InvocationRecord) 8553295844df24dff0a1f59e1104795e640b54c2efchrismair */ 8653295844df24dff0a1f59e1104795e640b54c2efchrismair protected void processData(Command command, Session session, InvocationRecord invocationRecord) { 8753295844df24dff0a1f59e1104795e640b54c2efchrismair InputStream inputStream = getClass().getClassLoader().getResourceAsStream(file); 8853295844df24dff0a1f59e1104795e640b54c2efchrismair Assert.notNull(inputStream, "InputStream for [" + file + "]"); 8953295844df24dff0a1f59e1104795e640b54c2efchrismair byte[] buffer = new byte[BUFFER_SIZE]; 9053295844df24dff0a1f59e1104795e640b54c2efchrismair try { 9153295844df24dff0a1f59e1104795e640b54c2efchrismair int numBytes = 0; 9253295844df24dff0a1f59e1104795e640b54c2efchrismair while ((numBytes = inputStream.read(buffer)) != -1) { 9353295844df24dff0a1f59e1104795e640b54c2efchrismair LOG.trace("Sending " + numBytes + " bytes..."); 9453295844df24dff0a1f59e1104795e640b54c2efchrismair session.sendData(buffer, numBytes); 9553295844df24dff0a1f59e1104795e640b54c2efchrismair } 9653295844df24dff0a1f59e1104795e640b54c2efchrismair } 9753295844df24dff0a1f59e1104795e640b54c2efchrismair catch(IOException e) { 9853295844df24dff0a1f59e1104795e640b54c2efchrismair throw new MockFtpServerException(e); 9953295844df24dff0a1f59e1104795e640b54c2efchrismair } 10053295844df24dff0a1f59e1104795e640b54c2efchrismair } 10153295844df24dff0a1f59e1104795e640b54c2efchrismair 10253295844df24dff0a1f59e1104795e640b54c2efchrismair /** 10353295844df24dff0a1f59e1104795e640b54c2efchrismair * Set the path of the file whose contents should be returned when this command is 10453295844df24dff0a1f59e1104795e640b54c2efchrismair * invoked. The path is relative to the CLASSPATH. 10553295844df24dff0a1f59e1104795e640b54c2efchrismair * @param file - the path to the file 10653295844df24dff0a1f59e1104795e640b54c2efchrismair * @throws AssertFailedException - if the file is null 10753295844df24dff0a1f59e1104795e640b54c2efchrismair */ 10853295844df24dff0a1f59e1104795e640b54c2efchrismair public void setFile(String file) { 10953295844df24dff0a1f59e1104795e640b54c2efchrismair Assert.notNull(file, "file"); 11053295844df24dff0a1f59e1104795e640b54c2efchrismair this.file = file; 11153295844df24dff0a1f59e1104795e640b54c2efchrismair } 11253295844df24dff0a1f59e1104795e640b54c2efchrismair 11353295844df24dff0a1f59e1104795e640b54c2efchrismair} 114