001    /*
002     * $Revision: 14552 $ $Date: 2008-12-10 13:50:10 +0100 (Mi, 10 Dez 2008) $
003     *
004     * This file is part of ***  M y C o R e  ***
005     * See http://www.mycore.de/ for details.
006     *
007     * This program is free software; you can use it, redistribute it
008     * and / or modify it under the terms of the GNU General Public License
009     * (GPL) as published by the Free Software Foundation; either version 2
010     * of the License or (at your option) any later version.
011     *
012     * This program is distributed in the hope that it will be useful, but
013     * WITHOUT ANY WARRANTY; without even the implied warranty of
014     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
015     * GNU General Public License for more details.
016     *
017     * You should have received a copy of the GNU General Public License
018     * along with this program, in a file called gpl.txt or license.txt.
019     * If not, write to the Free Software Foundation Inc.,
020     * 59 Temple Place - Suite 330, Boston, MA  02111-1307 USA
021     */
022    
023    package org.mycore.frontend.fileupload;
024    
025    import java.io.InputStream;
026    
027    import org.apache.log4j.Logger;
028    import org.mycore.common.MCRException;
029    import org.mycore.frontend.MCRWebsiteWriteProtection;
030    
031    /**
032     * This class does the server-side of uploading files from a client browser,
033     * which runs the upload applet. This is an abstract base class that must be
034     * subclassed to implement the storage of files at the server side for miless,
035     * MyCoRe or other usages of the upload framework. Every instance of
036     * MCRUploadHandler handles one singe upload session with the applet.
037     * 
038     * @author Harald Richter
039     * @author Frank Lützenkirchen
040     * 
041     * @version $Revision: 14552 $ $Date: 2008-12-10 13:50:10 +0100 (Mi, 10 Dez 2008) $
042     * 
043     * @see MCRUploadHandlerManager
044     */
045    public abstract class MCRUploadHandler {
046        /** The logger * */
047        protected Logger logger = Logger.getLogger(MCRUploadHandler.class);
048    
049        /** The unique ID of this upload session * */
050        protected String uploadID;
051    
052        /** The url where to go after upload is finished. * */
053        protected String url;
054    
055        /** Creates a new upload handler and registers it at the handler manager * */
056        protected MCRUploadHandler() {
057            if(MCRWebsiteWriteProtection.isActive())
058                throw new MCRException("System is currently in read-only mode");
059    
060            this.uploadID = Long.toString(System.currentTimeMillis(), 36);
061            MCRUploadHandlerManager.register(this);
062        }
063    
064        /** Returns the unique ID of this upload session * */
065        public final String getID() {
066            return uploadID;
067        }
068    
069        /** Returns the url where to go after upload is finished * */
070        public String getRedirectURL() {
071            return url;
072        }
073    
074        /**
075         * Starts the upload session.
076         * 
077         * @param numFiles
078         *            the number of files that the applet will upload
079         */
080        public abstract void startUpload(int numFiles) throws Exception;
081    
082        /**
083         * Before the applet sends each file, this method is called to ask if this
084         * file should be uploaded and will be accepted by the server. The default
085         * implementation always returns true (always upload file), but subclasses
086         * should overwrite this method to decide whether the file's content must be
087         * uploaded. Decision can be based on the MD5 checksum that the applet
088         * calculated on the client side, so unchanged files do not have to be
089         * uploaded again.
090         * 
091         * @param path
092         *            the path and filename of the file
093         * @param checksum
094         *            the MD5 checksum computed at the client applet side
095         * @param length 
096         *            the length of the file in bytes (file size)
097         * @return true, if the file should be uploaded, false if the file should be
098         *         skipped
099         * @throws Exception
100         */
101        public boolean acceptFile(String path, String checksum, long length) throws Exception {
102            return true;
103        }
104    
105        /**
106         * When the applet uploads a file, this method is called so that the
107         * UploadHandler subclass can store the file on the server side.
108         * When the UploadHandler could read less than length bytes from the
109         * InputStream at the time the InputStream has no data any more, the user
110         * at the remote side canceled upload during file transfer. The UploadHandler
111         * then can decide to delete the file, but must return the number of 
112         * bytes stored. The UploadHandler can also compare the MD5 checksum calculated
113         * at the client side with its own checksum, to detect magical transfer errors.
114         * 
115         * This method is not covered by a database transaction.
116         * The implementation has to handle transactions by itself.
117         * 
118         * @param path
119         *            the path and filename of the file
120         * @param in
121         *            the inputstream to read the content of the file from
122         * @param length
123         *            the total file size as number of bytes. This may be 0,
124         *            meaning that the file is empty or the file size is not known.
125         * @param md5
126         *            the md5 checksum calculated at the client applet side. This
127         *            may be null, meaning that the md5 checksum is not known.
128         * @return 
129         *            the number of bytes that have been stored.
130         * @throws Exception
131         */
132        public abstract long receiveFile(String path, InputStream in, long length, String md5) throws Exception;
133    
134        /**
135         * When the applet finished uploading all files, this method is called so
136         * that the UploadHandler subclass can finish work and commit all saved
137         * files.
138         * 
139         * @throws Exception
140         */
141        public abstract void finishUpload() throws Exception;
142    
143        /**
144         * After the remote user canceled the upload process in the applet, 
145         * this method is called so that the UploadHandler subclass can finish 
146         * or cancel work. The implementation is optional, by default finishUpload()
147         * is called 
148         * 
149         * @throws Exception
150         */
151        public void cancelUpload() throws Exception
152        {
153          finishUpload();
154        }
155    
156        /**
157         * When the applet is closed after uploading all files, the servlet calls
158         * this method automatically to unregister this upload handler from the
159         * UploadHandlerManager.
160         */
161        public void unregister() {
162            MCRUploadHandlerManager.unregister(this.uploadID);
163        }
164    }