1abd32a990e145862f22d15316feedced5ad246aachrismair/*
2abd32a990e145862f22d15316feedced5ad246aachrismair * Copyright 2008 the original author or authors.
3334c6ebce811c954bf2a79ba4579589a4a3326bfchrismair *
4abd32a990e145862f22d15316feedced5ad246aachrismair * Licensed under the Apache License, Version 2.0 (the "License");
5abd32a990e145862f22d15316feedced5ad246aachrismair * you may not use this file except in compliance with the License.
6abd32a990e145862f22d15316feedced5ad246aachrismair * You may obtain a copy of the License at
7334c6ebce811c954bf2a79ba4579589a4a3326bfchrismair *
8abd32a990e145862f22d15316feedced5ad246aachrismair *      http://www.apache.org/licenses/LICENSE-2.0
9334c6ebce811c954bf2a79ba4579589a4a3326bfchrismair *
10abd32a990e145862f22d15316feedced5ad246aachrismair * Unless required by applicable law or agreed to in writing, software
11abd32a990e145862f22d15316feedced5ad246aachrismair * distributed under the License is distributed on an "AS IS" BASIS,
12abd32a990e145862f22d15316feedced5ad246aachrismair * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13abd32a990e145862f22d15316feedced5ad246aachrismair * See the License for the specific language governing permissions and
14abd32a990e145862f22d15316feedced5ad246aachrismair * limitations under the License.
15abd32a990e145862f22d15316feedced5ad246aachrismair */
16334c6ebce811c954bf2a79ba4579589a4a3326bfchrismairpackage org.mockftpserver.fake.filesystem;
17334c6ebce811c954bf2a79ba4579589a4a3326bfchrismair
185e9566a04364b1cad5c33001a37d4638bc8a93e6chrismairimport java.io.ByteArrayInputStream;
195e9566a04364b1cad5c33001a37d4638bc8a93e6chrismairimport java.io.ByteArrayOutputStream;
205e9566a04364b1cad5c33001a37d4638bc8a93e6chrismairimport java.io.IOException;
215e9566a04364b1cad5c33001a37d4638bc8a93e6chrismairimport java.io.InputStream;
225e9566a04364b1cad5c33001a37d4638bc8a93e6chrismairimport java.io.OutputStream;
23abd32a990e145862f22d15316feedced5ad246aachrismair
24abd32a990e145862f22d15316feedced5ad246aachrismair/**
25abd32a990e145862f22d15316feedced5ad246aachrismair * File system entry representing a file
2681c5294b43234e26add70ffd5bfb8fbc31db45c9chrismair *
27abd32a990e145862f22d15316feedced5ad246aachrismair * @author Chris Mair
282a0a3f946dba517a01cc26278f905156857c9c91chrismair * @version $Revision$ - $Date$
29abd32a990e145862f22d15316feedced5ad246aachrismair */
30abd32a990e145862f22d15316feedced5ad246aachrismairpublic class FileEntry extends AbstractFileSystemEntry {
31abd32a990e145862f22d15316feedced5ad246aachrismair
32334c6ebce811c954bf2a79ba4579589a4a3326bfchrismair    private static final byte[] EMPTY = new byte[0];
3381c5294b43234e26add70ffd5bfb8fbc31db45c9chrismair
34334c6ebce811c954bf2a79ba4579589a4a3326bfchrismair    private byte[] bytes = EMPTY;
35334c6ebce811c954bf2a79ba4579589a4a3326bfchrismair    private ByteArrayOutputStream out;
3681c5294b43234e26add70ffd5bfb8fbc31db45c9chrismair
37abd32a990e145862f22d15316feedced5ad246aachrismair    /**
38334c6ebce811c954bf2a79ba4579589a4a3326bfchrismair     * Construct a new instance without setting its path
39abd32a990e145862f22d15316feedced5ad246aachrismair     */
40334c6ebce811c954bf2a79ba4579589a4a3326bfchrismair    public FileEntry() {
41abd32a990e145862f22d15316feedced5ad246aachrismair    }
42abd32a990e145862f22d15316feedced5ad246aachrismair
43abd32a990e145862f22d15316feedced5ad246aachrismair    /**
44334c6ebce811c954bf2a79ba4579589a4a3326bfchrismair     * Construct a new instance with the specified value for its path
45334c6ebce811c954bf2a79ba4579589a4a3326bfchrismair     *
46abd32a990e145862f22d15316feedced5ad246aachrismair     * @param path - the value for path
47abd32a990e145862f22d15316feedced5ad246aachrismair     */
48334c6ebce811c954bf2a79ba4579589a4a3326bfchrismair    public FileEntry(String path) {
49334c6ebce811c954bf2a79ba4579589a4a3326bfchrismair        super(path);
50abd32a990e145862f22d15316feedced5ad246aachrismair    }
51abd32a990e145862f22d15316feedced5ad246aachrismair
52abd32a990e145862f22d15316feedced5ad246aachrismair    /**
53334c6ebce811c954bf2a79ba4579589a4a3326bfchrismair     * Construct a new instance with the specified path and file contents
54334c6ebce811c954bf2a79ba4579589a4a3326bfchrismair     *
55334c6ebce811c954bf2a79ba4579589a4a3326bfchrismair     * @param path     - the value for path
56abd32a990e145862f22d15316feedced5ad246aachrismair     * @param contents - the contents of the file, as a String
57abd32a990e145862f22d15316feedced5ad246aachrismair     */
58334c6ebce811c954bf2a79ba4579589a4a3326bfchrismair    public FileEntry(String path, String contents) {
59334c6ebce811c954bf2a79ba4579589a4a3326bfchrismair        super(path);
60334c6ebce811c954bf2a79ba4579589a4a3326bfchrismair        setContents(contents);
61abd32a990e145862f22d15316feedced5ad246aachrismair    }
62abd32a990e145862f22d15316feedced5ad246aachrismair
63abd32a990e145862f22d15316feedced5ad246aachrismair    /**
64ef1713518991f8db0e129928853890a6508eade9chrismair     * Return false to indicate that this entry represents a file
65334c6ebce811c954bf2a79ba4579589a4a3326bfchrismair     *
66ef1713518991f8db0e129928853890a6508eade9chrismair     * @return false
67abd32a990e145862f22d15316feedced5ad246aachrismair     */
68334c6ebce811c954bf2a79ba4579589a4a3326bfchrismair    public boolean isDirectory() {
69334c6ebce811c954bf2a79ba4579589a4a3326bfchrismair        return false;
70abd32a990e145862f22d15316feedced5ad246aachrismair    }
7181c5294b43234e26add70ffd5bfb8fbc31db45c9chrismair
72abd32a990e145862f22d15316feedced5ad246aachrismair    /**
73abd32a990e145862f22d15316feedced5ad246aachrismair     * Return the size of this file
74334c6ebce811c954bf2a79ba4579589a4a3326bfchrismair     *
75abd32a990e145862f22d15316feedced5ad246aachrismair     * @return the file size in bytes
76abd32a990e145862f22d15316feedced5ad246aachrismair     */
77334c6ebce811c954bf2a79ba4579589a4a3326bfchrismair    public long getSize() {
78334c6ebce811c954bf2a79ba4579589a4a3326bfchrismair        return getCurrentBytes().length;
79abd32a990e145862f22d15316feedced5ad246aachrismair    }
8081c5294b43234e26add70ffd5bfb8fbc31db45c9chrismair
81abd32a990e145862f22d15316feedced5ad246aachrismair    /**
82abd32a990e145862f22d15316feedced5ad246aachrismair     * Set the contents of the file represented by this entry
83334c6ebce811c954bf2a79ba4579589a4a3326bfchrismair     *
84abd32a990e145862f22d15316feedced5ad246aachrismair     * @param contents - the String whose bytes are used as the contents
85abd32a990e145862f22d15316feedced5ad246aachrismair     */
86334c6ebce811c954bf2a79ba4579589a4a3326bfchrismair    public void setContents(String contents) {
87334c6ebce811c954bf2a79ba4579589a4a3326bfchrismair        byte[] newBytes = (contents != null) ? contents.getBytes() : EMPTY;
88334c6ebce811c954bf2a79ba4579589a4a3326bfchrismair        setContentsInternal(newBytes);
89abd32a990e145862f22d15316feedced5ad246aachrismair    }
9081c5294b43234e26add70ffd5bfb8fbc31db45c9chrismair
91abd32a990e145862f22d15316feedced5ad246aachrismair    /**
92abd32a990e145862f22d15316feedced5ad246aachrismair     * Set the contents of the file represented by this entry
93334c6ebce811c954bf2a79ba4579589a4a3326bfchrismair     *
94abd32a990e145862f22d15316feedced5ad246aachrismair     * @param contents - the byte[] used as the contents
95abd32a990e145862f22d15316feedced5ad246aachrismair     */
96334c6ebce811c954bf2a79ba4579589a4a3326bfchrismair    public void setContents(byte[] contents) {
97abd32a990e145862f22d15316feedced5ad246aachrismair        // Copy the bytes[] to guard against subsequent modification of the source array
983b10a12a6bf22b061eb0861469fbb5fd212de1bcchrismair        byte[] newBytes = EMPTY;
993b10a12a6bf22b061eb0861469fbb5fd212de1bcchrismair        if (contents != null) {
1003b10a12a6bf22b061eb0861469fbb5fd212de1bcchrismair            newBytes = new byte[contents.length];
1013b10a12a6bf22b061eb0861469fbb5fd212de1bcchrismair            System.arraycopy(contents, 0, newBytes, 0, contents.length);
1023b10a12a6bf22b061eb0861469fbb5fd212de1bcchrismair        }
103334c6ebce811c954bf2a79ba4579589a4a3326bfchrismair        setContentsInternal(newBytes);
104abd32a990e145862f22d15316feedced5ad246aachrismair    }
10581c5294b43234e26add70ffd5bfb8fbc31db45c9chrismair
106abd32a990e145862f22d15316feedced5ad246aachrismair    /**
107abd32a990e145862f22d15316feedced5ad246aachrismair     * Create and return an InputStream for reading the contents of the file represented by this entry
108334c6ebce811c954bf2a79ba4579589a4a3326bfchrismair     *
109abd32a990e145862f22d15316feedced5ad246aachrismair     * @return an InputStream
110abd32a990e145862f22d15316feedced5ad246aachrismair     */
111334c6ebce811c954bf2a79ba4579589a4a3326bfchrismair    public InputStream createInputStream() {
112334c6ebce811c954bf2a79ba4579589a4a3326bfchrismair        return new ByteArrayInputStream(getCurrentBytes());
113abd32a990e145862f22d15316feedced5ad246aachrismair    }
114abd32a990e145862f22d15316feedced5ad246aachrismair
115abd32a990e145862f22d15316feedced5ad246aachrismair    /**
116abd32a990e145862f22d15316feedced5ad246aachrismair     * Create and return an OutputStream for writing the contents of the file represented by this entry
117334c6ebce811c954bf2a79ba4579589a4a3326bfchrismair     *
118334c6ebce811c954bf2a79ba4579589a4a3326bfchrismair     * @param append - true if the OutputStream should append to any existing contents false if
119334c6ebce811c954bf2a79ba4579589a4a3326bfchrismair     *               any existing contents should be overwritten
120abd32a990e145862f22d15316feedced5ad246aachrismair     * @return an OutputStream
121abd32a990e145862f22d15316feedced5ad246aachrismair     * @throws FileSystemException - if an error occurs creating or initializing the OutputStream
122abd32a990e145862f22d15316feedced5ad246aachrismair     */
123334c6ebce811c954bf2a79ba4579589a4a3326bfchrismair    public OutputStream createOutputStream(boolean append) {
124abd32a990e145862f22d15316feedced5ad246aachrismair        // If appending and we already have an OutputStream, then continue to use it
125abd32a990e145862f22d15316feedced5ad246aachrismair        if (append && out != null) {
126334c6ebce811c954bf2a79ba4579589a4a3326bfchrismair            return out;
127abd32a990e145862f22d15316feedced5ad246aachrismair        }
12881c5294b43234e26add70ffd5bfb8fbc31db45c9chrismair
129334c6ebce811c954bf2a79ba4579589a4a3326bfchrismair        out = new ByteArrayOutputStream();
130334c6ebce811c954bf2a79ba4579589a4a3326bfchrismair        byte[] initialContents = (append) ? bytes : EMPTY;
131abd32a990e145862f22d15316feedced5ad246aachrismair        try {
132334c6ebce811c954bf2a79ba4579589a4a3326bfchrismair            out.write(initialContents);
133abd32a990e145862f22d15316feedced5ad246aachrismair        }
134abd32a990e145862f22d15316feedced5ad246aachrismair        catch (IOException e) {
135334c6ebce811c954bf2a79ba4579589a4a3326bfchrismair            throw new FileSystemException(getPath(), null, e);
136abd32a990e145862f22d15316feedced5ad246aachrismair        }
137334c6ebce811c954bf2a79ba4579589a4a3326bfchrismair        return out;
138abd32a990e145862f22d15316feedced5ad246aachrismair    }
139abd32a990e145862f22d15316feedced5ad246aachrismair
14009415075d96852489d096aea7ae07dd156b58643chrismair    /**
14109415075d96852489d096aea7ae07dd156b58643chrismair     * Return a new FileSystemEntry that is a clone of this object, except having the specified path
142334c6ebce811c954bf2a79ba4579589a4a3326bfchrismair     *
14309415075d96852489d096aea7ae07dd156b58643chrismair     * @param path - the new path value for the cloned file system entry
14409415075d96852489d096aea7ae07dd156b58643chrismair     * @return a new FileSystemEntry that has all the same values as this object except for its path
14509415075d96852489d096aea7ae07dd156b58643chrismair     */
146334c6ebce811c954bf2a79ba4579589a4a3326bfchrismair    public FileSystemEntry cloneWithNewPath(String path) {
147334c6ebce811c954bf2a79ba4579589a4a3326bfchrismair        FileEntry clone = new FileEntry(path);
148334c6ebce811c954bf2a79ba4579589a4a3326bfchrismair        clone.setLastModified(getLastModified());
149334c6ebce811c954bf2a79ba4579589a4a3326bfchrismair        clone.setOwner(getOwner());
150334c6ebce811c954bf2a79ba4579589a4a3326bfchrismair        clone.setGroup(getGroup());
151334c6ebce811c954bf2a79ba4579589a4a3326bfchrismair        clone.setPermissions(getPermissions());
152a5c19061b721f203631e1969bf38127301e29414chrismair        clone.setContents(getCurrentBytes());
153334c6ebce811c954bf2a79ba4579589a4a3326bfchrismair        return clone;
15409415075d96852489d096aea7ae07dd156b58643chrismair    }
15509415075d96852489d096aea7ae07dd156b58643chrismair
156abd32a990e145862f22d15316feedced5ad246aachrismair    //-------------------------------------------------------------------------
157abd32a990e145862f22d15316feedced5ad246aachrismair    // Internal Helper Methods
158abd32a990e145862f22d15316feedced5ad246aachrismair    //-------------------------------------------------------------------------
15981c5294b43234e26add70ffd5bfb8fbc31db45c9chrismair
160abd32a990e145862f22d15316feedced5ad246aachrismair    /**
161abd32a990e145862f22d15316feedced5ad246aachrismair     * @return the current contents of this file entry as a byte[]
162abd32a990e145862f22d15316feedced5ad246aachrismair     */
163abd32a990e145862f22d15316feedced5ad246aachrismair    private byte[] getCurrentBytes() {
164334c6ebce811c954bf2a79ba4579589a4a3326bfchrismair        return (out != null) ? out.toByteArray() : bytes;
165abd32a990e145862f22d15316feedced5ad246aachrismair    }
16681c5294b43234e26add70ffd5bfb8fbc31db45c9chrismair
167abd32a990e145862f22d15316feedced5ad246aachrismair    /**
168abd32a990e145862f22d15316feedced5ad246aachrismair     * Set the contents of the file represented by this entry
169334c6ebce811c954bf2a79ba4579589a4a3326bfchrismair     *
170abd32a990e145862f22d15316feedced5ad246aachrismair     * @param contents - the byte[] used as the contents
171abd32a990e145862f22d15316feedced5ad246aachrismair     */
172abd32a990e145862f22d15316feedced5ad246aachrismair    private void setContentsInternal(byte[] contents) {
173334c6ebce811c954bf2a79ba4579589a4a3326bfchrismair        this.bytes = contents;
17481c5294b43234e26add70ffd5bfb8fbc31db45c9chrismair
175abd32a990e145862f22d15316feedced5ad246aachrismair        // Get rid of any OutputStream
176334c6ebce811c954bf2a79ba4579589a4a3326bfchrismair        this.out = null;
177abd32a990e145862f22d15316feedced5ad246aachrismair    }
17881c5294b43234e26add70ffd5bfb8fbc31db45c9chrismair
1798c7679f897c9a2e018a225fd3080f1b038ddeeacchrismair    /**
1808c7679f897c9a2e018a225fd3080f1b038ddeeacchrismair     * @see java.lang.Object#toString()
1818c7679f897c9a2e018a225fd3080f1b038ddeeacchrismair     */
182334c6ebce811c954bf2a79ba4579589a4a3326bfchrismair    public String toString() {
183334c6ebce811c954bf2a79ba4579589a4a3326bfchrismair        return "File['" + getPath() + "' size=" + getSize() + " lastModified=" + getLastModified() + " owner="
184334c6ebce811c954bf2a79ba4579589a4a3326bfchrismair                + getOwner() + " group=" + getGroup() + " permissions=" + getPermissions() + "]";
1858c7679f897c9a2e018a225fd3080f1b038ddeeacchrismair    }
18681c5294b43234e26add70ffd5bfb8fbc31db45c9chrismair
187abd32a990e145862f22d15316feedced5ad246aachrismair}
188