001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.commons.vfs2; 018 019import java.io.Closeable; 020import java.io.IOException; 021import java.io.InputStream; 022import java.io.OutputStream; 023import java.nio.charset.Charset; 024import java.security.cert.Certificate; 025import java.util.Arrays; 026import java.util.Map; 027 028import org.apache.commons.vfs2.provider.AbstractFileObject; 029import org.apache.commons.vfs2.util.RandomAccessMode; 030 031/** 032 * Represents the data content of a file. 033 * <p> 034 * To read from a file, use the {@code InputStream} returned by {@link #getInputStream()}. 035 * </p> 036 * <p> 037 * To write to a file, use the {@code OutputStream} returned by {@link #getOutputStream()} method. This will create the 038 * file, and the parent folder, if necessary. 039 * </p> 040 * <p> 041 * A file may have multiple InputStreams open at the same time. 042 * </p> 043 * 044 * @see FileObject#getContent 045 */ 046public interface FileContent extends Closeable { 047 048 /** 049 * Closes all resources used by the content, including any open stream. Commits pending changes to the file. 050 * <p> 051 * This method is a hint to the implementation that it can release resources. This object can continue to be used 052 * after calling this method. 053 * </p> 054 * 055 * @throws FileSystemException if an error occurs closing the file. 056 */ 057 @Override 058 void close() throws FileSystemException; 059 060 /** 061 * Gets the value of an attribute of the file's content. 062 * 063 * @param attrName The name of the attribute. Attribute names are case-insensitive. 064 * @return The value of the attribute, or null if the attribute value is unknown. 065 * @throws FileSystemException If the file does not exist, or does not support attributes. 066 */ 067 Object getAttribute(String attrName) throws FileSystemException; 068 069 /** 070 * Gets the attributes of the file's content. 071 * 072 * @return The names of the attributes. Never returns null; 073 * @throws FileSystemException If the file does not exist, or does not support attributes. 074 */ 075 String[] getAttributeNames() throws FileSystemException; 076 077 /** 078 * Returns a read-only map of this file's attributes. 079 * 080 * @return The attribute Map. 081 * @throws FileSystemException If the file does not exist, or does not support attributes. 082 */ 083 Map<String, Object> getAttributes() throws FileSystemException; 084 085 /** 086 * Returns the content of a file as a byte array. 087 * 088 * @return The content as a byte array. 089 * @throws IOException if the file content cannot be accessed. 090 * @since 2.4 091 */ 092 default byte[] getByteArray() throws IOException { 093 final long sizeL = getSize(); 094 if (sizeL > Integer.MAX_VALUE) { 095 throw new IllegalStateException(String.format("File content is too large for a byte array: %,d", sizeL)); 096 } 097 final boolean sizeUndefined = sizeL < 0; 098 final int size = sizeUndefined ? AbstractFileObject.DEFAULT_BUFFER_SIZE : (int) sizeL; 099 final byte[] buf = new byte[size]; 100 int pos; 101 try (InputStream in = getInputStream(size)) { 102 int read = 0; 103 for (pos = 0; pos < size && read >= 0; pos += read) { 104 read = in.read(buf, pos, size - pos); 105 } 106 } 107 return sizeUndefined && pos < buf.length ? Arrays.copyOf(buf, ++pos) : buf; 108 } 109 110 /** 111 * Gets the certificates if any used to sign this file or folder. 112 * 113 * @return The certificates, or an empty array if there are no certificates or the file does not support signing. 114 * @throws FileSystemException If the file does not exist, or is being written. 115 */ 116 Certificate[] getCertificates() throws FileSystemException; 117 118 /** 119 * Gets the content info. e.g. type, encoding, ... 120 * 121 * @return the FileContentInfo 122 * @throws FileSystemException if an error occurs. 123 */ 124 FileContentInfo getContentInfo() throws FileSystemException; 125 126 /** 127 * Gets the file which this is the content of. 128 * 129 * @return The FileObject this is the content of. 130 */ 131 FileObject getFile(); 132 133 /** 134 * Gets an input stream for reading the file's content. 135 * <p> 136 * There may only be a single input or output stream open for the file at any time. 137 * </p> 138 * 139 * @return An input stream to read the file's content from. The input stream is buffered, so there is no need to 140 * wrap it in a {@code BufferedInputStream}. 141 * @throws FileSystemException If the file does not exist, or is being read, or is being written, or on error 142 * opening the stream. 143 */ 144 InputStream getInputStream() throws FileSystemException; 145 146 /** 147 * Gets an input stream for reading the file's content. 148 * <p> 149 * There may only be a single input or output stream open for the file at any time. 150 * </p> 151 * 152 * @param bufferSize The buffer size to use. 153 * @return An input stream to read the file's content from. The input stream is buffered, so there is no need to 154 * wrap it in a {@code BufferedInputStream}. 155 * @throws FileSystemException If the file does not exist, or is being read, or is being written, or on error 156 * opening the stream. 157 * @since 2.4 158 */ 159 default InputStream getInputStream(final int bufferSize) throws FileSystemException { 160 return getInputStream(); 161 } 162 163 /** 164 * Gets the last-modified timestamp of the file. 165 * 166 * @return The last-modified timestamp. 167 * @throws FileSystemException If the file does not exist, or is being written to, or on error determining the 168 * last-modified timestamp. 169 */ 170 long getLastModifiedTime() throws FileSystemException; 171 172 /** 173 * Gets an output stream for writing the file's content. 174 * <p> 175 * If the file does not exist, this method creates it, and the parent folder, if necessary. If the file does exist, 176 * it is replaced with whatever is written to the output stream. 177 * </p> 178 * <p> 179 * There may only be a single input or output stream open for the file at any time. 180 * </p> 181 * 182 * @return An output stream to write the file's content to. The stream is buffered, so there is no need to wrap it 183 * in a {@code BufferedOutputStream}. 184 * @throws FileSystemException If the file is read-only, or is being read, or is being written, or on error opening 185 * the stream. 186 */ 187 OutputStream getOutputStream() throws FileSystemException; 188 189 /** 190 * Gets an output stream for writing the file's content. 191 * <p> 192 * If the file does not exist, this method creates it, and the parent folder, if necessary. If the file does exist, 193 * it is replaced with whatever is written to the output stream. 194 * </p> 195 * <p> 196 * There may only be a single input or output stream open for the file at any time. 197 * </p> 198 * 199 * @param bAppend true if you would like to append to the file. This may not be supported by all implementations. 200 * @return An output stream to write the file's content to. The stream is buffered, so there is no need to wrap it 201 * in a {@code BufferedOutputStream}. 202 * @throws FileSystemException If the file is read-only, or is being read, or is being written, or bAppend is true 203 * and the implementation does not support it, or on error opening the stream. 204 */ 205 OutputStream getOutputStream(boolean bAppend) throws FileSystemException; 206 207 /** 208 * Gets an output stream for writing the file's content. 209 * <p> 210 * If the file does not exist, this method creates it, and the parent folder, if necessary. If the file does exist, 211 * it is replaced with whatever is written to the output stream. 212 * </p> 213 * <p> 214 * There may only be a single input or output stream open for the file at any time. 215 * </p> 216 * 217 * @param bAppend true if you would like to append to the file. This may not be supported by all implementations. 218 * @param bufferSize The buffer size to use. 219 * @return An output stream to write the file's content to. The stream is buffered, so there is no need to wrap it 220 * in a {@code BufferedOutputStream}. 221 * @throws FileSystemException If the file is read-only, or is being read, or is being written, or bAppend is true 222 * and the implementation does not support it, or on error opening the stream. 223 * @since 2.4 224 */ 225 default OutputStream getOutputStream(final boolean bAppend, final int bufferSize) throws FileSystemException { 226 return getOutputStream(bAppend); 227 } 228 229 /** 230 * Gets an output stream for writing the file's content. 231 * <p> 232 * If the file does not exist, this method creates it, and the parent folder, if necessary. If the file does exist, 233 * it is replaced with whatever is written to the output stream. 234 * </p> 235 * <p> 236 * There may only be a single input or output stream open for the file at any time. 237 * </p> 238 * 239 * @param bufferSize The buffer size to use. 240 * @return An output stream to write the file's content to. The stream is buffered, so there is no need to wrap it 241 * in a {@code BufferedOutputStream}. 242 * @throws FileSystemException If the file is read-only, or is being read, or is being written, or bAppend is true 243 * and the implementation does not support it, or on error opening the stream. 244 * @since 2.4 245 */ 246 default OutputStream getOutputStream(final int bufferSize) throws FileSystemException { 247 return getOutputStream(); 248 } 249 250 /** 251 * Gets a stream for reading/writing the file's content. 252 * <p> 253 * If the file does not exist, and you use one of the write* methods, this method creates it, and the parent folder, 254 * if necessary. If the file does exist, parts of the file are replaced with whatever is written at a given 255 * position. 256 * </p> 257 * <p> 258 * There may only be a single input or output stream open for the file at any time. 259 * </p> 260 * 261 * @param mode The mode to use to access the file. 262 * @return the stream for reading and writing the file's content. 263 * @throws FileSystemException If the file is read-only, or is being read, or is being written, or on error opening 264 * the stream. 265 */ 266 RandomAccessContent getRandomAccessContent(RandomAccessMode mode) throws FileSystemException; 267 268 /** 269 * Gets the size of the file, in bytes. 270 * 271 * @return The size of the file, in bytes. 272 * @throws FileSystemException If the file does not exist, or is being written to, or on error determining the size. 273 */ 274 long getSize() throws FileSystemException; 275 276 /** 277 * Returns the content of a file as a String. 278 * 279 * @param charset The file character set, may be null. 280 * @return The content as a byte array. 281 * @throws IOException if the file content cannot be accessed. 282 * @since 2.4 283 */ 284 default String getString(final Charset charset) throws IOException { 285 return new String(getByteArray(), charset == null ? Charset.defaultCharset() : charset); 286 } 287 288 /** 289 * Gets the content of a file as a String. 290 * 291 * @param charset The file character set, may be null. 292 * @return The content as a byte array. 293 * @throws IOException if the file content cannot be accessed. 294 * @since 2.4 295 */ 296 default String getString(final String charset) throws IOException { 297 return new String(getByteArray(), charset == null ? Charset.defaultCharset().name() : charset); 298 } 299 300 /** 301 * Checks if an attribute of the file's content exists. 302 * 303 * @param attrName The name of the attribute. 304 * @return true if the attribute exists, false otherwise. 305 * @throws FileSystemException If the file does not exist, or does not support attributes. 306 */ 307 boolean hasAttribute(String attrName) throws FileSystemException; 308 309 /** 310 * Tests if the receiver is empty. 311 * 312 * @return true if the receiver is empty, false otherwise. 313 * @throws FileSystemException If the file does not exist, or is being written to, or on error determining the size. 314 * @since 2.5.0 315 */ 316 default boolean isEmpty() throws FileSystemException { 317 return getSize() <= 0; 318 } 319 320 /** 321 * Tests if this file has open streams. 322 * 323 * @return true if the file is open, false otherwise. 324 */ 325 boolean isOpen(); 326 327 /** 328 * Removes the value of an attribute of the file's content. 329 * 330 * @param attrName The name of the attribute. 331 * @throws FileSystemException If the file does not exist, or is read-only, or does not support attributes, or on 332 * error removing the attribute. 333 */ 334 void removeAttribute(String attrName) throws FileSystemException; 335 336 /** 337 * Sets the value of an attribute of the file's content. Creates the file if it does not exist. 338 * 339 * @param attrName The name of the attribute. 340 * @param value The value of the attribute. 341 * @throws FileSystemException If the file does not exist, or is read-only, or does not support attributes, or on 342 * error setting the attribute. 343 */ 344 void setAttribute(String attrName, Object value) throws FileSystemException; 345 346 /** 347 * Sets the last-modified timestamp of the file. Creates the file if it does not exist. 348 * 349 * @param modTime The time to set the last-modified timestamp to. 350 * @throws FileSystemException If the file is read-only, or is being written to, or on error setting the 351 * last-modified timestamp. 352 */ 353 void setLastModifiedTime(long modTime) throws FileSystemException; 354 355 /** 356 * Writes this content to another FileContent. 357 * 358 * @param output The target OutputStream. 359 * @throws IOException if an error occurs writing the content. 360 * @return the total number of bytes written 361 * @since 2.1 362 */ 363 long write(FileContent output) throws IOException; 364 365 /** 366 * Writes this content to another FileObject. 367 * 368 * @param file The target FileObject. 369 * @throws IOException if an error occurs writing the content. 370 * @return the total number of bytes written 371 * @since 2.1 372 */ 373 long write(FileObject file) throws IOException; 374 375 /** 376 * Writes this content to an OutputStream. 377 * 378 * @param output The target OutputStream. 379 * @return the total number of bytes written 380 * @throws IOException if an error occurs writing the content. 381 * @since 2.1 382 */ 383 long write(OutputStream output) throws IOException; 384 385 /** 386 * Writes this content to an OutputStream. 387 * 388 * @param output The target OutputStream. 389 * @param bufferSize The buffer size to write data chunks. 390 * @return the total number of bytes written 391 * @throws IOException if an error occurs writing the file. 392 * @since 2.1 393 */ 394 long write(OutputStream output, int bufferSize) throws IOException; 395 396}