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