1*876b9d75SXin Li -------------------------------------------------- 2*876b9d75SXin Li FakeFtpServer Filesystems 3*876b9d75SXin Li -------------------------------------------------- 4*876b9d75SXin Li 5*876b9d75SXin LiFakeFtpServer Filesystems 6*876b9d75SXin Li~~~~~~~~~~~~~~~~~~~~~~~~~ 7*876b9d75SXin Li 8*876b9d75SXin Li <<FakeFtpServer>> provides a simulated server file system, including support for file and directory permissions 9*876b9d75SXin Li and owner and group authorization based on Unix. This file system can be populated at startup (or thereafter) with 10*876b9d75SXin Li directories and files (including arbitrary content) to be retrieved by an FTP client. Any files sent to the server 11*876b9d75SXin Li by an FTP client exist within that file system as well, and can be accessed through the file system API, or 12*876b9d75SXin Li can even be subsequently retrieved by an FTP client. 13*876b9d75SXin Li 14*876b9d75SXin Li The filesystem abstraction is accessed through the <<<FileSystem>>> interface in the 15*876b9d75SXin Li <<<org.mockftpserver.fake.filesystem>>> package. Two implementations of this interface are provided: 16*876b9d75SXin Li <<<WindowsFakeFileSystem>>> and <<<UnixFakeFileSystem>>>. They both manage the files and directories in memory, 17*876b9d75SXin Li simulating a real file system. You are also free to implement your own <<<FileSystem>>> implementation. 18*876b9d75SXin Li 19*876b9d75SXin Li Note that both <<<WindowsFakeFileSystem>>> and <<<UnixFakeFileSystem>>> are <virtual> file systems, and do 20*876b9d75SXin Li not depend on the <real> operating systems or file systems on which <<FakeFtpServer>> is running. In other 21*876b9d75SXin Li words, you can configure and run a <<FakeFtpServer>> with a <<<WindowsFakeFileSystem>>> on top of a <real> 22*876b9d75SXin Li Unix system, or run a <<FakeFtpServer>> with a <<<UnixFakeFileSystem>>> on top of a <real> Windows system. 23*876b9d75SXin Li 24*876b9d75SXin Li See the javadoc for these classes for more information. 25*876b9d75SXin Li 26*876b9d75SXin Li 27*876b9d75SXin Li* WindowsFakeFileSystem 28*876b9d75SXin Li~~~~~~~~~~~~~~~~~~~~~~~ 29*876b9d75SXin Li 30*876b9d75SXin Li <<WindowsFakeFileSystem>> is an implementation of the <<<FileSystem>>> interface that simulates a Microsoft 31*876b9d75SXin Li Windows file system. The rules for file and directory names include: 32*876b9d75SXin Li 33*876b9d75SXin Li * Filenames are case-insensitive 34*876b9d75SXin Li 35*876b9d75SXin Li * Either forward slashes (/) or backward slashes (\) are valid path separators (but are normalized to '\') 36*876b9d75SXin Li 37*876b9d75SXin Li * An absolute path starts with a drive specifier (e.g. 'a:' or 'c:') followed by '\' or '/', 38*876b9d75SXin Li or else it starts with "\\"</li> 39*876b9d75SXin Li 40*876b9d75SXin Li 41*876b9d75SXin Li* UnixFakeFileSystem 42*876b9d75SXin Li~~~~~~~~~~~~~~~~~~~~ 43*876b9d75SXin Li 44*876b9d75SXin Li <<UnixFakeFileSystem>> is an implementation of the <<<FileSystem>>> interface that simulates a Unix 45*876b9d75SXin Li file system. The rules for file and directory names include: 46*876b9d75SXin Li 47*876b9d75SXin Li * Filenames are case-sensitive 48*876b9d75SXin Li 49*876b9d75SXin Li * Forward slashes (/) are the only valid path separators 50*876b9d75SXin Li 51*876b9d75SXin Li 52*876b9d75SXin Li* WindowsFakeFileSystem and UnixFakeFileSystem: Common Behavior and Configuration 53*876b9d75SXin Li~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 54*876b9d75SXin Li 55*876b9d75SXin Li Both <<<WindowsFakeFileSystem>>> and <<<UnixFakeFileSystem>>> are subclasses of <<<AbstractFakeFileSystem>>>. They 56*876b9d75SXin Li manage the files and directories in memory, simulating a real file system. 57*876b9d75SXin Li 58*876b9d75SXin Li If the <createParentDirectoriesAutomatically> property is set to <true>, 59*876b9d75SXin Li then creating a directory or file will automatically create any parent directories (recursively) 60*876b9d75SXin Li that do not already exist. If <false>, then creating a directory or file throws an 61*876b9d75SXin Li exception if its parent directory does not exist. This value defaults to <true>. 62*876b9d75SXin Li 63*876b9d75SXin Li The <directoryListingFormatter> property holds an instance of <<DirectoryListingFormatter>>, 64*876b9d75SXin Li used by the <formatDirectoryListing> method to format directory listings in a 65*876b9d75SXin Li filesystem-specific manner. This property is initialized by concrete subclasses. 66*876b9d75SXin Li 67*876b9d75SXin Li 68*876b9d75SXin Li* File Permissions, Owners and Groups 69*876b9d75SXin Li~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 70*876b9d75SXin Li 71*876b9d75SXin Li Each <file> or <directory> entry within a <<<FileSystem>>> has associated <owner>, <group> and <permissions> 72*876b9d75SXin Li attributes. All of these attributes are optional. If none are specified for a file or directory, then full 73*876b9d75SXin Li access by all users is the default. 74*876b9d75SXin Li 75*876b9d75SXin Li If, however, these values are specified for a filesystem entry, then they affect whether a file can be created, 76*876b9d75SXin Li read, written or deleted, and whether a directory can be created, listed or deleted. 77*876b9d75SXin Li 78*876b9d75SXin Li This approach for access control is conceptually (and somewhat loosely) based on the Unix file system, but 79*876b9d75SXin Li don't expect a comprehensive implementation fully matching Unix's capabilities. 80*876b9d75SXin Li 81*876b9d75SXin Li 82*876b9d75SXin Li** Permissions 83*876b9d75SXin Li~~~~~~~~~~~~~~ 84*876b9d75SXin Li 85*876b9d75SXin Li The permissions for a file or directory entry in the filesystem are represented by a 9-character string of 86*876b9d75SXin Li the form "rwxrwxrwx", consisting of three "rwx" triples. Each triple indicates the READ ("r"), WRITE ("w") and 87*876b9d75SXin Li EXECUTE ("x") permissions for a specific set of users. Each position can alternatively contain a "-" to 88*876b9d75SXin Li indicate no READ/WRITE/EXECUTE access, depending on its position. 89*876b9d75SXin Li 90*876b9d75SXin Li The first "rwx" triple indicates the READ, WRITE and EXECUTE permissions for the owner of the file. The 91*876b9d75SXin Li second triple indicates the permissions for the group associated with the file. The third triple 92*876b9d75SXin Li indicates the permissions for the rest of the world. 93*876b9d75SXin Li 94*876b9d75SXin Li For example, the permissions string "rwx--xrw-" is interpreted to mean that users have READ/WRITE/EXECUTE access, 95*876b9d75SXin Li the group has only EXECUTE, and the world has only READ and WRITE. 96*876b9d75SXin Li 97*876b9d75SXin Li There are plenty of good tutorials and references for understanding Unix file permissions, including 98*876b9d75SXin Li {{{http://www.dartmouth.edu/~rc/help/faq/permissions.html}this one}}. 99*876b9d75SXin Li 100*876b9d75SXin Li The <<<Permissions>>> class represents and encapsulates the read/write/execute permissions for a file or 101*876b9d75SXin Li directory. Its constructor takes a 9-character "rwx" String as described above. 102*876b9d75SXin Li 103*876b9d75SXin Li The <<<AbstractFileSystemEntry>>> contains a <permissions> attribute, so that every file and directory in the 104*876b9d75SXin Li file system can be assigned a unique set of permissions from a <<<Permissions>>> object. There is also a 105*876b9d75SXin Li <<<setPermissionsFromString()>>> convenience setter that allows setting the permissions directly from a String. 106*876b9d75SXin Li 107*876b9d75SXin Li 108*876b9d75SXin Li** FileSystem Access Rules 109*876b9d75SXin Li~~~~~~~~~~~~~~~~~~~~~~~~~~~ 110*876b9d75SXin Li 111*876b9d75SXin Li*** When Are READ, WRITE or EXECUTE Access Required? 112*876b9d75SXin Li~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 113*876b9d75SXin Li 114*876b9d75SXin Li If the <permissions> are configured for a file or directory within the <<<FileSystem>>>, then 115*876b9d75SXin Li those permissions affect whether and how that file/directory can be accessed. 116*876b9d75SXin Li Here are the rules for applying permissions for file access: 117*876b9d75SXin Li 118*876b9d75SXin Li*------------------------*-------------------------------------------------------------------* 119*876b9d75SXin Li| <<Operation>> | <<Required Permissions>> | 120*876b9d75SXin Li*------------------------*-------------------------------------------------------------------* 121*876b9d75SXin Li| Create a new file | EXECUTE access to the directory and WRITE access to the directory | 122*876b9d75SXin Li*------------------------*-------------------------------------------------------------------* 123*876b9d75SXin Li| Read a file | EXECUTE access to the directory and READ access to the file | 124*876b9d75SXin Li*------------------------*-------------------------------------------------------------------* 125*876b9d75SXin Li| Write a file | EXECUTE access to the directory and WRITE access to the file | 126*876b9d75SXin Li*------------------------*-------------------------------------------------------------------* 127*876b9d75SXin Li| Delete a file | WRITE access to the directory | 128*876b9d75SXin Li*------------------------*-------------------------------------------------------------------* 129*876b9d75SXin Li| Rename a file | READ access to the FROM file and WRITE access to the directory | 130*876b9d75SXin Li*------------------------*-------------------------------------------------------------------* 131*876b9d75SXin Li| Create a directory | WRITE and EXECUTE acccess to the parent directory | 132*876b9d75SXin Li*------------------------*-------------------------------------------------------------------* 133*876b9d75SXin Li| List a directory | READ acccess to the directory/file | 134*876b9d75SXin Li*------------------------*-------------------------------------------------------------------* 135*876b9d75SXin Li| CD to a directory | EXECUTE acccess to the directory | 136*876b9d75SXin Li*------------------------*-------------------------------------------------------------------* 137*876b9d75SXin Li| Delete a directory | WRITE acccess to the parent directory | 138*876b9d75SXin Li*------------------------*-------------------------------------------------------------------* 139*876b9d75SXin Li 140*876b9d75SXin Li*** How Do Owner and Group Affect Access? 141*876b9d75SXin Li~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 142*876b9d75SXin Li 143*876b9d75SXin Li Each file and directory in the filesystem (subclass of <<<AbstractFileSystemEntry>>>) contains <owner> 144*876b9d75SXin Li and <group> attributes. These attributes are optional. 145*876b9d75SXin Li 146*876b9d75SXin Li If the <owner> is configured for a file/directory, AND the <permissions> are configured as well, 147*876b9d75SXin Li then the <<owner>> triple from the <permissions> are applied if and only if the <<<UserAccount>>> for the 148*876b9d75SXin Li currently logged in FTP user (client) matches the <owner> configured for the file/directory. 149*876b9d75SXin Li 150*876b9d75SXin Li Similarly, if the <group> is configured for a file/directory, AND the <permissions> are configured as well, 151*876b9d75SXin Li then the <<group>> triple from the <permissions> are applied if and only if <groups> configured for the 152*876b9d75SXin Li <<<UserAccount>>> for the currently logged in FTP user (client) contain the <group> configured for the file/directory. 153*876b9d75SXin Li 154*876b9d75SXin Li Otherwise, the <<world>> triple from the <permissions> are applied. 155*876b9d75SXin Li 156*876b9d75SXin Li* Example Code 157*876b9d75SXin Li~~~~~~~~~~~~~~ 158*876b9d75SXin Li 159*876b9d75SXin Li This example illustrates setting the permissions, owner and group for directories and files within the 160*876b9d75SXin Li <<<FakeFtpServer>>> filesystem. In this case, the filesystem is an instance of <<<WindowsFakeFileSystem>>>, 161*876b9d75SXin Li but the code would be almost exactly the same for <<<UnixFakeFileSystem>>> as well. 162*876b9d75SXin Li 163*876b9d75SXin Li+------------------------------------------------------------------------------ 164*876b9d75SXin Li final String USER1 = "joe"; 165*876b9d75SXin Li final String USER2 = "mary"; 166*876b9d75SXin Li final String GROUP = "dev"; 167*876b9d75SXin Li final String CONTENTS = "abcdef 1234567890"; 168*876b9d75SXin Li 169*876b9d75SXin Li FileSystem fileSystem = new WindowsFakeFileSystem(); 170*876b9d75SXin Li DirectoryEntry directoryEntry1 = new DirectoryEntry("c:\\"); 171*876b9d75SXin Li directoryEntry1.setPermissions(new Permissions("rwxrwx---")); 172*876b9d75SXin Li directoryEntry1.setOwner(USER1); 173*876b9d75SXin Li directoryEntry1.setGroup(GROUP); 174*876b9d75SXin Li 175*876b9d75SXin Li DirectoryEntry directoryEntry2 = new DirectoryEntry("c:\\data"); 176*876b9d75SXin Li directoryEntry2.setPermissions(Permissions.ALL); 177*876b9d75SXin Li directoryEntry2.setOwner(USER1); 178*876b9d75SXin Li directoryEntry2.setGroup(GROUP); 179*876b9d75SXin Li 180*876b9d75SXin Li FileEntry fileEntry1 = new FileEntry("c:\\data\\file1.txt", CONTENTS); 181*876b9d75SXin Li fileEntry1.setPermissionsFromString("rw-rw-rw-"); 182*876b9d75SXin Li fileEntry1.setOwner(USER1); 183*876b9d75SXin Li fileEntry1.setGroup(GROUP); 184*876b9d75SXin Li 185*876b9d75SXin Li FileEntry fileEntry2 = new FileEntry("c:\\data\\run.exe"); 186*876b9d75SXin Li fileEntry2.setPermissionsFromString("rwxrwx---"); 187*876b9d75SXin Li fileEntry2.setOwner(USER2); 188*876b9d75SXin Li fileEntry2.setGroup(GROUP); 189*876b9d75SXin Li 190*876b9d75SXin Li fileSystem.add(directoryEntry1); 191*876b9d75SXin Li fileSystem.add(directoryEntry2); 192*876b9d75SXin Li fileSystem.add(fileEntry1); 193*876b9d75SXin Li fileSystem.add(fileEntry2); 194*876b9d75SXin Li 195*876b9d75SXin Li FakeFtpServer fakeFtpServer = new FakeFtpServer(); 196*876b9d75SXin Li fakeFtpServer.setFileSystem(fileSystem); 197*876b9d75SXin Li+------------------------------------------------------------------------------ 198*876b9d75SXin Li 199*876b9d75SXin Li Things to note about the above example: 200*876b9d75SXin Li 201*876b9d75SXin Li * The <<<FakeFtpServer>>> instance is configured with a <<<WindowsFakeFileSystem>>> and a "c:\" root 202*876b9d75SXin Li directory with a "data" sub-directory containing two files. Permissions and owner/group are specified for 203*876b9d75SXin Li both directories and both files. 204*876b9d75SXin Li 205*876b9d75SXin Li * The permissions for the directories are specified using the "permissions" setter, which takes an 206*876b9d75SXin Li instance of the <<<Permissions>>> class. The permissions for both files are specified using the 207*876b9d75SXin Li "permissionsFromString" shortcut method. Either way is fine -- use whichever method you prefer on 208*876b9d75SXin Li both files and directories. 209*876b9d75SXin Li 210*876b9d75SXin Li [] 211*876b9d75SXin Li 212*876b9d75SXin Li When you want to retrieve and/or verify the contents of the <<<FakeFtpServer>>> filesystem, you can use 213*876b9d75SXin Li the <<<FileSystem#getEntry(String path)>>> method, as shown in the following code. 214*876b9d75SXin Li 215*876b9d75SXin Li+------------------------------------------------------------------------------ 216*876b9d75SXin Li DirectoryEntry dirEntry = (DirectoryEntry)fileSystem.getEntry("c:/data"); 217*876b9d75SXin Li 218*876b9d75SXin Li FileEntry fileEntry = (FileEntry)fileSystem.getEntry("c:/data/file1.txt"); 219*876b9d75SXin Li 220*876b9d75SXin Li FileEntry newFileEntry = (FileEntry)fileSystem.getEntry("c:/data/new.txt"); 221*876b9d75SXin Li InputStream inputStream = newFileEntry.createInputStream(); 222*876b9d75SXin Li // read the file contents using inputStream 223*876b9d75SXin Li+------------------------------------------------------------------------------ 224*876b9d75SXin Li 225*876b9d75SXin Li See the javadoc for <<<FileSystem>>>, <<<FileEntry>>> and <<<DirectoryEntry>>> for more information 226*876b9d75SXin Li on the methods available. 227*876b9d75SXin Li 228*876b9d75SXin Li 229*876b9d75SXin Li** Example Using Spring Configuration 230*876b9d75SXin Li~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 231*876b9d75SXin Li 232*876b9d75SXin Li See the {{{./fakeftpserver-getting-started.html#Spring}FakeFtpServer Getting Started - Spring Configuration}} 233*876b9d75SXin Li for an example of how to configure a <<<FakeFtpServer>>> instance and associated filesystem in the 234*876b9d75SXin Li {{{http://www.springframework.org/}Spring Framework}}. 235*876b9d75SXin Li