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