177b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair/* 277b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * Copyright 2008 the original author or authors. 377b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * 477b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * Licensed under the Apache License, Version 2.0 (the "License"); 577b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * you may not use this file except in compliance with the License. 677b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * You may obtain a copy of the License at 777b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * 877b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * http://www.apache.org/licenses/LICENSE-2.0 977b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * 1077b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * Unless required by applicable law or agreed to in writing, software 1177b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * distributed under the License is distributed on an "AS IS" BASIS, 1277b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1377b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * See the License for the specific language governing permissions and 1477b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * limitations under the License. 1577b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair */ 1677b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismairpackage org.mockftpserver.fake.filesystem; 1777b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair 1877b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismairimport org.apache.log4j.Logger; 1977b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismairimport org.mockftpserver.core.util.Assert; 2077b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismairimport org.mockftpserver.core.util.PatternUtil; 2177b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismairimport org.mockftpserver.core.util.StringUtil; 2277b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair 2377b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismairimport java.util.ArrayList; 2477b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismairimport java.util.Collections; 2577b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismairimport java.util.Date; 2677b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismairimport java.util.HashMap; 2777b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismairimport java.util.Iterator; 2877b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismairimport java.util.List; 2977b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismairimport java.util.Map; 3077b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair 3177b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair/** 3277b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * Abstract superclass for implementation of the FileSystem interface that manage the files 3377b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * and directories in memory, simulating a real file system. 3477b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * <p/> 3577b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * If the <code>createParentDirectoriesAutomatically</code> property is set to <code>true</code>, 3677b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * then creating a directory or file will automatically create any parent directories (recursively) 3777b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * that do not already exist. If <code>false</code>, then creating a directory or file throws an 3877b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * exception if its parent directory does not exist. This value defaults to <code>true</code>. 3977b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * <p/> 4077b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * The <code>directoryListingFormatter</code> property holds an instance of {@link DirectoryListingFormatter} , 4177b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * used by the <code>formatDirectoryListing</code> method to format directory listings in a 4277b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * filesystem-specific manner. This property must be initialized by concrete subclasses. 4377b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * 4477b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * @author Chris Mair 4577b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * @version $Revision$ - $Date$ 4677b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair */ 4777b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismairpublic abstract class AbstractFakeFileSystem implements FileSystem { 4877b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair 4977b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair private static final Logger LOG = Logger.getLogger(AbstractFakeFileSystem.class); 5077b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair 5177b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair /** 5277b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * If <code>true</code>, creating a directory or file will automatically create 5377b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * any parent directories (recursively) that do not already exist. If <code>false</code>, 5477b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * then creating a directory or file throws an exception if its parent directory 5577b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * does not exist. This value defaults to <code>true</code>. 5677b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair */ 5777b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair private boolean createParentDirectoriesAutomatically = true; 5877b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair 5977b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair /** 6077b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * The {@link DirectoryListingFormatter} used by the {@link #formatDirectoryListing(FileSystemEntry)} 6177b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * method. This must be initialized by concrete subclasses. 6277b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair */ 6377b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair private DirectoryListingFormatter directoryListingFormatter; 6477b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair 6577b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair private Map entries = new HashMap(); 6677b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair 6777b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair //------------------------------------------------------------------------- 6877b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair // Public API 6977b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair //------------------------------------------------------------------------- 7077b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair 7177b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair public boolean isCreateParentDirectoriesAutomatically() { 7277b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair return createParentDirectoriesAutomatically; 7377b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair } 7477b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair 7577b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair public void setCreateParentDirectoriesAutomatically(boolean createParentDirectoriesAutomatically) { 7677b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair this.createParentDirectoriesAutomatically = createParentDirectoriesAutomatically; 7777b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair } 7877b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair 7977b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair public DirectoryListingFormatter getDirectoryListingFormatter() { 8077b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair return directoryListingFormatter; 8177b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair } 8277b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair 8377b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair public void setDirectoryListingFormatter(DirectoryListingFormatter directoryListingFormatter) { 8477b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair this.directoryListingFormatter = directoryListingFormatter; 8577b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair } 8677b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair 8777b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair /** 8877b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * Add each of the entries in the specified List to this filesystem. Note that this does not affect 8977b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * entries already existing within this filesystem. 9077b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * 9177b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * @param entriesToAdd - the List of FileSystemEntry entries to add 9277b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair */ 9377b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair public void setEntries(List entriesToAdd) { 9477b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair for (Iterator iter = entriesToAdd.iterator(); iter.hasNext();) { 9577b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair FileSystemEntry entry = (FileSystemEntry) iter.next(); 9677b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair add(entry); 9777b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair } 9877b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair } 9977b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair 10077b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair /** 10177b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * Add the specified file system entry (file or directory) to this file system 10277b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * 10377b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * @param entry - the FileSystemEntry to add 10477b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair */ 10577b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair public void add(FileSystemEntry entry) { 10677b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair String path = entry.getPath(); 10777b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair checkForInvalidFilename(path); 10877b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair if (getEntry(path) != null) { 10977b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair throw new FileSystemException(path, "filesystem.pathAlreadyExists"); 11077b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair } 11177b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair 11277b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair if (!parentDirectoryExists(path)) { 11377b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair String parent = getParent(path); 11477b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair if (createParentDirectoriesAutomatically) { 11577b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair add(new DirectoryEntry(parent)); 11677b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair } else { 11777b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair throw new FileSystemException(parent, "filesystem.parentDirectoryDoesNotExist"); 11877b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair } 11977b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair } 12077b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair 12177b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair // Set lastModified, if not already set 12277b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair if (entry.getLastModified() == null) { 12377b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair entry.setLastModified(new Date()); 12477b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair } 12577b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair 12677b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair entries.put(getFileSystemEntryKey(path), entry); 12777b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair entry.lockPath(); 12877b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair } 12977b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair 13077b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair /** 13177b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * Delete the file or directory specified by the path. Return true if the file is successfully 13277b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * deleted, false otherwise. If the path refers to a directory, it must be empty. Return false 13377b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * if the path does not refer to a valid file or directory or if it is a non-empty directory. 13477b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * 13577b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * @param path - the path of the file or directory to delete 13677b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * @return true if the file or directory is successfully deleted 13777b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * @throws org.mockftpserver.core.util.AssertFailedException 13877b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * - if path is null 13977b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * @see org.mockftpserver.fake.filesystem.FileSystem#delete(java.lang.String) 14077b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair */ 14177b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair public boolean delete(String path) { 14277b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair Assert.notNull(path, "path"); 14377b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair 14477b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair if (getEntry(path) != null && !hasChildren(path)) { 14577b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair removeEntry(path); 14677b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair return true; 14777b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair } 14877b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair return false; 14977b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair } 15077b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair 15177b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair /** 15277b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * Return true if there exists a file or directory at the specified path 15377b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * 15477b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * @param path - the path 15577b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * @return true if the file/directory exists 15677b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * @throws AssertionError - if path is null 15777b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * @see org.mockftpserver.fake.filesystem.FileSystem#exists(java.lang.String) 15877b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair */ 15977b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair public boolean exists(String path) { 16077b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair Assert.notNull(path, "path"); 16177b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair return getEntry(path) != null; 16277b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair } 16377b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair 16477b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair /** 16577b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * Return true if the specified path designates an existing directory, false otherwise 16677b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * 16777b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * @param path - the path 16877b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * @return true if path is a directory, false otherwise 16977b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * @throws AssertionError - if path is null 17077b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * @see org.mockftpserver.fake.filesystem.FileSystem#isDirectory(java.lang.String) 17177b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair */ 17277b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair public boolean isDirectory(String path) { 17377b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair Assert.notNull(path, "path"); 17477b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair FileSystemEntry entry = getEntry(path); 17577b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair return entry != null && entry.isDirectory(); 17677b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair } 17777b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair 17877b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair /** 17977b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * Return true if the specified path designates an existing file, false otherwise 18077b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * 18177b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * @param path - the path 18277b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * @return true if path is a file, false otherwise 18377b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * @throws AssertionError - if path is null 18477b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * @see org.mockftpserver.fake.filesystem.FileSystem#isFile(java.lang.String) 18577b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair */ 18677b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair public boolean isFile(String path) { 18777b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair Assert.notNull(path, "path"); 18877b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair FileSystemEntry entry = getEntry(path); 18977b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair return entry != null && !entry.isDirectory(); 19077b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair } 19177b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair 19277b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair /** 19377b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * Return the List of FileSystemEntry objects for the files in the specified directory or group of 19477b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * files. If the path specifies a single file, then return a list with a single FileSystemEntry 19577b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * object representing that file. If the path does not refer to an existing directory or 19677b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * group of files, then an empty List is returned. 19777b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * 19877b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * @param path - the path specifying a directory or group of files; may contain wildcards (? or *) 19977b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * @return the List of FileSystemEntry objects for the specified directory or file; may be empty 20077b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * @see org.mockftpserver.fake.filesystem.FileSystem#listFiles(java.lang.String) 20177b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair */ 20277b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair public List listFiles(String path) { 20377b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair if (isFile(path)) { 20477b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair return Collections.singletonList(getEntry(path)); 20577b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair } 20677b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair 20777b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair List entryList = new ArrayList(); 20877b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair List children = children(path); 20977b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair Iterator iter = children.iterator(); 21077b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair while (iter.hasNext()) { 21177b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair String childPath = (String) iter.next(); 21277b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair FileSystemEntry fileSystemEntry = getEntry(childPath); 21377b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair entryList.add(fileSystemEntry); 21477b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair } 21577b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair return entryList; 21677b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair } 21777b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair 21877b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair /** 21977b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * Return the List of filenames in the specified directory path or file path. If the path specifies 22077b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * a single file, then return that single filename. The returned filenames do not 22177b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * include a path. If the path does not refer to a valid directory or file path, then an empty List 22277b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * is returned. 22377b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * 22477b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * @param path - the path specifying a directory or group of files; may contain wildcards (? or *) 22577b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * @return the List of filenames (not including paths) for all files in the specified directory 22677b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * or file path; may be empty 22777b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * @throws AssertionError - if path is null 22877b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * @see org.mockftpserver.fake.filesystem.FileSystem#listNames(java.lang.String) 22977b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair */ 23077b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair public List listNames(String path) { 23177b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair if (isFile(path)) { 23277b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair return Collections.singletonList(getName(path)); 23377b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair } 23477b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair 23577b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair List filenames = new ArrayList(); 23677b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair List children = children(path); 23777b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair Iterator iter = children.iterator(); 23877b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair while (iter.hasNext()) { 23977b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair String childPath = (String) iter.next(); 24077b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair FileSystemEntry fileSystemEntry = getEntry(childPath); 24177b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair filenames.add(fileSystemEntry.getName()); 24277b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair } 24377b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair return filenames; 24477b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair } 24577b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair 24677b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair /** 24777b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * Rename the file or directory. Specify the FROM path and the TO path. Throw an exception if the FROM path or 24877b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * the parent directory of the TO path do not exist; or if the rename fails for another reason. 24977b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * 25077b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * @param fromPath - the source (old) path + filename 25177b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * @param toPath - the target (new) path + filename 25277b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * @throws AssertionError - if fromPath or toPath is null 25377b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * @throws FileSystemException - if the rename fails. 25477b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair */ 25577b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair public void rename(String fromPath, String toPath) { 25677b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair Assert.notNull(toPath, "toPath"); 25777b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair Assert.notNull(fromPath, "fromPath"); 25877b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair 25977b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair FileSystemEntry entry = getRequiredEntry(fromPath); 26077b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair 26177b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair String normalizedFromPath = normalize(fromPath); 26277b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair String normalizedToPath = normalize(toPath); 26377b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair 26477b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair if (!entry.isDirectory()) { 26577b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair renamePath(entry, normalizedToPath); 26677b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair return; 26777b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair } 26877b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair 26977b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair // Create the TO directory entry first so that the destination path exists when you 27077b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair // move the children. Remove the FROM path after all children have been moved 27177b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair add(new DirectoryEntry(normalizedToPath)); 27277b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair 27377b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair List children = descendents(fromPath); 27477b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair Iterator iter = children.iterator(); 27577b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair while (iter.hasNext()) { 27677b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair String childPath = (String) iter.next(); 27777b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair FileSystemEntry child = getRequiredEntry(childPath); 27877b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair String normalizedChildPath = normalize(child.getPath()); 27977b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair Assert.isTrue(normalizedChildPath.startsWith(normalizedFromPath), "Starts with FROM path"); 28077b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair String childToPath = normalizedToPath + normalizedChildPath.substring(normalizedFromPath.length()); 28177b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair renamePath(child, childToPath); 28277b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair } 28377b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair Assert.isTrue(children(normalizedFromPath).isEmpty(), "Must have no children: " + normalizedFromPath); 28477b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair removeEntry(normalizedFromPath); 28577b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair } 28677b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair 28777b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair /** 28877b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * @see java.lang.Object#toString() 28977b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair */ 29077b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair public String toString() { 29177b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair return this.getClass().getName() + entries; 29277b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair } 29377b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair 29477b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair /** 29577b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * Return the formatted directory listing entry for the file represented by the specified FileSystemEntry 29677b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * 29777b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * @param fileSystemEntry - the FileSystemEntry representing the file or directory entry to be formatted 29877b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * @return the the formatted directory listing entry 29977b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair */ 30077b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair public String formatDirectoryListing(FileSystemEntry fileSystemEntry) { 30177b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair Assert.notNull(directoryListingFormatter, "directoryListingFormatter"); 30277b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair Assert.notNull(fileSystemEntry, "fileSystemEntry"); 30377b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair return directoryListingFormatter.format(fileSystemEntry); 30477b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair } 30577b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair 30677b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair /** 30777b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * Build a path from the two path components. Concatenate path1 and path2. Insert the path 30877b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * separator character in between if necessary (i.e., if both are non-empty and path1 does not already 30977b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * end with a separator character AND path2 does not begin with one). 31077b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * 31177b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * @param path1 - the first path component may be null or empty 31277b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * @param path2 - the second path component may be null or empty 31377b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * @return the normalized path resulting from concatenating path1 to path2 31477b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair */ 31577b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair public String path(String path1, String path2) { 31677b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair StringBuffer buf = new StringBuffer(); 31777b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair if (path1 != null && path1.length() > 0) { 31877b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair buf.append(path1); 31977b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair } 32077b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair if (path2 != null && path2.length() > 0) { 32177b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair if ((path1 != null && path1.length() > 0) 32277b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair && (!isSeparator(path1.charAt(path1.length() - 1))) 32377b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair && (!isSeparator(path2.charAt(0)))) { 32477b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair buf.append(this.getSeparator()); 32577b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair } 32677b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair buf.append(path2); 32777b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair } 32877b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair return normalize(buf.toString()); 32977b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair } 33077b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair 33177b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair /** 33277b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * Return the parent path of the specified path. If <code>path</code> specifies a filename, 33377b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * then this method returns the path of the directory containing that file. If <code>path</code> 33477b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * specifies a directory, the this method returns its parent directory. If <code>path</code> is 33577b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * empty or does not have a parent component, then return an empty string. 33677b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * <p/> 33777b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * All path separators in the returned path are converted to the system-dependent separator character. 33877b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * 33977b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * @param path - the path 34077b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * @return the parent of the specified path, or null if <code>path</code> has no parent 34177b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * @throws AssertionError - if path is null 34277b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair */ 34377b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair public String getParent(String path) { 34477b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair List parts = normalizedComponents(path); 34577b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair if (parts.size() < 2) { 34677b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair return null; 34777b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair } 34877b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair parts.remove(parts.size() - 1); 34977b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair return componentsToPath(parts); 35077b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair } 35177b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair 35277b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair /** 35377b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * Returns the name of the file or directory denoted by this abstract 35477b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * pathname. This is just the last name in the pathname's name 35577b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * sequence. If the pathname's name sequence is empty, then the empty string is returned. 35677b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * 35777b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * @param path - the path 35877b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * @return The name of the file or directory denoted by this abstract pathname, or the 35977b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * empty string if this pathname's name sequence is empty 36077b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair */ 36177b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair public String getName(String path) { 36277b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair Assert.notNull(path, "path"); 36377b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair String normalized = normalize(path); 36477b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair int separatorIndex = normalized.lastIndexOf(this.getSeparator()); 36577b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair return (separatorIndex == -1) ? normalized : normalized.substring(separatorIndex + 1); 36677b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair } 36777b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair 36877b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair /** 36977b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * Returns the FileSystemEntry object representing the file system entry at the specified path, or null 37077b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * if the path does not specify an existing file or directory within this file system. 37177b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * 37277b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * @param path - the path of the file or directory within this file system 37377b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * @return the FileSystemEntry containing the information for the file or directory, or else null 37477b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * @see FileSystem#getEntry(String) 37577b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair */ 37677b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair public FileSystemEntry getEntry(String path) { 37777b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair return (FileSystemEntry) entries.get(getFileSystemEntryKey(path)); 37877b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair } 37977b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair 38077b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair //------------------------------------------------------------------------- 38177b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair // Abstract Methods 38277b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair //------------------------------------------------------------------------- 38377b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair 38477b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair /** 38577b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * @param path - the path 38677b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * @return true if the specified dir/file path name is valid according to the current filesystem. 38777b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair */ 38877b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair protected abstract boolean isValidName(String path); 38977b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair 39077b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair /** 39177b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * @return the file system-specific file separator as a char 39277b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair */ 39377b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair protected abstract char getSeparatorChar(); 39477b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair 39577b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair /** 39677b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * @param pathComponent - the component (piece) of the path to check 39777b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * @return true if the specified path component is a root for this filesystem 39877b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair */ 39977b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair protected abstract boolean isRoot(String pathComponent); 40077b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair 40177b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair /** 40277b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * Return true if the specified char is a separator character for this filesystem 40377b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * 40477b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * @param c - the character to test 40577b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * @return true if the specified char is a separator character 40677b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair */ 40777b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair protected abstract boolean isSeparator(char c); 40877b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair 40977b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair //------------------------------------------------------------------------- 41077b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair // Internal Helper Methods 41177b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair //------------------------------------------------------------------------- 41277b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair 41377b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair /** 41477b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * @return the file system-specific file separator as a String 41577b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair */ 41677b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair protected String getSeparator() { 41777b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair return Character.toString(getSeparatorChar()); 41877b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair } 41977b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair 42077b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair /** 42177b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * Return the normalized and unique key used to access the file system entry 42277b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * 42377b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * @param path - the path 42477b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * @return the corresponding normalized key 42577b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair */ 42677b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair protected String getFileSystemEntryKey(String path) { 42777b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair return normalize(path); 42877b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair } 42977b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair 43077b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair /** 43177b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * Return the standard, normalized form of the path. 43277b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * 43377b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * @param path - the path 43477b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * @return the path in a standard, unique, canonical form 43577b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * @throws AssertionError - if path is null 43677b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair */ 43777b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair protected String normalize(String path) { 43877b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair return componentsToPath(normalizedComponents(path)); 43977b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair } 44077b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair 44177b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair /** 44277b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * Throw an InvalidFilenameException if the specified path is not valid. 44377b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * 44477b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * @param path - the path 44577b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair */ 44677b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair protected void checkForInvalidFilename(String path) { 44777b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair if (!isValidName(path)) { 44877b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair throw new InvalidFilenameException(path); 44977b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair } 45077b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair } 45177b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair 45277b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair /** 45377b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * Rename the file system entry to the specified path name 45477b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * 45577b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * @param entry - the file system entry 45677b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * @param toPath - the TO path (normalized) 45777b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair */ 45877b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair protected void renamePath(FileSystemEntry entry, String toPath) { 45977b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair String normalizedFrom = normalize(entry.getPath()); 46077b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair String normalizedTo = normalize(toPath); 46177b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair LOG.info("renaming from [" + normalizedFrom + "] to [" + normalizedTo + "]"); 46277b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair FileSystemEntry newEntry = entry.cloneWithNewPath(normalizedTo); 46377b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair add(newEntry); 46477b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair // Do this at the end, in case the addEntry() failed 46577b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair removeEntry(normalizedFrom); 46677b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair } 46777b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair 46877b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair /** 46977b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * Return the FileSystemEntry for the specified path. Throw FileSystemException if the 47077b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * specified path does not exist. 47177b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * 47277b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * @param path - the path 47377b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * @return the FileSystemEntry 47477b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * @throws FileSystemException - if the specified path does not exist 47577b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair */ 47677b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair protected FileSystemEntry getRequiredEntry(String path) { 47777b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair FileSystemEntry entry = getEntry(path); 47877b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair if (entry == null) { 47977b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair LOG.error("Path does not exist: " + path); 48077b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair throw new FileSystemException(normalize(path), "filesystem.doesNotExist"); 48177b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair } 48277b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair return entry; 48377b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair } 48477b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair 48577b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair /** 48677b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * Return the components of the specified path as a List. The components are normalized, and 48777b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * the returned List does not include path separator characters. 48877b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * 48977b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * @param path - the path 49077b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * @return the List of normalized components 49177b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair */ 49277b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair protected List normalizedComponents(String path) { 49377b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair Assert.notNull(path, "path"); 49477b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair char otherSeparator = this.getSeparatorChar() == '/' ? '\\' : '/'; 49577b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair String p = path.replace(otherSeparator, this.getSeparatorChar()); 49677b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair 49777b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair // TODO better way to do this 49877b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair if (p.equals(this.getSeparator())) { 49977b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair return Collections.singletonList(""); 50077b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair } 50177b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair List result = new ArrayList(); 50277b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair if (p.length() > 0) { 50377b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair String[] parts = p.split("\\" + this.getSeparator()); 50477b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair for (int i = 0; i < parts.length; i++) { 50577b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair String part = parts[i]; 50677b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair if (part.equals("..")) { 50777b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair result.remove(result.size() - 1); 50877b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair } else if (!part.equals(".")) { 50977b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair result.add(part); 51077b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair } 51177b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair } 51277b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair } 51377b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair return result; 51477b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair } 51577b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair 51677b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair /** 51777b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * Build a path from the specified list of path components 51877b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * 51977b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * @param components - the list of path components 52077b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * @return the resulting path 52177b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair */ 52277b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair protected String componentsToPath(List components) { 52377b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair if (components.size() == 1) { 52477b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair String first = (String) components.get(0); 52577b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair if (first.length() == 0 || isRoot(first)) { 52677b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair return first + this.getSeparator(); 52777b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair } 52877b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair } 52977b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair return StringUtil.join(components, this.getSeparator()); 53077b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair } 53177b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair 53277b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair /** 53377b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * Return true if the specified path designates an absolute file path. 53477b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * 53577b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * @param path - the path 53677b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * @return true if path is absolute, false otherwise 53777b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * @throws AssertionError - if path is null 53877b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair */ 53977b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair public boolean isAbsolute(String path) { 54077b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair return isValidName(path); 54177b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair } 54277b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair 54377b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair /** 54477b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * Return true if the specified path exists 54577b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * 54677b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * @param path - the path 54777b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * @return true if the path exists 54877b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair */ 54977b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair private boolean pathExists(String path) { 55077b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair return getEntry(path) != null; 55177b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair } 55277b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair 55377b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair /** 55477b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * If the specified path has a parent, then verify that the parent exists 55577b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * 55677b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * @param path - the path 55777b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * @return true if the parent of the specified path exists 55877b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair */ 55977b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair private boolean parentDirectoryExists(String path) { 56077b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair String parent = getParent(path); 56177b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair return parent == null || pathExists(parent); 56277b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair } 56377b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair 56477b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair /** 56577b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * Return true if the specified path represents a directory that contains one or more files or subdirectories 56677b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * 56777b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * @param path - the path 56877b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * @return true if the path has child entries 56977b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair */ 57077b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair private boolean hasChildren(String path) { 57177b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair if (!isDirectory(path)) { 57277b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair return false; 57377b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair } 57477b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair String key = getFileSystemEntryKey(path); 57577b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair Iterator iter = entries.keySet().iterator(); 57677b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair while (iter.hasNext()) { 57777b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair String p = (String) iter.next(); 57877b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair if (p.startsWith(key) && !key.equals(p)) { 57977b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair return true; 58077b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair } 58177b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair } 58277b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair return false; 58377b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair } 58477b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair 58577b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair /** 58677b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * Return the List of files or subdirectory paths that are descendents of the specified path 58777b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * 58877b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * @param path - the path 58977b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * @return the List of the paths for the files and subdirectories that are children, grandchildren, etc. 59077b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair */ 59177b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair private List descendents(String path) { 59277b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair if (isDirectory(path)) { 59377b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair String normalizedPath = getFileSystemEntryKey(path); 59477b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair String separator = (normalizedPath.endsWith(getSeparator())) ? "" : getSeparator(); 59577b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair String normalizedDirPrefix = normalizedPath + separator; 59677b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair List descendents = new ArrayList(); 59777b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair Iterator iter = entries.entrySet().iterator(); 59877b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair while (iter.hasNext()) { 59977b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair Map.Entry mapEntry = (Map.Entry) iter.next(); 60077b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair String p = (String) mapEntry.getKey(); 60177b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair if (p.startsWith(normalizedDirPrefix) && !normalizedPath.equals(p)) { 60277b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair FileSystemEntry fileSystemEntry = (FileSystemEntry) mapEntry.getValue(); 60377b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair descendents.add(fileSystemEntry.getPath()); 60477b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair } 60577b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair } 60677b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair return descendents; 60777b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair } 60877b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair return Collections.EMPTY_LIST; 60977b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair } 61077b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair 61177b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair /** 61277b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * Return the List of files or subdirectory paths that are children of the specified path 61377b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * 61477b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * @param path - the path 61577b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair * @return the List of the paths for the files and subdirectories that are children 61677b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair */ 61777b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair private List children(String path) { 61877b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair String lastComponent = getName(path); 61977b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair boolean containsWildcards = PatternUtil.containsWildcards(lastComponent); 62077b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair String dir = containsWildcards ? getParent(path) : path; 62177b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair String pattern = containsWildcards ? PatternUtil.convertStringWithWildcardsToRegex(getName(path)) : null; 62277b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair LOG.debug("path=" + path + " lastComponent=" + lastComponent + " containsWildcards=" + containsWildcards + " dir=" + dir + " pattern=" + pattern); 62377b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair 62477b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair List descendents = descendents(dir); 62577b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair List children = new ArrayList(); 62677b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair String normalizedDir = normalize(dir); 62777b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair Iterator iter = descendents.iterator(); 62877b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair while (iter.hasNext()) { 62977b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair String descendentPath = (String) iter.next(); 63077b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair 63177b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair boolean patternEmpty = pattern == null || pattern.length() == 0; 63277b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair if (normalizedDir.equals(getParent(descendentPath)) && 63377b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair (patternEmpty || (getName(descendentPath).matches(pattern)))) { 63477b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair children.add(descendentPath); 63577b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair } 63677b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair } 63777b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair return children; 63877b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair } 63977b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair 64077b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair private void removeEntry(String path) { 64177b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair entries.remove(getFileSystemEntryKey(path)); 64277b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair } 64377b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair 64477b8661f08d1379c0bdf2af93d8004fced9f1ab0chrismair}