1c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair/* 2c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair * Copyright 2008 the original author or authors. 3c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair * 4c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair * Licensed under the Apache License, Version 2.0 (the "License"); 5c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair * you may not use this file except in compliance with the License. 6c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair * You may obtain a copy of the License at 7c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair * 8c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair * http://www.apache.org/licenses/LICENSE-2.0 9c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair * 10c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair * Unless required by applicable law or agreed to in writing, software 11c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair * distributed under the License is distributed on an "AS IS" BASIS, 12c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair * See the License for the specific language governing permissions and 14c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair * limitations under the License. 15c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair */ 16c1de24f1bfa6699e54b069e300af5e4246b34a34chrismairpackage org.mockftpserver.fake.filesystem; 17c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair 18c1de24f1bfa6699e54b069e300af5e4246b34a34chrismairimport java.io.ByteArrayInputStream; 19c1de24f1bfa6699e54b069e300af5e4246b34a34chrismairimport java.io.ByteArrayOutputStream; 20c1de24f1bfa6699e54b069e300af5e4246b34a34chrismairimport java.io.IOException; 21c1de24f1bfa6699e54b069e300af5e4246b34a34chrismairimport java.io.InputStream; 22c1de24f1bfa6699e54b069e300af5e4246b34a34chrismairimport java.io.OutputStream; 23c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair 24c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair/** 25c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair * File system entry representing a file 26c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair * 27c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair * @author Chris Mair 28c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair * @version $Revision$ - $Date$ 29c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair */ 30c1de24f1bfa6699e54b069e300af5e4246b34a34chrismairpublic class FileEntry extends AbstractFileSystemEntry { 31c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair 32c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair private static final byte[] EMPTY = new byte[0]; 33c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair 34c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair private byte[] bytes = EMPTY; 35c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair private ByteArrayOutputStream out; 36c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair 37c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair /** 38c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair * Construct a new instance without setting its path 39c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair */ 40c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair public FileEntry() { 41c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair } 42c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair 43c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair /** 44c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair * Construct a new instance with the specified value for its path 45c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair * 46c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair * @param path - the value for path 47c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair */ 48c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair public FileEntry(String path) { 49c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair super(path); 50c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair } 51c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair 52c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair /** 53c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair * Construct a new instance with the specified path and file contents 54c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair * 55c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair * @param path - the value for path 56c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair * @param contents - the contents of the file, as a String 57c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair */ 58c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair public FileEntry(String path, String contents) { 59c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair super(path); 60c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair setContents(contents); 61c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair } 62c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair 63c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair /** 64c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair * Return false to indicate that this entry represents a file 65c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair * 66c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair * @return false 67c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair */ 68c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair public boolean isDirectory() { 69c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair return false; 70c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair } 71c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair 72c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair /** 73c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair * Return the size of this file 74c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair * 75c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair * @return the file size in bytes 76c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair */ 77c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair public long getSize() { 78c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair return getCurrentBytes().length; 79c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair } 80c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair 81c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair /** 82c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair * Set the contents of the file represented by this entry 83c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair * 84c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair * @param contents - the String whose bytes are used as the contents 85c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair */ 86c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair public void setContents(String contents) { 87c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair byte[] newBytes = (contents != null) ? contents.getBytes() : EMPTY; 88c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair setContentsInternal(newBytes); 89c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair } 90c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair 91c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair /** 92c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair * Set the contents of the file represented by this entry 93c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair * 94c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair * @param contents - the byte[] used as the contents 95c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair */ 96c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair public void setContents(byte[] contents) { 97c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair // Copy the bytes[] to guard against subsequent modification of the source array 98c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair byte[] newBytes = EMPTY; 99c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair if (contents != null) { 100c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair newBytes = new byte[contents.length]; 101c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair System.arraycopy(contents, 0, newBytes, 0, contents.length); 102c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair } 103c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair setContentsInternal(newBytes); 104c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair } 105c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair 106c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair /** 107c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair * Create and return an InputStream for reading the contents of the file represented by this entry 108c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair * 109c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair * @return an InputStream 110c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair */ 111c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair public InputStream createInputStream() { 112c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair return new ByteArrayInputStream(getCurrentBytes()); 113c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair } 114c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair 115c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair /** 116c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair * Create and return an OutputStream for writing the contents of the file represented by this entry 117c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair * 118c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair * @param append - true if the OutputStream should append to any existing contents false if 119c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair * any existing contents should be overwritten 120c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair * @return an OutputStream 121c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair * @throws FileSystemException - if an error occurs creating or initializing the OutputStream 122c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair */ 123c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair public OutputStream createOutputStream(boolean append) { 124c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair // If appending and we already have an OutputStream, then continue to use it 125c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair if (append && out != null) { 126c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair return out; 127c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair } 128c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair 129c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair out = new ByteArrayOutputStream(); 130c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair byte[] initialContents = (append) ? bytes : EMPTY; 131c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair try { 132c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair out.write(initialContents); 133c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair } 134c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair catch (IOException e) { 135c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair throw new FileSystemException(getPath(), null, e); 136c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair } 137c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair return out; 138c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair } 139c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair 140c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair /** 141c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair * Return a new FileSystemEntry that is a clone of this object, except having the specified path 142c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair * 143c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair * @param path - the new path value for the cloned file system entry 144c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair * @return a new FileSystemEntry that has all the same values as this object except for its path 145c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair */ 146c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair public FileSystemEntry cloneWithNewPath(String path) { 147c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair FileEntry clone = new FileEntry(path); 148c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair clone.setLastModified(getLastModified()); 149c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair clone.setOwner(getOwner()); 150c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair clone.setGroup(getGroup()); 151c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair clone.setPermissions(getPermissions()); 152c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair clone.setContents(getCurrentBytes()); 153c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair return clone; 154c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair } 155c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair 156c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair //------------------------------------------------------------------------- 157c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair // Internal Helper Methods 158c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair //------------------------------------------------------------------------- 159c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair 160c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair /** 161c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair * @return the current contents of this file entry as a byte[] 162c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair */ 163c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair private byte[] getCurrentBytes() { 164c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair return (out != null) ? out.toByteArray() : bytes; 165c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair } 166c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair 167c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair /** 168c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair * Set the contents of the file represented by this entry 169c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair * 170c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair * @param contents - the byte[] used as the contents 171c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair */ 172c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair private void setContentsInternal(byte[] contents) { 173c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair this.bytes = contents; 174c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair 175c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair // Get rid of any OutputStream 176c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair this.out = null; 177c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair } 178c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair 179c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair /** 180c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair * @see java.lang.Object#toString() 181c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair */ 182c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair public String toString() { 183c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair return "File['" + getPath() + "' size=" + getSize() + " lastModified=" + getLastModified() + " owner=" 184c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair + getOwner() + " group=" + getGroup() + " permissions=" + getPermissions() + "]"; 185c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair } 186c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair 187c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair} 188