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