1fba2635c088b01af59300e8a02611bb788ee3bffchrismair/* 2fba2635c088b01af59300e8a02611bb788ee3bffchrismair * Copyright 2008 the original author or authors. 3fba2635c088b01af59300e8a02611bb788ee3bffchrismair * 4fba2635c088b01af59300e8a02611bb788ee3bffchrismair * Licensed under the Apache License, Version 2.0 (the "License"); 5fba2635c088b01af59300e8a02611bb788ee3bffchrismair * you may not use this file except in compliance with the License. 6fba2635c088b01af59300e8a02611bb788ee3bffchrismair * You may obtain a copy of the License at 7fba2635c088b01af59300e8a02611bb788ee3bffchrismair * 8fba2635c088b01af59300e8a02611bb788ee3bffchrismair * http://www.apache.org/licenses/LICENSE-2.0 9fba2635c088b01af59300e8a02611bb788ee3bffchrismair * 10fba2635c088b01af59300e8a02611bb788ee3bffchrismair * Unless required by applicable law or agreed to in writing, software 11fba2635c088b01af59300e8a02611bb788ee3bffchrismair * distributed under the License is distributed on an "AS IS" BASIS, 12fba2635c088b01af59300e8a02611bb788ee3bffchrismair * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13fba2635c088b01af59300e8a02611bb788ee3bffchrismair * See the License for the specific language governing permissions and 14fba2635c088b01af59300e8a02611bb788ee3bffchrismair * limitations under the License. 15fba2635c088b01af59300e8a02611bb788ee3bffchrismair */ 16fba2635c088b01af59300e8a02611bb788ee3bffchrismairpackage org.mockftpserver.fake.filesystem; 17fba2635c088b01af59300e8a02611bb788ee3bffchrismair 18fba2635c088b01af59300e8a02611bb788ee3bffchrismairimport org.mockftpserver.core.util.Assert; 19fba2635c088b01af59300e8a02611bb788ee3bffchrismair 20fba2635c088b01af59300e8a02611bb788ee3bffchrismair/** 21fba2635c088b01af59300e8a02611bb788ee3bffchrismair * Implementation of the {@link FileSystem} interface that simulates a Microsoft 22fba2635c088b01af59300e8a02611bb788ee3bffchrismair * Windows file system. The rules for file and directory names include: 23fba2635c088b01af59300e8a02611bb788ee3bffchrismair * <ul> 24fba2635c088b01af59300e8a02611bb788ee3bffchrismair * <li>Filenames are case-insensitive (and normalized to lower-case)</li> 25fba2635c088b01af59300e8a02611bb788ee3bffchrismair * <li>Either forward slashes (/) or backward slashes (\) are valid path separators (but are normalized to '\')</li> 26fba2635c088b01af59300e8a02611bb788ee3bffchrismair * <li>An absolute path starts with a drive specifier (e.g. 'a:' or 'c:') followed 27fba2635c088b01af59300e8a02611bb788ee3bffchrismair * by '\' or '/', or else if it starts with "\\"</li> 28fba2635c088b01af59300e8a02611bb788ee3bffchrismair * </ul> 29fba2635c088b01af59300e8a02611bb788ee3bffchrismair * <p/> 30fba2635c088b01af59300e8a02611bb788ee3bffchrismair * The <code>directoryListingFormatter</code> property is automatically initialized to an instance 31fba2635c088b01af59300e8a02611bb788ee3bffchrismair * of {@link WindowsDirectoryListingFormatter}. 32fba2635c088b01af59300e8a02611bb788ee3bffchrismair * 33fba2635c088b01af59300e8a02611bb788ee3bffchrismair * @author Chris Mair 34fba2635c088b01af59300e8a02611bb788ee3bffchrismair * @version $Revision$ - $Date$ 35fba2635c088b01af59300e8a02611bb788ee3bffchrismair */ 36fba2635c088b01af59300e8a02611bb788ee3bffchrismairpublic class WindowsFakeFileSystem extends AbstractFakeFileSystem { 37fba2635c088b01af59300e8a02611bb788ee3bffchrismair 38fba2635c088b01af59300e8a02611bb788ee3bffchrismair public static final char SEPARATOR = '\\'; 39fba2635c088b01af59300e8a02611bb788ee3bffchrismair private static final String VALID_PATTERN = "\\p{Alpha}\\:" + "(\\\\|(\\\\[^\\\\\\:\\*\\?\\<\\>\\|\\\"]+)+)"; 40fba2635c088b01af59300e8a02611bb788ee3bffchrismair //static final VALID_PATTERN = /\p{Alpha}\:(\\|(\\[^\\\:\*\?\<\>\|\"]+)+)/ 41fba2635c088b01af59300e8a02611bb788ee3bffchrismair private static final String LAN_PREFIX = "\\\\"; 42fba2635c088b01af59300e8a02611bb788ee3bffchrismair 43fba2635c088b01af59300e8a02611bb788ee3bffchrismair /** 44fba2635c088b01af59300e8a02611bb788ee3bffchrismair * Construct a new instance and initialize the directoryListingFormatter to a WindowsDirectoryListingFormatter. 45fba2635c088b01af59300e8a02611bb788ee3bffchrismair */ 46fba2635c088b01af59300e8a02611bb788ee3bffchrismair public WindowsFakeFileSystem() { 47fba2635c088b01af59300e8a02611bb788ee3bffchrismair this.setDirectoryListingFormatter(new WindowsDirectoryListingFormatter()); 48fba2635c088b01af59300e8a02611bb788ee3bffchrismair } 49fba2635c088b01af59300e8a02611bb788ee3bffchrismair 50fba2635c088b01af59300e8a02611bb788ee3bffchrismair //------------------------------------------------------------------------- 51fba2635c088b01af59300e8a02611bb788ee3bffchrismair // Abstract Or Overridden Method Implementations 52fba2635c088b01af59300e8a02611bb788ee3bffchrismair //------------------------------------------------------------------------- 53fba2635c088b01af59300e8a02611bb788ee3bffchrismair 54fba2635c088b01af59300e8a02611bb788ee3bffchrismair /** 55fba2635c088b01af59300e8a02611bb788ee3bffchrismair * Return the normalized and unique key used to access the file system entry. Windows is case-insensitive, 56fba2635c088b01af59300e8a02611bb788ee3bffchrismair * so normalize all paths to lower-case. 57fba2635c088b01af59300e8a02611bb788ee3bffchrismair * 58fba2635c088b01af59300e8a02611bb788ee3bffchrismair * @param path - the path 59fba2635c088b01af59300e8a02611bb788ee3bffchrismair * @return the corresponding normalized key 60fba2635c088b01af59300e8a02611bb788ee3bffchrismair */ 61fba2635c088b01af59300e8a02611bb788ee3bffchrismair protected String getFileSystemEntryKey(String path) { 62fba2635c088b01af59300e8a02611bb788ee3bffchrismair return normalize(path).toLowerCase(); 63fba2635c088b01af59300e8a02611bb788ee3bffchrismair } 64fba2635c088b01af59300e8a02611bb788ee3bffchrismair 65fba2635c088b01af59300e8a02611bb788ee3bffchrismair protected char getSeparatorChar() { 66fba2635c088b01af59300e8a02611bb788ee3bffchrismair return SEPARATOR; 67fba2635c088b01af59300e8a02611bb788ee3bffchrismair } 68fba2635c088b01af59300e8a02611bb788ee3bffchrismair 69fba2635c088b01af59300e8a02611bb788ee3bffchrismair /** 70fba2635c088b01af59300e8a02611bb788ee3bffchrismair * Return true if the specified path designates a valid (absolute) file path. For Windows 71fba2635c088b01af59300e8a02611bb788ee3bffchrismair * paths, a path is valid if it starts with a drive specifier followed by 72fba2635c088b01af59300e8a02611bb788ee3bffchrismair * '\' or '/', or if it starts with "\\". 73fba2635c088b01af59300e8a02611bb788ee3bffchrismair * 74fba2635c088b01af59300e8a02611bb788ee3bffchrismair * @param path - the path 75fba2635c088b01af59300e8a02611bb788ee3bffchrismair * @return true if path is valid, false otherwise 76fba2635c088b01af59300e8a02611bb788ee3bffchrismair * @throws AssertionError - if path is null 77fba2635c088b01af59300e8a02611bb788ee3bffchrismair */ 78fba2635c088b01af59300e8a02611bb788ee3bffchrismair protected boolean isValidName(String path) { 79fba2635c088b01af59300e8a02611bb788ee3bffchrismair // \/:*?"<>| 80fba2635c088b01af59300e8a02611bb788ee3bffchrismair Assert.notNull(path, "path"); 81fba2635c088b01af59300e8a02611bb788ee3bffchrismair String standardized = path.replace('/', '\\'); 82fba2635c088b01af59300e8a02611bb788ee3bffchrismair return standardized.matches(VALID_PATTERN) || standardized.startsWith(LAN_PREFIX); 83fba2635c088b01af59300e8a02611bb788ee3bffchrismair } 84fba2635c088b01af59300e8a02611bb788ee3bffchrismair 85fba2635c088b01af59300e8a02611bb788ee3bffchrismair /** 86fba2635c088b01af59300e8a02611bb788ee3bffchrismair * Return true if the specified char is a separator character ('\' or '/') 87fba2635c088b01af59300e8a02611bb788ee3bffchrismair * 88fba2635c088b01af59300e8a02611bb788ee3bffchrismair * @param c - the character to test 89fba2635c088b01af59300e8a02611bb788ee3bffchrismair * @return true if the specified char is a separator character ('\' or '/') 90fba2635c088b01af59300e8a02611bb788ee3bffchrismair */ 91fba2635c088b01af59300e8a02611bb788ee3bffchrismair protected boolean isSeparator(char c) { 92fba2635c088b01af59300e8a02611bb788ee3bffchrismair return c == '\\' || c == '/'; 93fba2635c088b01af59300e8a02611bb788ee3bffchrismair } 94fba2635c088b01af59300e8a02611bb788ee3bffchrismair 95fba2635c088b01af59300e8a02611bb788ee3bffchrismair /** 96fba2635c088b01af59300e8a02611bb788ee3bffchrismair * @return true if the specified path component is a root for this filesystem 97fba2635c088b01af59300e8a02611bb788ee3bffchrismair */ 98fba2635c088b01af59300e8a02611bb788ee3bffchrismair protected boolean isRoot(String pathComponent) { 99fba2635c088b01af59300e8a02611bb788ee3bffchrismair return pathComponent.indexOf(":") != -1; 100fba2635c088b01af59300e8a02611bb788ee3bffchrismair } 101fba2635c088b01af59300e8a02611bb788ee3bffchrismair 102fba2635c088b01af59300e8a02611bb788ee3bffchrismair}