source: 3thparty/jupload/src/main/java/wjhk/jupload2/upload/UploadFileData.java @ 3951

Revision 3951, 11.6 KB checked in by alexandrecorreia, 13 years ago (diff)

Ticket #1709 - Adicao de codigo fonte java do componente jupload

Line 
1//
2// $Id: UploadFileData.java 1360 2010-06-28 11:35:55Z etienne_sf $
3//
4// jupload - A file upload applet.
5// Copyright 2007 The JUpload Team
6//
7// Created: 2006-11-20
8// Creator: etienne_sf
9// Last modified: $Date: 2010-06-28 08:35:55 -0300 (Seg, 28 Jun 2010) $
10//
11// This program is free software; you can redistribute it and/or modify it under
12// the terms of the GNU General Public License as published by the Free Software
13// Foundation; either version 2 of the License, or (at your option) any later
14// version. This program is distributed in the hope that it will be useful, but
15// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
17// details. You should have received a copy of the GNU General Public License
18// along with this program; if not, write to the Free Software Foundation, Inc.,
19// 675 Mass Ave, Cambridge, MA 02139, USA.
20
21package wjhk.jupload2.upload;
22
23import java.io.File;
24import java.io.IOException;
25import java.io.InputStream;
26import java.io.OutputStream;
27import java.util.Date;
28
29import wjhk.jupload2.exception.JUploadException;
30import wjhk.jupload2.exception.JUploadIOException;
31import wjhk.jupload2.exception.JUploadInterrupted;
32import wjhk.jupload2.filedata.FileData;
33import wjhk.jupload2.policies.UploadPolicy;
34import wjhk.jupload2.upload.helper.ByteArrayEncoder;
35
36/**
37 * This class implements the FileData interface, and is responsible to do the
38 * actual upload of the files.
39 *
40 * @author etienne_sf
41 */
42public class UploadFileData implements FileData {
43
44        /**
45         * The {@link FileData} instance that contains all information about the
46         * file to upload.
47         */
48        private FileData fileData = null;
49
50        /**
51         * The value of the fileData InputStream. It's main use is to allow chunk
52         * upload, to reuse the previous InputStream, that is: each chunk will start
53         * reading the stream where the previous one stopped.
54         */
55        InputStream uploadInputStream = null;
56
57        /**
58         * Indicates the position of the file in the current upload (from 0 to
59         * max-1). It is mainly used by the
60         * ProgressBarManager.updateUploadProgressBarText() method, to display the
61         * upload status to the user.
62         */
63        int numOfFileInCurrentUpload = -1;
64
65        // FIXME numOfFileInCurrentUpload should be from 1 to max
66
67        /**
68         * Instance of the fileUploadManagerThread. This allow this class to send
69         * feedback to the thread.
70         *
71         * @see FileUploadManagerThread#nbBytesUploaded(long)
72         */
73        private FileUploadManagerThread fileUploadManagerThread = null;
74
75        /**
76         * The number of bytes to upload, for this file (without the head and tail
77         * defined for the HTTP multipart body).
78         */
79        private long uploadRemainingLength = -1;
80
81        /**
82         * The current {@link UploadPolicy}
83         */
84        private UploadPolicy uploadPolicy = null;
85
86        private final static int BUFLEN = 4096;
87
88        /**
89         * This field is no more static, as we could decide to upload two files
90         * simultaneously.
91         */
92        private final byte readBuffer[] = new byte[BUFLEN];
93
94        // /////////////////////////////////////////////////////////////////////////////////////////////////////
95        // //////////////////////////////////// CONSTRUCTOR
96        // ///////////////////////////////////////////
97        // /////////////////////////////////////////////////////////////////////////////////////////////////////
98
99        /**
100         * Standard constructor for the UploadFileData class.
101         *
102         * @param fileDataParam
103         *            The file data the this instance must transmist.
104         * @param numOfFileInCurrentUpload
105         * @param fileUploadManagerThreadParam
106         *            The current instance of {@link FileUploadThread}
107         * @param uploadPolicyParam
108         *            The current upload policy, instance of {@link UploadPolicy}
109         */
110        public UploadFileData(FileData fileDataParam, int numOfFileInCurrentUpload,
111                        FileUploadManagerThread fileUploadManagerThreadParam,
112                        UploadPolicy uploadPolicyParam) {
113                if (fileDataParam == null && !(this instanceof UploadFileDataPoisonned)) {
114                        throw new NullPointerException(
115                                        "fileData is null in UploadFileData(FileData, FileUploadManagerThread, UploadPolicy) constructor");
116                }
117                this.fileData = fileDataParam;
118                this.numOfFileInCurrentUpload = numOfFileInCurrentUpload;
119                this.fileUploadManagerThread = fileUploadManagerThreadParam;
120                this.uploadPolicy = uploadPolicyParam;
121        }
122
123        /**
124         * This particular constructor is posted by the
125         * {@link FilePreparationThread} in the preparedFileQueue to indicate that
126         * the last file has been prepared.
127         *
128         * @param poisonned
129         *            This parameter is here to avoid this constructor to be the
130         *            default constructor. Its value must be 'true'.
131         */
132        public UploadFileData(boolean poisonned) {
133                if (!poisonned) {
134                        throw new IllegalArgumentException(
135                                        "poisonned must be true in UploadFileData(boolean) constructor");
136                }
137        }
138
139        /**
140         * Get the number of files that are still to upload. It is initialized at
141         * the creation of the file, by a call to the
142         * {@link FileData#getUploadLength()}. <BR>
143         * <B>Note:</B> When the upload for this file is finish and you want to send
144         * it again (for instance the upload failed, and you want to do a retry),
145         * you should not reuse this instance, but, instead, create a new
146         * UploadFileData instance.
147         *
148         * @return Number of bytes still to upload.
149         * @see #getInputStream()
150         */
151        long getRemainingLength() {
152                return this.uploadRemainingLength;
153        }
154
155        /**
156         * This methods writes the file data (see {@link FileData#getInputStream()}
157         * to the given outputStream (the output toward the HTTP server).
158         *
159         * @param outputStream
160         *            The stream on which the data is to be written.
161         * @param amount
162         *            The number of bytes to write.
163         * @throws JUploadException
164         *             if an I/O error occurs.
165         * @throws JUploadInterrupted
166         *             Thrown when an interruption of the thread is detected.
167         */
168        void uploadFile(OutputStream outputStream, long amount)
169                        throws JUploadException, JUploadInterrupted {
170                this.uploadPolicy.displayDebug("in UploadFileData.uploadFile (amount:"
171                                + amount + ", getUploadLength(): " + getUploadLength() + ")",
172                                30);
173
174                // getInputStream will put a new fileInput in the inputStream attribute,
175                // or leave it unchanged if it is not null.
176                InputStream inputStream = getInputStream();
177
178                while (amount > 0 && !this.fileUploadManagerThread.isUploadFinished()) {
179                        // Are we interrupted ?
180                        if (Thread.interrupted()) {
181                                throw new JUploadInterrupted(getClass().getName()
182                                                + ".uploadFile [" + this.getFileName() + "]",
183                                                this.uploadPolicy);
184                        }
185
186                        int toread = (amount > BUFLEN) ? BUFLEN : (int) amount;
187                        int towrite = 0;
188
189                        try {
190                                towrite = inputStream.read(this.readBuffer, 0, toread);
191                        } catch (IOException e) {
192                                throw new JUploadIOException(e);
193                        }
194                        if (towrite > 0) {
195                                try {
196                                        outputStream.write(this.readBuffer, 0, towrite);
197                                        this.fileUploadManagerThread.nbBytesUploaded(towrite, this);
198                                        amount -= towrite;
199                                        this.uploadRemainingLength -= towrite;
200
201                                        // For debug reason, I may need to simulate upload, that are
202                                        // on a real network. We then slow down the upload. This can
203                                        // occurs only when given a 'high' debugLevel (higher than
204                                        // what can be set with the applet GUI.
205                                        if (this.uploadPolicy.getDebugLevel() > 100) {
206                                                try {
207                                                        Thread.sleep(20);
208                                                } catch (InterruptedException e) {
209                                                        // Nothing to do. We'll just take a look at the loop
210                                                        // condition.
211                                                }
212                                        }
213                                } catch (IOException ioe) {
214                                        throw new JUploadIOException(this.getClass().getName()
215                                                        + ".uploadFile()", ioe);
216                                } catch (Exception e) {
217                                        // When the user may not override an existing file, I got a
218                                        // NullPointerException. Let's trap all errors here.
219                                        throw new JUploadException(
220                                                        this.getClass().getName()
221                                                                        + ".uploadFile()  (check the user permission on the server)",
222                                                        e);
223                                }
224                        }
225                }// while
226        }
227
228        /**
229         * Just transmit to {@link FileData#afterUpload()}.
230         *
231         * @see FileData#afterUpload()
232         */
233        public void afterUpload() {
234                // Transmission to the 'real' FileData
235                this.fileData.afterUpload();
236        }
237
238        /** {@inheritDoc} */
239        public void appendFileProperties(ByteArrayEncoder bae, int index)
240                        throws JUploadIOException {
241                this.fileData.appendFileProperties(bae, index);
242        }
243
244        /** {@inheritDoc} */
245        public void beforeUpload() throws JUploadException {
246                this.fileData.beforeUpload();
247
248                // Calculation of some internal variables.
249                this.uploadRemainingLength = this.fileData.getUploadLength();
250        }
251
252        /** {@inheritDoc} */
253        public boolean canRead() {
254                return this.fileData.canRead();
255        }
256
257        /** {@inheritDoc} */
258        public String getDirectory() {
259                return this.fileData.getDirectory();
260        }
261
262        /** {@inheritDoc} */
263        public File getFile() {
264                return this.fileData.getFile();
265        }
266
267        /** {@inheritDoc} */
268        public String getFileExtension() {
269                return this.fileData.getFileExtension();
270        }
271
272        /** {@inheritDoc} */
273        public long getFileLength() {
274                return this.fileData.getFileLength();
275        }
276
277        /** {@inheritDoc} */
278        public String getFileName() {
279                return this.fileData.getFileName();
280        }
281
282        /** {@inheritDoc} */
283        public InputStream getInputStream() throws JUploadException {
284                if (this.uploadInputStream == null) {
285                        this.uploadInputStream = this.fileData.getInputStream();
286                }
287                return this.uploadInputStream;
288        }
289
290        /** {@inheritDoc} */
291        public Date getLastModified() {
292                return this.fileData.getLastModified();
293        }
294
295        /** {@inheritDoc} */
296        public String getMD5() throws JUploadException {
297                return this.fileData.getMD5();
298        }
299
300        /** {@inheritDoc} */
301        public String getMimeType() {
302                return this.fileData.getMimeType();
303        }
304
305        /** {@inheritDoc} */
306        public String getRelativeDir() {
307                return this.fileData.getRelativeDir();
308        }
309
310        /**
311         * Retrieves the file name, that should be used in the server application.
312         * Default is to send the original filename.
313         *
314         * @param index
315         *            The index of this file in the current request to the server.
316         * @return The real file name. Not used in FTP upload.
317         * @throws JUploadException
318         *             Thrown when an error occurs.
319         * @see UploadPolicy#getUploadFilename(FileData, int)
320         */
321        public String getUploadFilename(int index) throws JUploadException {
322                return this.uploadPolicy.getUploadFilename(this.fileData, index);
323        }
324
325        /**
326         * Retrieves the upload file name, that should be sent to the server. It's
327         * the technical name used to retrieve the file content. Default is File0,
328         * File1... This method just calls the
329         * {@link UploadPolicy#getUploadFilename(FileData, int)} method.
330         *
331         * @param index
332         *            The index of this file in the current request to the server.
333         * @return The technical upload file name. Not used in FTP upload.
334         * @throws JUploadException
335         * @see UploadPolicy#getUploadName(FileData, int)
336         */
337        public String getUploadName(int index) throws JUploadException {
338                return this.uploadPolicy.getUploadName(this.fileData, index);
339        }
340
341        /**
342         * This methods stores locally the upload length. So, on the contrary of the
343         * {@link FileData} interface, this method may be called after
344         * {@link #afterUpload()}, at one condition: that it has been called once
345         * before {@link #afterUpload()} is called.
346         *
347         * @see FileData#getUploadLength()
348         */
349        public long getUploadLength() {
350                return this.fileData.getUploadLength();
351        }
352
353        /** {@inheritDoc} */
354        public boolean isPreparedForUpload() {
355                return this.fileData.isPreparedForUpload();
356        }
357
358        /**
359         * @return the poisonned status. Returns always false, as this instance is a
360         *         true one. false indicates the 'End Of Queue' marker in the
361         *         preparedFileQueue, which is not the case here
362         * @see UploadFileDataPoisonned
363         */
364        public boolean isPoisonned() {
365                return false;
366        }
367
368        /**
369         * @return the numOfFileInCurrentUpload
370         */
371        public int getNumOfFileInCurrentUpload() {
372                return numOfFileInCurrentUpload;
373        }
374
375}
Note: See TracBrowser for help on using the repository browser.