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