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