All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.mockftpserver.fake.command.AbstractStoreFileCommandHandler Maven / Gradle / Ivy

/*
 * Copyright 2008 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.mockftpserver.fake.command;

import org.mockftpserver.core.command.Command;
import org.mockftpserver.core.command.ReplyCodes;
import org.mockftpserver.core.session.Session;
import org.mockftpserver.fake.filesystem.FileEntry;
import org.mockftpserver.fake.filesystem.FileSystemException;

import java.io.IOException;
import java.io.OutputStream;

/**
 * Abstract superclass for CommandHandlers that that store a file (STOR, STOU, APPE). Handler logic:
 * 
    *
  1. If the user has not logged in, then reply with 530 and terminate
  2. *
  3. If the pathname parameter is required but missing, then reply with 501 and terminate
  4. *
  5. If the required pathname parameter does not specify a valid filename, then reply with 553 and terminate
  6. *
  7. If the current user does not have write access to the named file, if it already exists, or else to its * parent directory, then reply with 553 and terminate
  8. *
  9. If the current user does not have execute access to the parent directory, then reply with 553 and terminate
  10. *
  11. Send an initial reply of 150
  12. *
  13. Read all available bytes from the data connection and store/append to the named file in the server file system
  14. *
  15. If file write/store fails, then reply with 553 and terminate
  16. *
  17. Send a final reply with 226
  18. *
* * @author Chris Mair * @version $Revision: 201 $ - $Date: 2008-12-11 19:39:48 -0500 (Thu, 11 Dec 2008) $ */ public abstract class AbstractStoreFileCommandHandler extends AbstractFakeCommandHandler { protected void handle(Command command, Session session) { verifyLoggedIn(session); this.replyCodeForFileSystemException = ReplyCodes.WRITE_FILE_ERROR; String filename = getOutputFile(command); String path = getRealPath(session, filename); verifyFileSystemCondition(!getFileSystem().isDirectory(path), path, "filesystem.isDirectory"); String parentPath = getFileSystem().getParent(path); verifyFileSystemCondition(getFileSystem().isDirectory(parentPath), parentPath, "filesystem.isNotADirectory"); // User must have write permission to the file, if an existing file, or else to the directory if a new file String pathMustBeWritable = getFileSystem().exists(path) ? path : parentPath; verifyWritePermission(session, pathMustBeWritable); // User must have execute permission to the parent directory verifyExecutePermission(session, parentPath); sendReply(session, ReplyCodes.TRANSFER_DATA_INITIAL_OK); session.openDataConnection(); byte[] contents = session.readData(); session.closeDataConnection(); FileEntry file = (FileEntry) getFileSystem().getEntry(path); if (file == null) { file = new FileEntry(path); getFileSystem().add(file); } file.setPermissions(getUserAccount(session).getDefaultPermissionsForNewFile()); if (contents != null && contents.length > 0) { OutputStream out = file.createOutputStream(appendToOutputFile()); try { out.write(contents); } catch (IOException e) { LOG.error("Error writing to file [" + file.getPath() + "]", e); throw new FileSystemException(file.getPath(), null, e); } finally { try { out.close(); } catch (IOException e) { LOG.error("Error closing OutputStream for file [" + file.getPath() + "]", e); } } } sendReply(session, ReplyCodes.TRANSFER_DATA_FINAL_OK, getMessageKey(), list(filename)); } /** * Return the path (absolute or relative) for the output file. The default behavior is to return * the required first parameter for the specified Command. Subclasses may override the default behavior. * * @param command - the Command * @return the output file name */ protected String getOutputFile(Command command) { return command.getRequiredParameter(0); } /** * @return true if this command should append the transferred contents to the output file; false means * overwrite an existing file. This default implentation returns false. */ protected boolean appendToOutputFile() { return false; } /** * @return the message key for the reply message sent with the final (226) reply */ protected abstract String getMessageKey(); }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy