1/* 2 * Copyright 2008 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.fake.filesystem 17 18import java.io.File 19import java.io.IOException 20 21/** 22 * Implementation of the {@link FileSystem} interface that simulates a Microsoft 23 * Windows file system. The rules for file and directory names include: 24 * <ul> 25 * <li>Filenames are case-insensitive (and normalized to lower-case)</li> 26 * <li>Either forward slashes (/) or backward slashes (\) are valid path separators (but are normalized to '\')</li> 27 * <li>An absolute path starts with a drive specifier (e.g. 'a:' or 'c:') followed 28 * by '\' or '/', or else if it starts with "\\"</li> 29 * </ul> 30 * 31 * @version $Revision: $ - $Date: $ 32 * 33 * @author Chris Mair 34 */ 35class FakeWindowsFileSystem extends AbstractFakeFileSystem { 36 37 public static final String SEPARATOR = "\\" 38 static final VALID_PATTERN = /\p{Alpha}\:(\\|(\\[^\\\:\*\?\<\>\|\"]+)+)/ 39 static final LAN_PREFIX = "\\\\" 40 41 //------------------------------------------------------------------------- 42 // Abstract Method Implementations 43 //------------------------------------------------------------------------- 44 45 protected String getSeparator() { 46 return SEPARATOR 47 } 48 49 protected boolean isValidName(String path) { 50 // \/:*?"<>| 51 assert path != null 52 def standardized = path.replace("/", "\\") 53 return (standardized ==~ VALID_PATTERN) || standardized.startsWith(LAN_PREFIX) 54 } 55 56 /** 57 * Return true if the specified char is a separator character ('\' or '/') 58 * @param c - the character to test 59 * @return true if the specified char is a separator character ('\' or '/') 60 */ 61 protected boolean isSeparator(char c) { 62 return c == '\\' || c == '/' 63 } 64 65 protected String componentsToPath(List components) { 66 if (components.size() == 1) { 67 def first = components[0] 68 if (first == "" || isRoot(first)) { 69 return first + this.separator 70 } 71 } 72 return components.join(this.separator) 73 } 74 75 protected boolean isRoot(String pathComponent) { 76 return pathComponent.contains(":") 77 } 78 79 /** 80 * Return the components of the specified path as a List. The components are normalized, and 81 * the returned List does not include path separator characters. 82 */ 83 protected List normalizedComponents(String path) { 84 assert path != null 85 def p = path.replace("/", this.separator) 86 87 // TODO better way to do this 88 if (p == this.separator) { 89 return [""] 90 } 91 92 def parts = p.split("\\" + this.separator) as List 93 def result = [] 94 parts.each { part -> 95 if (part == "..") { 96 result.remove(result.size()-1) 97 } 98 else if (part != ".") { 99 result << part 100 } 101 } 102 return result 103 } 104 105 /** 106 * Return true if the specified path designates an absolute file path. For Windows 107 * paths, a path is absolute if it starts with a drive specifier followed by 108 * '\' or '/', or if it starts with "\\". 109 * 110 * @param path - the path 111 * @return true if path is absolute, false otherwise 112 * 113 * @throws AssertionError - if path is null 114 */ 115 boolean isAbsolute(String path) { 116 return isValidName(path) 117 } 118 119 }