001/*
002 * This library is part of OpenCms -
003 * the Open Source Content Management System
004 *
005 * Copyright (c) Alkacon Software GmbH & Co. KG (http://www.alkacon.com)
006 *
007 * This library is free software; you can redistribute it and/or
008 * modify it under the terms of the GNU Lesser General Public
009 * License as published by the Free Software Foundation; either
010 * version 2.1 of the License, or (at your option) any later version.
011 *
012 * This library is distributed in the hope that it will be useful,
013 * but WITHOUT ANY WARRANTY; without even the implied warranty of
014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
015 * Lesser General Public License for more details.
016 *
017 * For further information about Alkacon Software GmbH & Co. KG, please see the
018 * company website: http://www.alkacon.com
019 *
020 * For further information about OpenCms, please see the
021 * project website: http://www.opencms.org
022 *
023 * You should have received a copy of the GNU Lesser General Public
024 * License along with this library; if not, write to the Free Software
025 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
026 */
027
028package org.opencms.file;
029
030import org.opencms.db.CmsResourceState;
031import org.opencms.util.CmsUUID;
032
033/**
034 * A file resource in the OpenCms VFS.<p>
035 *
036 * A file resource is a CmsResource that contains an additional byte
037 *  array of binary data, which is the file content.<p>
038 *
039 * A file object is not allowed to have sub-resources.<p>
040 *
041 * @since 6.0.0
042 */
043public class CmsFile extends CmsResource {
044
045    /** Serial version UID required for safe serialization. */
046    private static final long serialVersionUID = -5201022482708455620L;
047
048    /** The content of this file. */
049    private byte[] m_fileContent;
050
051    /**
052     * Constructor, creates a new file Object from the given resource with
053     * an empty byte array as file content, if the resource does not
054     * implement a file.<p>
055     *
056     * @param resource the base resource object to create a file from
057     */
058    public CmsFile(CmsResource resource) {
059
060        this(
061            resource.getStructureId(),
062            resource.getResourceId(),
063            resource.getRootPath(),
064            resource.getTypeId(),
065            resource.getFlags(),
066            resource.getProjectLastModified(),
067            resource.getState(),
068            resource.getDateCreated(),
069            resource.getUserCreated(),
070            resource.getDateLastModified(),
071            resource.getUserLastModified(),
072            resource.getDateReleased(),
073            resource.getDateExpired(),
074            resource.getSiblingCount(),
075            resource.getLength(),
076            resource.getDateContent(),
077            resource.getVersion(),
078            // if the resource already is a file, keep contents that might have been already read
079            resource instanceof CmsFile ? ((CmsFile)resource).getContents() : null);
080    }
081
082    /**
083     * Constructor, creates a new file object.<p>
084     *
085     * @param structureId the id of this resources structure record
086     * @param resourceId the id of this resources resource record
087     * @param path the filename of this resource
088     * @param type the type of this resource
089     * @param flags the flags of this resource
090     * @param projectId the project id this resource was last modified in
091     * @param state the state of this resource
092     * @param dateCreated the creation date of this resource
093     * @param userCreated the id of the user who created this resource
094     * @param dateLastModified the date of the last modification of this resource
095     * @param userLastModified the id of the user who did the last modification of this resource
096     * @param dateReleased the release date of this resource
097     * @param dateExpired the expiration date of this resource
098     * @param linkCount the count of all siblings of this resource
099     * @param length the size of the file content of this resource
100     * @param dateContent the date of the last modification of the content of this resource
101     * @param version the version number of this resource
102     * @param content the binary content data of this file
103     */
104    public CmsFile(
105        CmsUUID structureId,
106        CmsUUID resourceId,
107        String path,
108        int type,
109        int flags,
110        CmsUUID projectId,
111        CmsResourceState state,
112        long dateCreated,
113        CmsUUID userCreated,
114        long dateLastModified,
115        CmsUUID userLastModified,
116        long dateReleased,
117        long dateExpired,
118        int linkCount,
119        int length,
120        long dateContent,
121        int version,
122        byte[] content) {
123
124        super(
125            structureId,
126            resourceId,
127            path,
128            type,
129            false,
130            flags,
131            projectId,
132            state,
133            dateCreated,
134            userCreated,
135            dateLastModified,
136            userLastModified,
137            dateReleased,
138            dateExpired,
139            linkCount,
140            length,
141            dateContent,
142            version);
143
144        m_fileContent = content;
145        if (m_fileContent == null) {
146            m_fileContent = new byte[0];
147        }
148    }
149
150    /**
151     * Returns a clone of this Objects instance.<p>
152     *
153     * @return a clone of this instance
154     */
155    @Override
156    public Object clone() {
157
158        byte[] newContent = new byte[getContents().length];
159        System.arraycopy(getContents(), 0, newContent, 0, getContents().length);
160
161        CmsFile clone = new CmsFile(
162            getStructureId(),
163            getResourceId(),
164            getRootPath(),
165            getTypeId(),
166            getFlags(),
167            getProjectLastModified(),
168            getState(),
169            getDateCreated(),
170            getUserCreated(),
171            getDateLastModified(),
172            getUserLastModified(),
173            getDateReleased(),
174            getDateExpired(),
175            getSiblingCount(),
176            getLength(),
177            getDateContent(),
178            getVersion(),
179            newContent);
180
181        if (isTouched()) {
182            clone.setDateLastModified(getDateLastModified());
183        }
184
185        return clone;
186    }
187
188    /**
189     * Returns the content of this file.<p>
190     *
191     * @return the content of this file
192     */
193    public byte[] getContents() {
194
195        return m_fileContent;
196    }
197
198    /**
199     * @see org.opencms.file.CmsResource#getLength()
200     */
201    @Override
202    public int getLength() {
203
204        return m_length;
205    }
206
207    /**
208     * @see org.opencms.file.CmsResource#isFile()
209     */
210    @Override
211    public boolean isFile() {
212
213        return true;
214    }
215
216    /**
217     * @see org.opencms.file.CmsResource#isFolder()
218     */
219    @Override
220    public boolean isFolder() {
221
222        return false;
223    }
224
225    /**
226     * @see org.opencms.file.CmsResource#isTemporaryFile()
227     */
228    @Override
229    public boolean isTemporaryFile() {
230
231        return ((getFlags() & CmsResource.FLAG_TEMPFILE) > 0) || isTemporaryFileName(getName());
232    }
233
234    /**
235     * Sets the contents of this file.<p>
236     *
237     * This will also set the date content, but only if the content is already set.<p>
238     *
239     * @param value the content of this file
240     */
241    public void setContents(byte[] value) {
242
243        if (value == null) {
244            value = new byte[] {};
245        }
246        long dateContent = System.currentTimeMillis();
247        if ((m_fileContent == null) || (m_fileContent.length == 0)) {
248            dateContent = m_dateContent;
249        }
250        m_fileContent = new byte[value.length];
251        System.arraycopy(value, 0, m_fileContent, 0, value.length);
252
253        if (m_fileContent.length > 0) {
254            m_length = m_fileContent.length;
255        } else {
256            m_length = 0;
257        }
258        m_dateContent = dateContent;
259    }
260}