12ab05e83458f35931075adca0d7b0fce4ea7cccbchrismair/*
22ab05e83458f35931075adca0d7b0fce4ea7cccbchrismair * Copyright 2008 the original author or authors.
32ab05e83458f35931075adca0d7b0fce4ea7cccbchrismair *
42ab05e83458f35931075adca0d7b0fce4ea7cccbchrismair * Licensed under the Apache License, Version 2.0 (the "License");
52ab05e83458f35931075adca0d7b0fce4ea7cccbchrismair * you may not use this file except in compliance with the License.
62ab05e83458f35931075adca0d7b0fce4ea7cccbchrismair * You may obtain a copy of the License at
72ab05e83458f35931075adca0d7b0fce4ea7cccbchrismair *
82ab05e83458f35931075adca0d7b0fce4ea7cccbchrismair *      http://www.apache.org/licenses/LICENSE-2.0
92ab05e83458f35931075adca0d7b0fce4ea7cccbchrismair *
102ab05e83458f35931075adca0d7b0fce4ea7cccbchrismair * Unless required by applicable law or agreed to in writing, software
112ab05e83458f35931075adca0d7b0fce4ea7cccbchrismair * distributed under the License is distributed on an "AS IS" BASIS,
122ab05e83458f35931075adca0d7b0fce4ea7cccbchrismair * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
132ab05e83458f35931075adca0d7b0fce4ea7cccbchrismair * See the License for the specific language governing permissions and
142ab05e83458f35931075adca0d7b0fce4ea7cccbchrismair * limitations under the License.
152ab05e83458f35931075adca0d7b0fce4ea7cccbchrismair */
162ab05e83458f35931075adca0d7b0fce4ea7cccbchrismairpackage org.mockftpserver.fake.filesystem;
172ab05e83458f35931075adca0d7b0fce4ea7cccbchrismair
182ab05e83458f35931075adca0d7b0fce4ea7cccbchrismairimport java.io.ByteArrayInputStream;
192ab05e83458f35931075adca0d7b0fce4ea7cccbchrismairimport java.io.ByteArrayOutputStream;
202ab05e83458f35931075adca0d7b0fce4ea7cccbchrismairimport java.io.IOException;
212ab05e83458f35931075adca0d7b0fce4ea7cccbchrismairimport java.io.InputStream;
222ab05e83458f35931075adca0d7b0fce4ea7cccbchrismairimport java.io.OutputStream;
232ab05e83458f35931075adca0d7b0fce4ea7cccbchrismair
242ab05e83458f35931075adca0d7b0fce4ea7cccbchrismair/**
252ab05e83458f35931075adca0d7b0fce4ea7cccbchrismair * File system entry representing a file
262ab05e83458f35931075adca0d7b0fce4ea7cccbchrismair *
272ab05e83458f35931075adca0d7b0fce4ea7cccbchrismair * @author Chris Mair
282ab05e83458f35931075adca0d7b0fce4ea7cccbchrismair * @version $Revision$ - $Date$
292ab05e83458f35931075adca0d7b0fce4ea7cccbchrismair */
302ab05e83458f35931075adca0d7b0fce4ea7cccbchrismairpublic class FileEntry extends AbstractFileSystemEntry {
312ab05e83458f35931075adca0d7b0fce4ea7cccbchrismair
322ab05e83458f35931075adca0d7b0fce4ea7cccbchrismair    private static final byte[] EMPTY = new byte[0];
332ab05e83458f35931075adca0d7b0fce4ea7cccbchrismair
342ab05e83458f35931075adca0d7b0fce4ea7cccbchrismair    private byte[] bytes = EMPTY;
352ab05e83458f35931075adca0d7b0fce4ea7cccbchrismair    private ByteArrayOutputStream out;
362ab05e83458f35931075adca0d7b0fce4ea7cccbchrismair
372ab05e83458f35931075adca0d7b0fce4ea7cccbchrismair    /**
382ab05e83458f35931075adca0d7b0fce4ea7cccbchrismair     * Construct a new instance without setting its path
392ab05e83458f35931075adca0d7b0fce4ea7cccbchrismair     */
402ab05e83458f35931075adca0d7b0fce4ea7cccbchrismair    public FileEntry() {
412ab05e83458f35931075adca0d7b0fce4ea7cccbchrismair    }
422ab05e83458f35931075adca0d7b0fce4ea7cccbchrismair
432ab05e83458f35931075adca0d7b0fce4ea7cccbchrismair    /**
442ab05e83458f35931075adca0d7b0fce4ea7cccbchrismair     * Construct a new instance with the specified value for its path
452ab05e83458f35931075adca0d7b0fce4ea7cccbchrismair     *
462ab05e83458f35931075adca0d7b0fce4ea7cccbchrismair     * @param path - the value for path
472ab05e83458f35931075adca0d7b0fce4ea7cccbchrismair     */
482ab05e83458f35931075adca0d7b0fce4ea7cccbchrismair    public FileEntry(String path) {
492ab05e83458f35931075adca0d7b0fce4ea7cccbchrismair        super(path);
502ab05e83458f35931075adca0d7b0fce4ea7cccbchrismair    }
512ab05e83458f35931075adca0d7b0fce4ea7cccbchrismair
522ab05e83458f35931075adca0d7b0fce4ea7cccbchrismair    /**
532ab05e83458f35931075adca0d7b0fce4ea7cccbchrismair     * Construct a new instance with the specified path and file contents
542ab05e83458f35931075adca0d7b0fce4ea7cccbchrismair     *
552ab05e83458f35931075adca0d7b0fce4ea7cccbchrismair     * @param path     - the value for path
562ab05e83458f35931075adca0d7b0fce4ea7cccbchrismair     * @param contents - the contents of the file, as a String
572ab05e83458f35931075adca0d7b0fce4ea7cccbchrismair     */
582ab05e83458f35931075adca0d7b0fce4ea7cccbchrismair    public FileEntry(String path, String contents) {
592ab05e83458f35931075adca0d7b0fce4ea7cccbchrismair        super(path);
602ab05e83458f35931075adca0d7b0fce4ea7cccbchrismair        setContents(contents);
612ab05e83458f35931075adca0d7b0fce4ea7cccbchrismair    }
622ab05e83458f35931075adca0d7b0fce4ea7cccbchrismair
632ab05e83458f35931075adca0d7b0fce4ea7cccbchrismair    /**
642ab05e83458f35931075adca0d7b0fce4ea7cccbchrismair     * Return false to indicate that this entry represents a file
652ab05e83458f35931075adca0d7b0fce4ea7cccbchrismair     *
662ab05e83458f35931075adca0d7b0fce4ea7cccbchrismair     * @return false
672ab05e83458f35931075adca0d7b0fce4ea7cccbchrismair     */
682ab05e83458f35931075adca0d7b0fce4ea7cccbchrismair    public boolean isDirectory() {
692ab05e83458f35931075adca0d7b0fce4ea7cccbchrismair        return false;
702ab05e83458f35931075adca0d7b0fce4ea7cccbchrismair    }
712ab05e83458f35931075adca0d7b0fce4ea7cccbchrismair
722ab05e83458f35931075adca0d7b0fce4ea7cccbchrismair    /**
732ab05e83458f35931075adca0d7b0fce4ea7cccbchrismair     * Return the size of this file
742ab05e83458f35931075adca0d7b0fce4ea7cccbchrismair     *
752ab05e83458f35931075adca0d7b0fce4ea7cccbchrismair     * @return the file size in bytes
762ab05e83458f35931075adca0d7b0fce4ea7cccbchrismair     */
772ab05e83458f35931075adca0d7b0fce4ea7cccbchrismair    public long getSize() {
782ab05e83458f35931075adca0d7b0fce4ea7cccbchrismair        return getCurrentBytes().length;
792ab05e83458f35931075adca0d7b0fce4ea7cccbchrismair    }
802ab05e83458f35931075adca0d7b0fce4ea7cccbchrismair
812ab05e83458f35931075adca0d7b0fce4ea7cccbchrismair    /**
822ab05e83458f35931075adca0d7b0fce4ea7cccbchrismair     * Set the contents of the file represented by this entry
832ab05e83458f35931075adca0d7b0fce4ea7cccbchrismair     *
842ab05e83458f35931075adca0d7b0fce4ea7cccbchrismair     * @param contents - the String whose bytes are used as the contents
852ab05e83458f35931075adca0d7b0fce4ea7cccbchrismair     */
862ab05e83458f35931075adca0d7b0fce4ea7cccbchrismair    public void setContents(String contents) {
872ab05e83458f35931075adca0d7b0fce4ea7cccbchrismair        byte[] newBytes = (contents != null) ? contents.getBytes() : EMPTY;
882ab05e83458f35931075adca0d7b0fce4ea7cccbchrismair        setContentsInternal(newBytes);
892ab05e83458f35931075adca0d7b0fce4ea7cccbchrismair    }
902ab05e83458f35931075adca0d7b0fce4ea7cccbchrismair
912ab05e83458f35931075adca0d7b0fce4ea7cccbchrismair    /**
922ab05e83458f35931075adca0d7b0fce4ea7cccbchrismair     * Set the contents of the file represented by this entry
932ab05e83458f35931075adca0d7b0fce4ea7cccbchrismair     *
942ab05e83458f35931075adca0d7b0fce4ea7cccbchrismair     * @param contents - the byte[] used as the contents
952ab05e83458f35931075adca0d7b0fce4ea7cccbchrismair     */
962ab05e83458f35931075adca0d7b0fce4ea7cccbchrismair    public void setContents(byte[] contents) {
972ab05e83458f35931075adca0d7b0fce4ea7cccbchrismair        // Copy the bytes[] to guard against subsequent modification of the source array
982ab05e83458f35931075adca0d7b0fce4ea7cccbchrismair        byte[] newBytes = EMPTY;
992ab05e83458f35931075adca0d7b0fce4ea7cccbchrismair        if (contents != null) {
1002ab05e83458f35931075adca0d7b0fce4ea7cccbchrismair            newBytes = new byte[contents.length];
1012ab05e83458f35931075adca0d7b0fce4ea7cccbchrismair            System.arraycopy(contents, 0, newBytes, 0, contents.length);
1022ab05e83458f35931075adca0d7b0fce4ea7cccbchrismair        }
1032ab05e83458f35931075adca0d7b0fce4ea7cccbchrismair        setContentsInternal(newBytes);
1042ab05e83458f35931075adca0d7b0fce4ea7cccbchrismair    }
1052ab05e83458f35931075adca0d7b0fce4ea7cccbchrismair
1062ab05e83458f35931075adca0d7b0fce4ea7cccbchrismair    /**
1072ab05e83458f35931075adca0d7b0fce4ea7cccbchrismair     * Create and return an InputStream for reading the contents of the file represented by this entry
1082ab05e83458f35931075adca0d7b0fce4ea7cccbchrismair     *
1092ab05e83458f35931075adca0d7b0fce4ea7cccbchrismair     * @return an InputStream
1102ab05e83458f35931075adca0d7b0fce4ea7cccbchrismair     */
1112ab05e83458f35931075adca0d7b0fce4ea7cccbchrismair    public InputStream createInputStream() {
1122ab05e83458f35931075adca0d7b0fce4ea7cccbchrismair        return new ByteArrayInputStream(getCurrentBytes());
1132ab05e83458f35931075adca0d7b0fce4ea7cccbchrismair    }
1142ab05e83458f35931075adca0d7b0fce4ea7cccbchrismair
1152ab05e83458f35931075adca0d7b0fce4ea7cccbchrismair    /**
1162ab05e83458f35931075adca0d7b0fce4ea7cccbchrismair     * Create and return an OutputStream for writing the contents of the file represented by this entry
1172ab05e83458f35931075adca0d7b0fce4ea7cccbchrismair     *
1182ab05e83458f35931075adca0d7b0fce4ea7cccbchrismair     * @param append - true if the OutputStream should append to any existing contents false if
1192ab05e83458f35931075adca0d7b0fce4ea7cccbchrismair     *               any existing contents should be overwritten
1202ab05e83458f35931075adca0d7b0fce4ea7cccbchrismair     * @return an OutputStream
1212ab05e83458f35931075adca0d7b0fce4ea7cccbchrismair     * @throws FileSystemException - if an error occurs creating or initializing the OutputStream
1222ab05e83458f35931075adca0d7b0fce4ea7cccbchrismair     */
1232ab05e83458f35931075adca0d7b0fce4ea7cccbchrismair    public OutputStream createOutputStream(boolean append) {
1242ab05e83458f35931075adca0d7b0fce4ea7cccbchrismair        // If appending and we already have an OutputStream, then continue to use it
1252ab05e83458f35931075adca0d7b0fce4ea7cccbchrismair        if (append && out != null) {
1262ab05e83458f35931075adca0d7b0fce4ea7cccbchrismair            return out;
1272ab05e83458f35931075adca0d7b0fce4ea7cccbchrismair        }
1282ab05e83458f35931075adca0d7b0fce4ea7cccbchrismair
1292ab05e83458f35931075adca0d7b0fce4ea7cccbchrismair        out = new ByteArrayOutputStream();
1302ab05e83458f35931075adca0d7b0fce4ea7cccbchrismair        byte[] initialContents = (append) ? bytes : EMPTY;
1312ab05e83458f35931075adca0d7b0fce4ea7cccbchrismair        try {
1322ab05e83458f35931075adca0d7b0fce4ea7cccbchrismair            out.write(initialContents);
1332ab05e83458f35931075adca0d7b0fce4ea7cccbchrismair        }
1342ab05e83458f35931075adca0d7b0fce4ea7cccbchrismair        catch (IOException e) {
1352ab05e83458f35931075adca0d7b0fce4ea7cccbchrismair            throw new FileSystemException(getPath(), null, e);
1362ab05e83458f35931075adca0d7b0fce4ea7cccbchrismair        }
1372ab05e83458f35931075adca0d7b0fce4ea7cccbchrismair        return out;
1382ab05e83458f35931075adca0d7b0fce4ea7cccbchrismair    }
1392ab05e83458f35931075adca0d7b0fce4ea7cccbchrismair
1402ab05e83458f35931075adca0d7b0fce4ea7cccbchrismair    /**
1412ab05e83458f35931075adca0d7b0fce4ea7cccbchrismair     * Return a new FileSystemEntry that is a clone of this object, except having the specified path
1422ab05e83458f35931075adca0d7b0fce4ea7cccbchrismair     *
1432ab05e83458f35931075adca0d7b0fce4ea7cccbchrismair     * @param path - the new path value for the cloned file system entry
1442ab05e83458f35931075adca0d7b0fce4ea7cccbchrismair     * @return a new FileSystemEntry that has all the same values as this object except for its path
1452ab05e83458f35931075adca0d7b0fce4ea7cccbchrismair     */
1462ab05e83458f35931075adca0d7b0fce4ea7cccbchrismair    public FileSystemEntry cloneWithNewPath(String path) {
1472ab05e83458f35931075adca0d7b0fce4ea7cccbchrismair        FileEntry clone = new FileEntry(path);
1482ab05e83458f35931075adca0d7b0fce4ea7cccbchrismair        clone.setLastModified(getLastModified());
1492ab05e83458f35931075adca0d7b0fce4ea7cccbchrismair        clone.setOwner(getOwner());
1502ab05e83458f35931075adca0d7b0fce4ea7cccbchrismair        clone.setGroup(getGroup());
1512ab05e83458f35931075adca0d7b0fce4ea7cccbchrismair        clone.setPermissions(getPermissions());
1522ab05e83458f35931075adca0d7b0fce4ea7cccbchrismair        clone.setContents(getCurrentBytes());
1532ab05e83458f35931075adca0d7b0fce4ea7cccbchrismair        return clone;
1542ab05e83458f35931075adca0d7b0fce4ea7cccbchrismair    }
1552ab05e83458f35931075adca0d7b0fce4ea7cccbchrismair
1562ab05e83458f35931075adca0d7b0fce4ea7cccbchrismair    //-------------------------------------------------------------------------
1572ab05e83458f35931075adca0d7b0fce4ea7cccbchrismair    // Internal Helper Methods
1582ab05e83458f35931075adca0d7b0fce4ea7cccbchrismair    //-------------------------------------------------------------------------
1592ab05e83458f35931075adca0d7b0fce4ea7cccbchrismair
1602ab05e83458f35931075adca0d7b0fce4ea7cccbchrismair    /**
1612ab05e83458f35931075adca0d7b0fce4ea7cccbchrismair     * @return the current contents of this file entry as a byte[]
1622ab05e83458f35931075adca0d7b0fce4ea7cccbchrismair     */
1632ab05e83458f35931075adca0d7b0fce4ea7cccbchrismair    private byte[] getCurrentBytes() {
1642ab05e83458f35931075adca0d7b0fce4ea7cccbchrismair        return (out != null) ? out.toByteArray() : bytes;
1652ab05e83458f35931075adca0d7b0fce4ea7cccbchrismair    }
1662ab05e83458f35931075adca0d7b0fce4ea7cccbchrismair
1672ab05e83458f35931075adca0d7b0fce4ea7cccbchrismair    /**
1682ab05e83458f35931075adca0d7b0fce4ea7cccbchrismair     * Set the contents of the file represented by this entry
1692ab05e83458f35931075adca0d7b0fce4ea7cccbchrismair     *
1702ab05e83458f35931075adca0d7b0fce4ea7cccbchrismair     * @param contents - the byte[] used as the contents
1712ab05e83458f35931075adca0d7b0fce4ea7cccbchrismair     */
1722ab05e83458f35931075adca0d7b0fce4ea7cccbchrismair    private void setContentsInternal(byte[] contents) {
1732ab05e83458f35931075adca0d7b0fce4ea7cccbchrismair        this.bytes = contents;
1742ab05e83458f35931075adca0d7b0fce4ea7cccbchrismair
1752ab05e83458f35931075adca0d7b0fce4ea7cccbchrismair        // Get rid of any OutputStream
1762ab05e83458f35931075adca0d7b0fce4ea7cccbchrismair        this.out = null;
1772ab05e83458f35931075adca0d7b0fce4ea7cccbchrismair    }
1782ab05e83458f35931075adca0d7b0fce4ea7cccbchrismair
1792ab05e83458f35931075adca0d7b0fce4ea7cccbchrismair    /**
1802ab05e83458f35931075adca0d7b0fce4ea7cccbchrismair     * @see java.lang.Object#toString()
1812ab05e83458f35931075adca0d7b0fce4ea7cccbchrismair     */
1822ab05e83458f35931075adca0d7b0fce4ea7cccbchrismair    public String toString() {
1832ab05e83458f35931075adca0d7b0fce4ea7cccbchrismair        return "File['" + getPath() + "' size=" + getSize() + " lastModified=" + getLastModified() + " owner="
1842ab05e83458f35931075adca0d7b0fce4ea7cccbchrismair                + getOwner() + " group=" + getGroup() + " permissions=" + getPermissions() + "]";
1852ab05e83458f35931075adca0d7b0fce4ea7cccbchrismair    }
1862ab05e83458f35931075adca0d7b0fce4ea7cccbchrismair
1872ab05e83458f35931075adca0d7b0fce4ea7cccbchrismair}
188