001    /*
002     * $Revision: 15002 $ 
003     * $Date: 2009-03-25 09:36:28 +0100 (Wed, 25 Mar 2009) $
004     *
005     * This file is part of ***  M y C o R e  ***
006     * See http://www.mycore.de/ for details.
007     *
008     * This program is free software; you can use it, redistribute it
009     * and / or modify it under the terms of the GNU General Public License
010     * (GPL) as published by the Free Software Foundation; either version 2
011     * of the License or (at your option) any later version.
012     *
013     * This program is distributed in the hope that it will be useful, but
014     * WITHOUT ANY WARRANTY; without even the implied warranty of
015     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
016     * GNU General Public License for more details.
017     *
018     * You should have received a copy of the GNU General Public License
019     * along with this program, in a file called gpl.txt or license.txt.
020     * If not, write to the Free Software Foundation Inc.,
021     * 59 Temple Place - Suite 330, Boston, MA  02111-1307 USA
022     */
023    
024    package org.mycore.datamodel.ifs2;
025    
026    import java.io.File;
027    
028    import org.apache.commons.vfs.FileObject;
029    import org.apache.commons.vfs.provider.local.LocalFile;
030    import org.apache.log4j.Logger;
031    import org.jdom.Element;
032    import org.mycore.common.MCRUtils;
033    
034    /**
035     * Represents a file stored in a file collection. This is a file that is
036     * imported from outside the system, and may be updated and modified afterwards.
037     * 
038     * @author Frank Lützenkirchen
039     * 
040     */
041    public class MCRFile extends MCRStoredNode {
042    
043        private final static Logger LOGGER = Logger.getLogger(MCRFile.class);
044    
045        /**
046         * The md5 checksum of the empty file
047         */
048        public final static String MD5_OF_EMPTY_FILE = "d41d8cd98f00b204e9800998ecf8427e";
049    
050        /**
051         * Returns a MCRFile object representing an existing file already stored in
052         * the store.
053         * 
054         * @param parent
055         *            the parent directory containing this file
056         * @param fo
057         *            the file in the local underlying filesystem storing this file
058         */
059        protected MCRFile(MCRDirectory parent, FileObject fo, Element data) throws Exception {
060            super(parent, fo, data);
061        }
062    
063        /**
064         * Creates a new MCRFile that does not exist yet
065         * 
066         * @param parent
067         *            the parent directory
068         * @param name
069         *            the file name
070         */
071        protected MCRFile(MCRDirectory parent, String name) throws Exception {
072            super(parent, name, "file");
073            fo.createFile();
074            data.setAttribute("md5", MCRFile.MD5_OF_EMPTY_FILE);
075            getRoot().saveAdditionalData();
076        }
077    
078        /**
079         * Returns a MCRVirtualNode contained in this file as a child. A file that
080         * is a container, like zip or tar, may contain other files as children.
081         */
082        protected MCRVirtualNode buildChildNode(FileObject fo) throws Exception {
083            return new MCRVirtualNode(this, fo);
084        }
085    
086        /**
087         * Returns the md5 checksum of the file's content.
088         * 
089         * @return the md5 checksum of the file's content.
090         */
091        public String getMD5() {
092            return data.getAttributeValue("md5");
093        }
094    
095        /**
096         * Returns the file name extension, which is the part after the last dot in
097         * the filename.
098         * 
099         * @return the file extension, or the empty string if the file name does not
100         *         have an extension
101         */
102        public String getExtension() {
103            String name = this.getName();
104            int pos = name.lastIndexOf(".");
105            return (pos == -1 ? "" : name.substring(pos + 1));
106        }
107    
108        /**
109         * Sets the content of this file.
110         * 
111         * @param content
112         *            the content to be read
113         * @return the MD5 checksum of the stored content
114         */
115        public String setContent(MCRContent source) throws Exception {
116            MCRContentInputStream cis = source.getContentInputStream();
117            source.sendTo(fo);
118            String md5 = cis.getMD5String();
119            data.setAttribute("md5", md5);
120            getRoot().saveAdditionalData();
121            return md5;
122        }
123    
124        /**
125         * Returns the local java.io.File representing this stored file. Be careful
126         * to use this only for reading data, do never modify directly!
127         * 
128         * @return the file in the local filesystem representing this file
129         */
130        public File getLocalFile() throws Exception {
131            if (fo instanceof LocalFile)
132                return new File(fo.getURL().getPath());
133            else
134                return null;
135        }
136    
137        /**
138         * Repairs additional metadata of this file and all its children
139         */
140        void repairMetadata() throws Exception {
141            data.setName("file");
142            data.setAttribute("name", getName());
143            data.removeChildren("file");
144            data.removeChildren("directory");
145            MCRContentInputStream cis = getContent().getContentInputStream();
146            MCRUtils.copyStream(cis, null);
147            cis.close();
148            String md5 = cis.getMD5String();
149            if (!md5.equals(data.getAttributeValue("md5"))) {
150                LOGGER.warn("Fixed MD5 of " + getPath() + " to " + md5);
151                data.setAttribute("md5", md5);
152            }
153        }
154    }